मुझे पहले जांचेता के जवाब से उलझन में था, जब तक मुझे पता चला कि siglongjmp
का उद्देश्य सिग्नल मास्क में प्राप्त सिग्नल को अनब्लॉक करना है, कूदने से पहले। संकेत सिग्नल हैंडलर के प्रवेश पर अवरुद्ध है ताकि हैंडलर खुद को बाधित न करे। हम सामान्य निष्पादन को फिर से शुरू करते समय सिग्नल अवरुद्ध नहीं करना चाहते हैं, और यही कारण है कि हम longjmp
के बजाय siglongjmp
का उपयोग करते हैं। एआईयूआई, यह सिर्फ शॉर्टेंड है, हम sigprocmask
पर भी longjmp
पर कॉल कर सकते हैं, ऐसा लगता है कि siglongjmp
में ग्लिब क्या कर रहा है।
मैंने सोचा कि यह कूदने के लिए असुरक्षित हो सकता है क्योंकि readline()
malloc
और free
पर कॉल करता है। अगर सिग्नल प्राप्त होता है जबकि कुछ एसिंक-सिग्नल-असुरक्षित फ़ंक्शन malloc
या free
वैश्विक स्थिति को संशोधित कर रहा है, तो कुछ भ्रष्टाचार का परिणाम हो सकता है यदि हम सिग्नल हैंडलर से बाहर निकलते हैं। लेकिन रीडलाइन अपने सिग्नल हैंडलर स्थापित करती है जो इस बारे में सावधान हैं। वे सिर्फ एक झंडा सेट और बाहर निकलें; जब रीडलाइन लाइब्रेरी को फिर से नियंत्रण मिल जाता है (आमतौर पर बाधित 'पढ़ने()' कॉल के बाद) यह RL_CHECK_SIGNALS()
पर कॉल करता है जो उसके बाद kill()
का उपयोग कर क्लाइंट एप्लिकेशन को लंबित सिग्नल अग्रेषित करता है। इसलिए सिग्नल हैंडलर से बाहर निकलने के लिए siglongjmp()
का उपयोग करना सुरक्षित है, जिसने readline()
पर कॉल को बाधित कर दिया - संकेत को एसिंक-सिग्नल-असुरक्षित फ़ंक्शन के दौरान प्राप्त नहीं किया गया है।
वास्तव में, जो पूरी तरह सच नहीं है क्योंकि वहाँ rl_set_prompt()
भीतर malloc()
और free()
करने के लिए कुछ कॉल है, जो readline()
कॉल बस से पहले rl_set_signals()
हैं। मुझे आश्चर्य है कि क्या यह कॉलिंग ऑर्डर बदला जाना चाहिए। किसी भी मामले में दौड़ की स्थिति की संभावना बहुत पतली है।
मैंने बैश स्रोत कोड को देखा और ऐसा लगता है कि यह अपने सिगिनट हैंडलर से बाहर निकलता है।
एक अन्य रीडलाइन इंटरफ़ेस जिसका आप उपयोग कर सकते हैं वह कॉलबैक इंटरफ़ेस है। इसका उपयोग पायथन या आर जैसे अनुप्रयोगों द्वारा किया जाता है, जिसे एक साथ कई फ़ाइल डिस्क्रिप्टरों पर सुनने की आवश्यकता होती है, उदाहरण के लिए यह बताएं कि कमांड लाइन इंटरफ़ेस सक्रिय होने पर प्लॉट विंडो का आकार बदल रहा है या नहीं। वे इसे select()
लूप में करेंगे।
यहाँ जो क्या कॉलबैक इंटरफ़ेस में SIGINT प्राप्त होने पर बैश की तरह व्यवहार प्राप्त करने के लिए ऐसा करने के लिए की कुछ विचार देता है चेट रामे से एक संदेश है:
https://lists.gnu.org/archive/html/bug-readline/2016-04/msg00071.html
संदेशों पता चलता है कि आप की तरह कुछ करना इस:
rl_free_line_state();
rl_cleanup_after_signal();
RL_UNSETSTATE(RL_STATE_ISEARCH|RL_STATE_NSEARCH|RL_STATE_VIMOTION|RL_STATE_NUMERICARG|RL_STATE_MULTIKEY);
rl_line_buffer[rl_point = rl_end = rl_mark = 0] = 0;
printf("\n");
जब आपके SIGINT प्राप्त होता है, यदि आप एक ध्वज सेट कर सकते हैं, और बाद में अपने select()
पाश में झंडा जाँच - के बाद से select()
कॉल बाधित हो जाएगी errno==EINTR
के साथ सिग्नल द्वारा। यदि आपको लगता है कि ध्वज सेट किया गया है, तो उपरोक्त कोड निष्पादित करें।
मेरी राय यह है कि रीडलाइन को अपने स्वयं के सिगिनट हैंडलिंग कोड में उपरोक्त खंड की तरह कुछ चलाना चाहिए। वर्तमान में यह केवल पहले दो पंक्तियों को कम या कम निष्पादित करता है, यही कारण है कि वृद्धिशील-खोज और कीबोर्ड मैक्रोज़ जैसी सामग्री^सी द्वारा रद्द कर दी जाती है, लेकिन रेखा को साफ़ नहीं किया जाता है।
एक और पोस्टर ने कहा "कॉल rl_clear_signals()", जो अभी भी मुझे भ्रमित करता है। मैंने कोशिश नहीं की है, लेकिन मुझे नहीं पता कि यह कुछ भी कैसे पूरा करेगा (1) रीडलाइन के सिग्नल हैंडलर आपको संकेत भेजते हैं, और (2) readline()
प्रविष्टि पर सिग्नल हैंडलर इंस्टॉल करता है (और जब यह निकलता है तो उन्हें साफ़ करता है), इसलिए वे आमतौर पर रीडलाइन कोड के बाहर सक्रिय नहीं होंगे।
आप सिग्नल हैंडलर से सुरक्षित रूप से 'printf' को कॉल नहीं कर सकते हैं। – pat