सबसे पहले, मुझे पता है कि म्यूटेक्स को सामान्य रूप से एसिंक-सुरक्षित नहीं माना जाता है। यह सवाल sigprocmask
के उपयोग से संबंधित है ताकि मल्टीक्स्रेड प्रोग्राम में एसिंक सिग्नल और सिग्नल हैंडलर के साथ म्यूटेक्स सुरक्षित हो सके।एसिंक संकेतों के साथ म्यूटेक्स सुरक्षा की गारंटी
struct { int a, b; } gvars;
void sigfoo_handler(int signo, siginfo_t *info, void *context) {
if(gvars.a == 42 || gvars.b == 13) {
/* run a chained signal handler */
}
}
/* called from normal code */
void update_gvars(int a, int b) {
gvars.a = a;
gvars.b = b;
}
gvars
एक वैश्विक चर जो एक एकल sig_atomic_t
में फिट करने के लिए बहुत बड़ी है है:
मैं धारणात्मक निम्नलिखित की तरह कुछ कोड है। यह सामान्य कोड द्वारा अद्यतन किया जाता है और सिग्नल हैंडलर से पढ़ा जाता है। नियंत्रित कोड एक जंजीर सिग्नल हैंडलर है, और इसलिए इसे सिग्नल हैंडलर संदर्भ में चलाना चाहिए (यह info
या context
का उपयोग कर सकता है)। नतीजतन, gvars
तक पहुंच सभी प्रकार के सिंक्रनाइज़ेशन तंत्र के माध्यम से नियंत्रित की जानी चाहिए। जटिल मामलों, कार्यक्रम बहुप्रचारित है, और किसी भी धागे को SIGFOO
प्राप्त हो सकता है।
प्रश्न:sigprocmask
(या pthread_sigmask
) और pthread_mutex_t
के संयोजन से, यह संभव करने के लिए गारंटी तुल्यकालन, निम्नलिखित की तरह कोड का उपयोग कर रहा है?
struct { int a, b; } gvars;
pthread_mutex_t gvars_mutex;
void sigfoo_handler(int signo, siginfo_t *info, void *context) {
/* Assume SIGFOO's handler does not have NODEFER set, i.e. it is automatically blocked upon entry */
pthread_mutex_lock(&gvars_mutex);
int cond = gvars.a == 42 || gvars.b == 13;
pthread_mutex_unlock(&gvars_mutex);
if(cond) {
/* run a chained signal handler */
}
}
/* called from normal code */
void update_gvars(int a, int b) {
sigset_t set, oset;
sigemptyset(&set);
sigaddset(&set, SIGFOO);
pthread_sigmask(SIG_BLOCK, &set, &oset);
pthread_mutex_lock(&gvars_mutex);
gvars.a = a;
gvars.b = b;
pthread_mutex_unlock(&gvars_mutex);
pthread_sigmask(SIG_SETMASK, &oset, NULL);
}
तर्क निम्नलिखित के रूप में चला जाता है: sigfoo_handler
भीतर, SIGFOO
अवरुद्ध है तो यह pthread_mutex_lock
को बाधित नहीं कर सकते हैं। update_gvars
के भीतर, SIGFOO
pthread_sigmask
-संरक्षित महत्वपूर्ण क्षेत्र के दौरान वर्तमान धागे में नहीं उठाया जा सकता है, और इसलिए यह pthread_mutex_lock
को बाधित नहीं कर सकता है। मान लें कि अन्य सिग्नल (और हम हमेशा किसी अन्य सिग्नल को अवरुद्ध कर सकते हैं जो समस्याग्रस्त हो सकता है), ताला/अनलॉक हमेशा मौजूदा थ्रेड पर सामान्य, अनियंत्रित फैशन में आगे बढ़ना चाहिए, और लॉक/अनलॉक के उपयोग को सुनिश्चित करना चाहिए कि अन्य धागे हस्तक्षेप नहीं करते हैं। क्या मैं सही हूं, या मुझे इस दृष्टिकोण से बचना चाहिए?
यदि सिग्नल 'SA_NODEFER' के साथ सेट किया गया है, तो मैं हैंडलर के भीतर ही 'sigprocmask' का उपयोग उसी तरह से करने में सक्षम होना चाहिए, नहीं? – nneonneo
इसके अलावा, प्रक्रिया सिग्मास्क प्रश्न से बाहर हैं, क्योंकि दो धागे से एक साथ 'सिगप्रोकमास्क' का उपयोग करना निश्चित रूप से नो-नो है। मुझे संदेह है कि इससे निपटने का सबसे अच्छा तरीका थ्रेड सिग्मास्क में सभी संकेतों को अवरुद्ध करना होगा यदि एकाधिक सिग्नल हैंडलर थे। – nneonneo
यदि मैं स्पष्ट रूप से कर सकता हूं, तो मैं एप्लिकेशन को फिर से डिजाइन कर दूंगा, लेकिन मेरे मामले में ऐसा कुछ क्यों जरूरी है, इसके बहुत अच्छे कारण हैं। – nneonneo