2015-10-21 5 views
6

इस प्रश्न को लिनक्स से दिमाग में पूछा जाता है। जीसीसी कंपाइलर का उपयोग किया जाता है।यदि मैं SIGSEGV को पकड़ता हूं और सिग्नल हैंडलर एक और SIGSEGV का कारण बनता है तो क्या होता है?

एसआईजीएसईजीवी (मेरा मतलब है कि आमतौर पर एसआईजीएसईजीवी का कारण बनने वाला उल्लंघन) सिग्नल हैंडलर के भीतर होता है जिसका उद्देश्य एसआईजीएसईजीवी को पकड़ना था? चर्चा के लिए कोड उदाहरण:

/* In main or whatever */ 
{ 
    struct sigaction sa = {}; /* initialised to all zero (I vote for GCC style breach of standard here) */ 
    sa.sa_handler = DisasterSignals; 
    sa.sa_flags = SA_RESETHAND | SA_NODEFER; /* To have or have not */ 
    sigaction(SIGSEGV, &sa, NULL); 
} 

static void DisasterSignals(int signal) 
{ 
    /* We cannot save the situation, the purpose of catching the signal is 
    only to do something clever to aid debugging before we go. */ 

    /* Q: What if we segfault in here?? */ 

    abort(); /* This should give us the expected core dump (if we survive to this point) */ 
} 

कल्पना करें, बिंदु "क्यू" में, एक अपमानजनक मशीन निर्देश है।

1) SA_RESETHAND | SA_NODEFER के बिना: यह सिस्टम को तार्किक जाल में डालता है: "क्यू" पर, SIGSEGV उत्पन्न होना चाहिए। लेकिन सिग्नल हैंडलर (डिफ़ॉल्ट सिग्नेक्शन व्यवहार) में SIGSEGV अवरुद्ध है। निष्पादन कैसे जारी रख सकता है? क्या यह स्थिर हो जाएगा? क्या यह अपमानजनक निर्देश से पहले कूद जाएगा (मुझे नहीं लगता)?

2) SA_RESETHAND | SA_NODEFER के साथ: मुझे लगता है कि इस मामले में प्रोग्राम "सामान्य" फैशन में दुर्घटनाग्रस्त हो जाएगा जब SIGSEGV दोहराया जाएगा।

3) केवल SA_NODEFER के साथ: मुझे लगता है कि इस मामले में सिग्नल हैंडलर को फिर से बुलाया जाता है जब SIGSEGV दोहराया जाता है; अगर SIGSEGV हमेशा दोहराया जाता है, तो हम ढेर अतिप्रवाह होने तक फ्रीज प्राप्त करते हैं, और फिर क्या।

+3

Quis custodiet ipsos custodes? –

+1

आपको सिग्नल हैंडलर में केवल पुनर्वित्त कार्यों को कॉल करना होगा। – edmz

+0

क्या होता है जब एक कवच छेड़छाड़ करने वाला कवच कवच को तोड़ देता है? – mah

उत्तर

3

डिफ़ॉल्ट रूप से, जबकि सिग्नल को संभाला जा रहा है, इसे मुखौटा किया जाता है, इसलिए इसे पुनरावर्ती रूप से ट्रिगर नहीं किया जा सकता है। नकाबपोश संकेत (0 आदि द्वारा अवैध स्मृति का उपयोग, segfault, प्रभाग) प्रोग्राम निष्पादन से शुरू हो रहा है, तो व्यवहार अपरिभाषित है: जब वे अवरुद्ध कर रहे हैं

तो SIGBUS, SIGFPE, SIGILL, या SIGSEGV उत्पन्न कर रहे हैं, परिणाम अपरिभाषित है, जब तक संकेत मार (2), सिग्यू्यू (3), या raise (3) द्वारा उत्पन्न किया गया था।

मेरे सिस्टम पर, यह प्रक्रिया को क्रैश करने का कारण बनता है।

SA_NODEFER के साथ कोई मास्किंग नहीं है, इसलिए सिग्नल ओवरफ्लो तक सिग्नल को फिर से संभाला जा सकता है। और SA_RESETHAND जोड़ना डिफ़ॉल्ट कार्रवाई को पुनर्स्थापित करेगा (SIGSEGV के लिए क्रैश)।

मैं साधारण परीक्षण कार्यक्रम के लिए अपने उदाहरण अनुकूलित है, तो आप इस व्यवहार को सत्यापित कर सकते हैं:

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

volatile char *ptr; 

static void DisasterSignals(int signal) 
{ 
    /* We cannot save the situation, the purpose of catching the signal is 
    only to do something clever to aid debugging before we go. */ 
    write(1, "11\n", 3); 
    *ptr = 1; 
    write(1, "13\n", 3); 
    abort(); /* This should give us the expected core dump (if we survive to this point) */ 
} 

struct sigaction sa = {}; /* initialised to all zero (I vote for GCC style breach of standard here) */ 

int main() 
{ 
    sa.sa_handler = DisasterSignals; 
    sa.sa_flags = /*SA_RESETHAND | */SA_NODEFER; /* To have or have not */ 
    sigaction(SIGSEGV, &sa, NULL); 

    write(1, "25\n", 3); 
    *ptr = 1; 
} 
संबंधित मुद्दे