2013-06-06 5 views
6

मैं निम्नलिखित sigaction हैंडलर समारोहफ़ंक्शन एसिंक-सिग्नल-सुरक्षित कैसे करें?

void signal_term_handler(int sig) 
{ 
    printf("EXIT :TERM signal Received!\n"); 
    int rc = flock(pid_file, LOCK_UN | LOCK_NB); 
    if(rc) { 
     char *piderr = "PID file unlock failed!"; 
     fprintf(stderr, "%s\n", piderr); 
     printf(piderr); 
    } 
    abort(); 
} 

किसी ने मुझसे कहा था कि flock और printf async-संकेत सुरक्षित नहीं हैं। और मुझे list में flock के लिए वैकल्पिक एसिंक-सिग्नल-सुरक्षित फ़ंक्शन नहीं मिला।

और ऊपर के लिंक के अनुसार:

जब एक संकेत एक असुरक्षित समारोह और संकेत को पकड़ने समारोह एक असुरक्षित फ़ंक्शन को कॉल बीच, व्यवहार अपरिभाषित है

वहाँ एक रास्ता है flock async-signal-safe बनाने के लिए? या सिग्नल प्राप्त करते समय flock निष्पादित करने का कोई और समाधान है?

+0

संभावित डुप्लिकेट [सिग्नल हैंडलर में printf का उपयोग करने से कैसे बचें?] (Https://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler) के लिए 'printf', https://stackoverflow.com/questions/16979059/use-flock-in-the-sigaction-handler 'flock' के लिए। –

उत्तर

4

आप फ्लॉक() के विकल्प के रूप में fcntl() का उपयोग कर सकते हैं।

+0

ध्यान रखें कि 'fcntl()' ताले के अर्थशास्त्र 'झुंड() 'की तुलना में कम और कम उपयोगी हैं। – jilles

+0

वास्तव में मैं इस [विषय] में संकेत के रूप में एक नई संपत्ति झुंड() फ़ंक्शन विकसित करने के लिए fcntl का उपयोग कर सकता हूं (http://stackoverflow.com/questions/16988256/how-to-lock-and-unlock-pid-file- साथ-fcntl)। उत्तर – MOHAMED

0

आप exit() बजाय अपने संकेत हैंडलर में abort() उपयोग कर सकते हैं, और फिर atexit() का उपयोग कर एक निकास हैंडलर में अपने असुरक्षित कार्यों डाल दिया।

अद्यतन: सामान्य रूप से, आपको अपने सिग्नल हैंडलर में संभावित रूप से अवरुद्ध सिस्टम कॉल नहीं करना चाहिए। इससे बचने का एक तरीका यह है कि अपने सिग्नल हैंडलर में केवल एक ध्वज सेट करें, और उसके बाद अपने मुख्य लूप के संदर्भ में इच्छित कार्यों को निष्पादित करें।

volatile int shutdown = 0; 

void signal_term_handler(int sig) 
{ 
    shutdown = 1; 
} 

void cleanup() { 
    printf("EXIT :TERM signal Received!\n"); 
    int rc = flock(pid_file, LOCK_UN | LOCK_NB); 
    if(rc) { 
     char *piderr = "PID file unlock failed!"; 
     fprintf(stderr, "%s\n", piderr); 
     printf(piderr); 
    } 
} 

void *workerFunction(void *arg) { 
    while (!shutdown) { 
     ... do stuff ... 
    } 
    return NULL; 
} 

int main(int argc, char *argv[]) { 
    //... 
    pthread_create(...,workerFunction,...); 
    pthread_join(...); 
    cleanup(); 
    return 0; 
} 
+0

निकास-हैंडलर को समकालिक रूप से कहा जा सकता है। एक असीमित रूप से संकेत सिग्नल हैंडलर से ऐसा करने से उन्हें कैसे चलाया जाता है? – alk

+0

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

+0

यह गलत है; यह अस्थिर होना चाहिए sig_atomic_t –

4

flock() आम तौर पर एसिंक-सिग्नल-सुरक्षित है क्योंकि यह एक सिस्टम कॉल है। इसके अर्थशास्त्र इसे अलग-अलग कार्यान्वित करना कठिन बनाते हैं। यह POSIX की एसिंक-सिग्नल-सुरक्षित फ़ंक्शंस की सूची में नहीं है क्योंकि यह POSIX में बिल्कुल नहीं है।

आपको संभावित अनलॉक की आवश्यकता नहीं है क्योंकि flock() ताले स्वचालित रूप से रिलीज़ होते हैं जब सभी फ़ाइल वर्णनकर्ता खुले फ़ाइल विवरण का जिक्र करते हैं।

printf() और fprintf() कॉल उचित write() कॉल के साथ प्रतिस्थापित किया जाना चाहिए। Stdio फ़ंक्शन एसिंक-सिग्नल-सुरक्षित फ़ंक्शंस की सूची में नहीं हैं और अक्सर दृढ़ता से एसिंक-सिग्नल-असुरक्षित होते हैं।

abort() कॉल शायद डिफ़ॉल्ट कार्रवाई को सिग्नल सेट करके और इसे स्वयं पर भेजकर सबसे अच्छा स्थानांतरित किया गया है; इस तरह, गोले जानते हैं कि आपका प्रोग्राम सिग्नल के कारण निकला है और उचित होने पर कमांड अनुक्रमों को रोक सकता है।

+0

के लिए धन्यवाद, क्या मैं सिग्नेशन हैंडलर में समस्याओं के बिना 'झुंड() 'का उपयोग कर सकता हूं? – MOHAMED

+0

हां, लेकिन जैसा कि मैंने कहा था कि आपको इसकी आवश्यकता नहीं हो सकती है। – jilles

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