2015-05-29 14 views
6

Libapap kullanılarak pcap verileri toplanarak pcap_dump işlevi kullanılarak stdout kullanarak, FILE * olarak stdout ile programlanan bir programım var. SIGINT üzerinde biraz temizlik gerekiyor, bu yüzden sigaction() ile başa çıkıyorum. Bu bir kabuktan yürütüldüğünde güzel çalışır. Bununla birlikte, bu programın işe yaramadığı görülen başka bir program tarafından çağrılması amaçlanmıştır. Bu "arayan" program bir boru(), sonra bir fork() çağırır, daha sonra çocuğun stdout dosya tanımlayıcısı kapanır ve borunun yazma ucuyla değiştirilir. Son olarak, daha önce bahsedilen pcap programı çocuk işleminde yürütülür. Bu sayede pcap verileri, arayan programa boru yoluyla yazılır. Bu da güzel çalışıyor. Ancak, boruya yazarken çocuk sürecine bir SIGINT yolladığımda (iyi, pcap programı yazımını stdout olarak düşünür, fakat dosya tanıtıcı değiştirildi), sinyal düşüyor ve sinyal işleyici işlevi asla hiç çağırılmaz.SIGINT sinyali bir boruya yazılırken düşüyor

Neden? Eğer pcap verilerini stderr veya bir dosyaya yazarsam, SIGINT asla düşmez. Sadece boruya yazarken. Biz boru/çatal kuruyorlar nasıl İşte

olduğunu/yürütün: çocukta

kill(pid, SIGINT); 

, bizim pcap_loop için geri arama işlevi:

int fd[2]; 

//Create pipe 
pipe(fd); 

pid = fork(); //We forked a child 

if(pid == 0){ //We are the child now 

    close(1); //close child's stdout 

    dup(fd[1]); //duplicate child's stdout to the write end of the pipe 

    close(fd[0]); //close unused file descriptors 
    close(fd[1]); 

    //Load the new program 
    execlp("./collectraw", "collectraw", NULL); 

    perror("Exec"); 
    exit(127); //Should never get called but we leave it so the child 
    //doesnt accidently keep executing 
} 
else{ //We are the parent 

    //Set up the file descriptors 
    close(fd[1]); 
} 

sonra kullandığımız çocuğu öldürmek() kadar basit olabilir:

void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet){ 
    write(1,"<pretend this is like a thousand zeros>",1000); //write to stdout, which is really a pipe 
} 

Ve temelde her zaman SIGINT düşecek. Bu arada çekilecek birçok paket var, bu yüzden neredeyse her zaman geri arama işlevinde olduğunu varsaymak oldukça güvenli.

biz

write(1,...); //write to stdout, which is really a pipe 

den

write(2,...); //write to stderr, or writing to a file would work too 

geçtiğinizdeyse Ama sonra her şey yine kıyak olur.

SIGINT'imiz bir yazı yazılırken neden boruya düşüyor?

Yardımlarınız için teşekkürler.

DÜZENLEME: Çocuğun SIGINT işleyicisine hiç çağrılmadı, ama neden çocukta gerçekten bir sorun değildi, ebeveynte bir problemdi. Ben gibi çocuğu öldürmek için kullanılan:

if(kill(pid, SIGINT) == -1){ 
    perror("Could not kill child"); 
} 
close(pipefd); 
fprintf(stdout, "Successfully killed child\n"); 

Ve bu bizim SIGCHLD işleyici olarak kullanılan: hemen boruyu kapatarak kabul edilen yanıt açıklandığı gibi

void handlesigchild(int sig) { 
    wait(); 

    printf("Cleaned up a child\n"); 
} 

Yani, çıkmak için çocuğumuzu neden oldu SIGINT'in ele alınmasından önce bir SIGPIPE ile. Yakın zamanda (pipefd) SIGCHLD işleyicisine taşındık ve şimdi çalışıyor.

+0

Yığın Taşması'na Hoş Geldiniz. Lütfen yakında [Hakkında] sayfasını okuyun. Genel olarak, C ya da C++ dil etiketi olarak seçmelisiniz ve her ikisini de değil - çünkü C++ için uygun olan çözümler genellikle C için uygun değildir ve tersi de çoğu zaman geçerlidir. –

+0

"Strace" altında işlemler nasıl çalışıyor? (Linux'un işletim sisteminiz olduğunu varsayarsak) Ayrıca, sinyal işleme kodunuzu gönderin. –

+0

Bunun nedeni, sinyal tutucunuzun (varsayacağınız varsayılarak) boruyu kapatmıyor olması (şu anda kullanımda olan)? Belki de denemeye değer. – Addison

cevap

2

Neler olup bittiğini öğrenmek için kodunuzu yeterince göstermiyorsunuz. Her zaman bir SSCCE oluşturmayı denemelisiniz ve insanların programınıza yorum yapabilmelerini istiyorsanız, bunu göndermelisiniz.

En iyi tahmin: Ebeveyn, sinyali okuduktan sonra, borunun okunan sonunu kapattıktan sonra çıkar.Bu, müşterinin SIGINT ile başa çıkma şansı elde etmeden önce bir SIGPIPE ile hemen çıkmasına neden olur. SIGPIPE'de de temizlemeyi deneyin ya da SIGPIPE'yi yoksayın.

+0

Harika, teşekkürler. Bizim ebeveynimiz aslında çıkmıyor, fakat SIGINT'i aynı etkiye sahip olan çocuğa gönderdikten hemen sonra boruyu kapatıyordu. Neler olduğunu görmek için orijinal gönderiyi güncelleyeceğim. – rexroni

İlgili konular