2010-11-22 7 views
29

मेरे पास एक उपयोगकर्ता परिभाषित विनाशक के साथ एक कक्षा है। यदि कक्षा को प्रारंभ में तत्काल प्रारंभ किया गया था, और फिर प्रोग्राम चलाए जाने पर एसआईजीआईएनटी जारी किया जाता है (यूनिक्स में CTRL + C का उपयोग करके), क्या विनाशक को बुलाया जाएगा? एसआईजीएसटीपी (यूनिक्स में CTRL + Z) के लिए व्यवहार क्या है?क्या विनाशक कहा जाता है अगर सिगिनट या सिगस्ट जारी किया गया है?

उत्तर

24

नहीं, डिफ़ॉल्ट रूप से, अधिकांश संकेत आपके प्रोग्राम के तत्काल, असामान्य निकास का कारण बनते हैं।

हालांकि, आप अधिकतर सिग्नल के लिए डिफ़ॉल्ट व्यवहार को आसानी से बदल सकते हैं।

इस कोड को दिखाता है कि सभी सामान्य विनाशकर्ता बुला सहित एक संकेत बाहर निकलने के अपने कार्यक्रम बनाने के लिए सामान्य रूप से,:

#include <iostream> 
#include <signal.h> 
#include <unistd.h> 
#include <cstring> 
#include <atomic> 

std::atomic<bool> quit(false); // signal flag 

void got_signal(int) 
{ 
    quit.store(true); 
} 

class Foo 
{ 
public: 
    ~Foo() { std::cout << "destructor\n"; } 
}; 

int main(void) 
{ 
    struct sigaction sa; 
    memset(&sa, 0, sizeof(sa)); 
    sa.sa_handler = got_signal; 
    sigfillset(&sa.sa_mask); 
    sigaction(SIGINT,&sa,NULL); 

    Foo foo; // needs destruction before exit 
    while (true) 
    { 
     // do real work here... 
     sleep(1); 
     if(quit.load()) break; // exit normally after SIGINT 
    } 
    return 0; 
} 

आप इस कार्यक्रम और प्रेस नियंत्रण सी चलाते हैं, तो आप शब्द "नाशक" देखना चाहिए मुद्रित। सावधान रहें कि आपके सिग्नल हैंडलर फ़ंक्शंस (got_signal) को ध्वज सेट करने और चुपचाप लौटने के अलावा, शायद ही कभी कोई काम करना चाहिए, जब तक आप वास्तव में नहीं जानते कि आप क्या कर रहे हैं।

अधिकतर सिग्नल ऊपर दिखाए गए अनुसार पकड़ने योग्य हैं, लेकिन सिगकिल नहीं, आपके पास इसका कोई नियंत्रण नहीं है क्योंकि सिगकिल एक रनवे प्रक्रिया को मारने के लिए आखिरी-खाई विधि है, और सिगस्टॉप नहीं है जो उपयोगकर्ता को प्रक्रिया को ठंडा करने की अनुमति देता है। ध्यान दें कि यदि आप वांछित हैं तो आप SIGTSTP (नियंत्रण-जेड) को पकड़ सकते हैं, लेकिन आपको सिग्नल में केवल एक ही रूचि विनाशकारी व्यवहार है, क्योंकि अंततः नियंत्रण के बाद-जेड प्रक्रिया जागृत हो जाएगी, चलती रहेगी, और प्रभाव में सभी विनाशकों के साथ सामान्य रूप से बाहर निकलेंगे।

+5

आईआईआरसी, 'छोड़ने' का सही प्रकार 'अस्थिर std :: sig_atomic_t' होना चाहिए। उस उद्देश्य के लिए 'बूल' का उपयोग करने के लिए यह यूबी है। – MSalters

+0

@MSalters: ठीक है, मुझे sigfillset() को सिग्नेशन() से पहले कॉल करना चाहिए था, जो शायद sig_atomic_t से भी बेहतर होगा। सिग्नल हैंडलर को बाधित करने से अतिरिक्त सिग्नल अवरुद्ध होने पर एक बूल का उपयोग करना अधिक परिचित और पूरी तरह से सुरक्षित है। मेरा उदाहरण कोड संपादित, धन्यवाद। –

+2

मुझे वास्तव में इस कोड के साथ एक त्रुटि मिलती है: 'quit = false' लाइन के लिए हटाए गए फ़ंक्शन का उपयोग करें। आपको 'quit = false' के बजाय 'छोड़ना (झूठा)' करना होगा। यह भी ध्यान देने योग्य है कि यह कोड विंडोज पर काम नहीं करता है; आपको 'SetConsoleCtrlHandler() 'का उपयोग करना होगा। – Timmmm

8

यदि आप इन संकेतों को स्वयं संभाल नहीं पाते हैं, तो नहीं, विनाशकों को बुलाया नहीं जाता है। हालांकि, ऑपरेटिंग सिस्टम आपके प्रोग्राम को समाप्त होने पर उपयोग किए जाने वाले किसी भी संसाधन को पुनः प्राप्त करेगा।

यदि आप स्वयं संकेतों को संभालना चाहते हैं, तो sigaction मानक लाइब्रेरी फ़ंक्शन को देखने पर विचार करें।

+3

ओएस द्वारा स्वामित्व वाले संसाधनों को पुनः प्राप्त करना। एक आवेदन के भीतर अन्य अन्य संसाधन भी होते हैं और वे आमतौर पर इस तरह से लपेटे जाते हैं कि उन्हें सही ढंग से बंद करना आवश्यक है (अन्यथा आपको दूषित संसाधन मिलते हैं (जैसे फ़ाइल ठीक से समाप्त नहीं होती है))। –

6

की यह कोशिश करते हैं:

#include <stdio.h> 
#include <unistd.h> 

class Foo { 
public: 
    Foo() {}; 
    ~Foo() { printf("Yay!\n"); } 
} bar; 

int main(int argc, char **argv) { 
    sleep(5); 
} 

और फिर:

$ g++ -o test ./test.cc 
$ ./test 
^C 
$ ./test 
Yay! 

तो मैं नहीं डर लग रहा है, तो आप इसे पकड़ने के लिए होगा।

SIGSTOP के लिए, इसे पकड़ा नहीं जा सकता है, और SIGCONT भेजे जाने तक प्रक्रिया को रोक देता है।

संबंधित मुद्दे