लिनक्स में कई थ्रेड्स के साथ सिग्नल हैंडलिंग


119

लिनक्स में, क्या होता है जब एक प्रोग्राम (जिसमें संभवतः कई थ्रेड होते हैं) एक संकेत प्राप्त करता है, जैसे कि SIGTERM या SIGHUP?

कौन सा धागा सिग्नल को स्वीकार करता है? क्या कई धागे एक ही संकेत प्राप्त कर सकते हैं? क्या संकेतों को संभालने के लिए पूरी तरह से समर्पित एक विशेष धागा है? यदि नहीं, तो संकेत को संभालने के लिए थ्रेड के अंदर क्या होता है? सिग्नल हैंडलर रूटीन खत्म होने के बाद निष्पादन कैसे शुरू होता है?

जवाबों:


35

यह थोड़ा बारीक है, जो आप उपयोग कर रहे हैं लिनक्स कर्नेल के किस संस्करण पर आधारित है।

2.6 पॉज़िक्स थ्रेड्स मानकर, और यदि आप OS को SIGTERM या SIGHUP भेजने की बात कर रहे हैं, तो सिग्नल को प्रोसेस में भेजा जाता है, जो रूट थ्रेड द्वारा प्राप्त और संभाला जाता है। POSIX थ्रेड्स का उपयोग करते हुए, आप SIGTERM को अलग-अलग थ्रेड्स में भी भेज सकते हैं, लेकिन मुझे संदेह है कि आप पूछ रहे हैं कि क्या होता है जब OS प्रक्रिया को सिग्नल भेजता है।

2.6 में, SIGTERM बाल थ्रेड्स को "सफाई से" बाहर निकलने का कारण होगा, जहां 2.4 के रूप में, बच्चे के थ्रेड्स को एक अनिश्चित स्थिति में छोड़ दिया गया था।


और जब संकेत प्राप्त होता है तो रूट थ्रेड के अंदर क्या होता है? मान लीजिए कि मैंने SIGUSR1 के लिए एक कस्टम सिग्नल हैंडलर लिखा है, और अब मैं उस सिग्नल को प्रक्रिया में भेज रहा हूं। रूट थ्रेड को वह संकेत मिल जाएगा। शायद यह किसी समारोह के बीच में हो। क्या होने वाला है?

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

ध्यान दें कि यह SIGUSR1 के लिए विशिष्ट है, जो IIRC सिस्टम कॉल को बाधित नहीं करता है। यदि आपने उदाहरण के लिए SIGINT के साथ यह कोशिश की, तो यह एक स्ट्रीम रीड को बाधित कर सकता है, और जब आप पढ़ने के लिए वापस जाते हैं, तो स्ट्रीम एक त्रुटि लौटा सकती है जिसे बाधित किया गया था।
एलन

10
मैं थोड़ा उलझन में हूँ कि "रूट थ्रेड" का क्या मतलब है। इसका मतलब यह है कि SIGTERM के लिए हैंडलर हमेशा मुख्य धागे में चलेगा, या यह किसी भी धागे में चल सकता है?
स्टीफन नट

3
यह उत्तर , जो बताता है कि सिग्नल को संभालने के लिए एक मनमाना धागा चुना जाता है, आपके उत्तर का खंडन करता है।
user202729

135

pthreads(7) वर्णन करता है कि POSIX.1 को प्रोसेस थ्रू विशेषताओं में सभी थ्रेड्स की आवश्यकता होती है, जिसमें शामिल हैं:

  • संकेत निपटान

POSIX.1 को प्रत्येक थ्रेड के लिए अलग होने के लिए कुछ विशेषताओं की भी आवश्यकता होती है , जिनमें शामिल हैं:

लिनक्स कर्नेल की complete_signalदिनचर्या में निम्न कोड ब्लॉक है - टिप्पणियां काफी उपयोगी हैं:

/*
 * Now find a thread we can wake up to take the signal off the queue.
 *
 * If the main thread wants the signal, it gets first crack.
 * Probably the least surprising to the average bear.
 */
if (wants_signal(sig, p))
        t = p;
else if (!group || thread_group_empty(p))
        /*
         * There is just one thread and it does not need to be woken.
         * It will dequeue unblocked signals before it runs again.
         */
        return;
else {
        /*
         * Otherwise try to find a suitable thread.
         */
        t = signal->curr_target;
        while (!wants_signal(sig, t)) {
                t = next_thread(t);
                if (t == signal->curr_target)
                        /*
                         * No thread needs to be woken.
                         * Any eligible threads will see
                         * the signal in the queue soon.
                         */
                        return;
        }
        signal->curr_target = t;
}

/*
 * Found a killable thread.  If the signal will be fatal,
 * then start taking the whole group down immediately.
 */
if (sig_fatal(p, sig) &&
    !(signal->flags & SIGNAL_GROUP_EXIT) &&
    !sigismember(&t->real_blocked, sig) &&
    (sig == SIGKILL || !p->ptrace)) {
        /*
         * This signal will be fatal to the whole group.
         */

तो, आप देखते हैं कि आप सिग्नल के वितरण के प्रभारी हैं:

यदि आपकी प्रक्रिया ने सिग्नल के स्वभाव को SIG_IGNया के लिए निर्धारित किया हैSIG_DFL तो कर दिया है, तो सिग्नल को सभी थ्रेड्स के लिए अनदेखा (या डिफ़ॉल्ट - किल, कोर या इग्नोर) किया जाता है।

यदि आपकी प्रक्रिया ने एक विशिष्ट हैंडलर रूटीन के लिए सिग्नल के फैलाव को निर्धारित किया है, तो आप यह नियंत्रित कर सकते हैं कि कौन सा धागा विशिष्ट थ्रेड सिग्नल मास्क का उपयोग करके संकेतों को प्राप्त करेगा। pthread_sigmask(3) । आप उन सभी को प्रबंधित करने के लिए एक धागे को नामांकित कर सकते हैं, या प्रति संकेत एक धागा बना सकते हैं, या विशिष्ट संकेतों के लिए इन विकल्पों में से कोई भी मिश्रण, या आप मुख्य धागे को संकेत देने के लिए लिनक्स कर्नेल के वर्तमान डिफ़ॉल्ट व्यवहार पर भरोसा कर सकते हैं।

हालांकि, कुछ संकेत signal(7)मैन पेज के अनुसार विशेष हैं :

एक प्रक्रिया के लिए एक संकेत (और इस प्रकार लंबित) उत्पन्न हो सकता है (जैसे, जब मार (2) का उपयोग करके भेजा जाता है ) या किसी विशिष्ट धागे के लिए (जैसे, कुछ संकेत, जैसे कि SIGSEGV और SIGFPE, निष्पादित होने के परिणामस्वरूप उत्पन्न होते हैं। एक विशिष्ट मशीन-भाषा निर्देश थ्रेड निर्देशित हैं, जैसे कि pthread_kill (3) ) का उपयोग करके एक विशिष्ट थ्रेड पर लक्षित संकेत हैं । एक प्रक्रिया-निर्देशित संकेत उन थ्रेड्स में से किसी एक को दिया जा सकता है, जिसमें वर्तमान में संकेत अवरुद्ध नहीं है। यदि थ्रेड्स में से एक में सिग्नल अनब्लॉक है, तो कर्नेल एक मनमाना धागा चुनता है जिससे सिग्नल डिलीवर किया जा सके।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.