2015-05-29 8 views
6

पर लिखने के दौरान SIGINT सिग्नल गिरा दिया गया है मेरे पास एक प्रोग्राम है जो pcap_dump फ़ंक्शन का उपयोग करके stpout के साथ libpcap का उपयोग करके एकत्रित पॅक डेटा को डंप करता है, जिसमें FILE * के रूप में stdout है। SIGINT पर आवश्यक क्लीनअप का एक छोटा सा हिस्सा है, इसलिए मैं सिग्नेशन() के साथ इसे संभालता हूं। जब एक खोल से निष्पादित किया जाता है तो यह अच्छी तरह से काम करता है।एक पाइप

हालांकि, इस कार्यक्रम का उद्देश्य किसी अन्य कार्यक्रम द्वारा बुलाया जाना है, जो काम नहीं कर रहा है। यह "कॉलर" प्रोग्राम एक पाइप(), फिर एक कांटा() कहता है, तो बच्चे के stdout फ़ाइल डिस्क्रिप्टर बंद हो जाता है, और पाइप के लिखने के अंत के साथ बदल दिया जाता है। अंत में, उपरोक्त पॅक प्रोग्राम बाल प्रक्रिया में निष्पादित किया जाता है। इस तरह पाइप डेटा को पाइप के माध्यम से कॉलर प्रोग्राम में लिखा जाता है। यह अच्छी तरह से काम करता है। हालांकि, जब मैं पाइप को लिखते समय बच्चे की प्रक्रिया में एक सिगिनट भेजता हूं (ठीक है, तो पॅक प्रोग्राम अपने लेखन को stdout पर सोचता है, लेकिन इसकी फ़ाइल डिस्क्रिप्टर बदल दी गई थी), संकेत गिरा दिया जाता है, और सिग्नल हैंडलर फ़ंक्शन कभी भी बुलाया नहीं जाता है।

वह क्यों है? अगर मैं stderr या फ़ाइल में पाप डेटा लिखता हूं, तो SIGINT कभी नहीं छोड़ा जाता है। केवल जब पाइप को लिखते हैं।

यहाँ है कि कैसे हम पाइप/कांटा सेट कर रहे हैं/निष्पादित करें:

kill(pid, SIGINT); 

बच्चे में, हमारे pcap_loop के लिए कॉलबैक फ़ंक्शन:

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]); 
} 

उसके बाद बच्चे उपयोग हम को मारने के लिए() के रूप में सरल हो सकता है:

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 
} 

और हम मूल रूप से हमेशा सिगिनट छोड़ देंगे। रास्ते से कब्जा करने के लिए बहुत सारे पैकेट हैं, इसलिए यह कॉलबैक फ़ंक्शन में लगभग हमेशा के लिए यह सुरक्षित है।

लेकिन अगर हम से

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

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

को बदल तो सब कुछ फिर से hunky-dory हो जाता है।

एक पाइप को लिखने के दौरान हमारे SIGINT को क्यों गिरा दिया जाता है?

मदद के लिए धन्यवाद।

संपादित करें: बच्चे के सिगिनट हैंडलर को कभी भी बुलाया नहीं जा रहा था, लेकिन कारण वास्तव में बच्चे में कोई समस्या नहीं थी, यह माता-पिता में एक समस्या थी। मैं की तरह बच्चे को मारने के लिए इस्तेमाल किया:

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

और यह हमारी SIGCHLD हैंडलर हुआ करता था:

void handlesigchild(int sig) { 
    wait(); 

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

तो, स्वीकार किए जाते हैं जवाब में वर्णित है, तुरंत पाइप बंद करने बाहर निकलने के लिए हमारे बच्चे पैदा कर रहा था SIGINT को संभालने से पहले एक सिगिप के साथ। हमने अभी सिगचल्ड हैंडलर को क्लोज़ (पाइपएफडी) ले जाया है और यह अब काम करता है।

+0

स्टैक ओवरफ़्लो में आपका स्वागत है। कृपया जल्द ही [के बारे में] पृष्ठ पढ़ें। आम तौर पर, आपको सी या सी ++ को भाषा टैग के रूप में चुनना चाहिए और दोनों नहीं - क्योंकि सी ++ के लिए उपयुक्त समाधान आमतौर पर सी के लिए उपयुक्त नहीं होते हैं, और इसके विपरीत अक्सर मामला भी होता है। –

+0

'स्ट्रेस' शो के तहत प्रक्रियाओं को क्या चल रहा है? (मान लीजिए लिनक्स आपका ओएस है) इसके अलावा, अपना सिग्नल-हैंडलिंग कोड पोस्ट करें। –

+0

ऐसा इसलिए हो सकता है क्योंकि आपका सिग्नल हैंडलर (मानते हुए कि आपके पास है) पाइप को बंद नहीं करता है (जो वर्तमान में उपयोग में है)? शायद एक कोशिश के लायक है। – Addison

उत्तर

2

आप यह जानने के लिए पर्याप्त कोड नहीं दिखा रहे हैं कि क्या हो रहा है। आपको हमेशा SSCCE बनाने का प्रयास करना चाहिए और यदि आप चाहते हैं कि लोग आपके कार्यक्रम पर टिप्पणी करने में सक्षम हों।

सर्वश्रेष्ठ अनुमान: आपके माता-पिता सिग्नल भेजने के बाद बाहर निकलते हैं, पाइप के पढ़ने के अंत को बंद करते हैं।एसआईजीआईएनटी को संभालने का मौका मिलने से पहले क्लाइंट तुरंत सिगिप के साथ बाहर निकलने का कारण बनता है। SIGPIPE पर भी अपनी सफाई करने का प्रयास करें, या सिगिप को अनदेखा करें।

+0

बहुत बढ़िया, धन्यवाद। हमारे माता-पिता वास्तव में बाहर नहीं निकलते हैं, लेकिन यह बच्चे को सिगिनट भेजने के तुरंत बाद पाइप बंद कर रहा था, जिसका एक ही प्रभाव था। क्या हो रहा था यह दिखाने के लिए मैं मूल पोस्ट अपडेट करूंगा। – rexroni