2014-09-22 10 views
6

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

दुर्भाग्य से, हम अपवाद उपयोग नहीं कर सकते हैं - तो नहीं "पकड़", आदि

यहाँ मेरी परीक्षण कार्यक्रम (C++) है:

void* workerThreadFunc(void* threadId) { 
    int* a = NULL; 
    *a = 5; //Error (segmentation fault) 
    pthread_exit(NULL); 
} 

int main() { 
    cout << "Main thread start" << endl; 

    pthread_t workerThread; 
    pthread_attr_t attr; 
    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
    pthread_create(&workerThread, &attr, workerThreadFunc, (void*)0); 
    pthread_join(workerThread, NULL); 

    cout << "Main thread end" << endl; 
} 

उपरोक्त उदाहरण में, workerThread की वजह से त्रुटि होगा पूरे कार्यक्रम को समाप्त करें। लेकिन मैं इस त्रुटि के बावजूद मुख्य धागा चलाना जारी रखना चाहता हूं। क्या यह हासिल करना संभव है?

+0

दुर्भाग्यवश, हम अपवादों का उपयोग नहीं कर सकते - इसलिए कोई "पकड़" आदि नहीं। - जरूर आप कर सकते हो। अपवाद को उस धागे में फेंक दिया जाएगा जो इसे उठाएगा। –

+0

अपवादों/त्रुटियों से अन्य धागे को 'सुरक्षित' करने का सबसे अच्छा तरीका यह है कि उन्हें ठीक किया जाए ताकि वे ऐसा न हों या पता चला हो और प्रबंधित/लॉग/जो भी हो। –

+0

नोट - ऊपर दिए गए आपके उदाहरण में, आप ऐसे थ्रेड में शामिल होने का प्रयास कर रहे हैं जो अभी तक नहीं बनाया गया है। –

उत्तर

8

मुझे लगता है जैसे आपको कई प्रक्रियाओं का उपयोग करना चाहिए, धागे नहीं। स्वतंत्र प्रक्रियाओं को स्वचालित रूप से अन्य प्रक्रियाओं में होने वाली त्रुटियों से सुरक्षित किया जाता है।

आप थ्रेड के बीच डेटा पास करने के लिए पाइप या साझा मेमोरी (या आईपीसी के अन्य रूपों) का उपयोग कर सकते हैं, जिसमें आपके द्वारा साझा की जाने वाली मेमोरी को साझा करने का अतिरिक्त लाभ होता है, इसलिए कार्यकर्ता "थ्रेड" में एक बग स्टॉम्प नहीं हो सकता मुख्य "थ्रेड" के ढेर पर, क्योंकि यह एक अलग पता स्थान के साथ एक अलग प्रक्रिया है।

थ्रेड उपयोगी हो सकते हैं, लेकिन कई नुकसान के साथ आते हैं, कभी-कभी अलग प्रक्रियाओं में चलना अधिक उपयुक्त होता है।

+0

"प्रक्रिया" से आपका मतलब एक्सपैम्प के लिए है ले फोर्क()? – Martin

+0

हां, 'फोर्क()' मास्टर से नई बाल प्रक्रियाएं, और या तो 'exec() 'श्रमिकों के लिए एक अलग निष्पादन योग्य है, या केवल एक ही निष्पादन योग्य चलती रहें लेकिन बच्चे" कार्यकर्ता "मोड में चलें। –

4

आपके सिस्टम मान लिया जाये कि एक तरह से की एक POSIX प्रकार में संकेतों का उपयोग करता (कि हालांकि "कोई अपवाद नहीं" नियम के तहत गिर सकता है), तो POSIX का कहना है:

पीढ़ी के समय, एक दृढ़ संकल्प किया जाएगा बनाया गया है कि प्रक्रिया के लिए या प्रक्रिया के भीतर एक विशिष्ट थ्रेड के लिए सिग्नल उत्पन्न किया गया है या नहीं। सिग्नल जो किसी विशेष थ्रेड के लिए जिम्मेदार कुछ क्रियाओं से उत्पन्न होते हैं, जैसे हार्डवेयर गलती, सिग्नल उत्पन्न होने वाले थ्रेड के लिए जेनरेट की जाएगी।

तो तुम SIGSEGV, SIGFPE, एक प्रति pthread आधार पर आदि संभाल कर सकते हैं (लेकिन ध्यान दें कि आप केवल पूरी प्रक्रिया के लिए एक संकेत हैंडलर समारोह सेट कर सकते हैं कि)। तो, आप एक पठार में विफलता से प्रक्रिया को "रोक" से रोक सकते हैं ... एक बिंदु तक। समस्या यह है कि, आपको यह बताने में बहुत मुश्किल हो सकती है कि प्रक्रिया किस स्थिति में है - असफल पर्थ्रेड, और अन्य सभी pthreads - अंदर है। असफल पठार में कई म्यूटेक्स हो सकते हैं। असफल पर्थ्रेड कुछ साझा डेटा संरचनाओं को गड़बड़ में छोड़ सकता है। कौन जानता है कि किस प्रकार की उलझन में चीजें हैं - जब तक कि पर्थ्रेड अनिवार्य रूप से स्वतंत्र न हों। दुर्घटनाग्रस्त होने और जलाए जाने के बजाय "खूबसूरत" बंद करने के लिए अन्य pthreads की व्यवस्था करना संभव हो सकता है। अंत में, अच्छी तरह से परिभाषित राज्य से कम कुछ जारी रखने की कोशिश करने के बजाय, सभी pthreads मृत को रोकने के लिए सुरक्षित हो सकता है। यह पूरी तरह से आवेदन की प्रकृति पर निर्भर करेगा।

कुछ भी नहीं के लिए कुछ भी नहीं है ... धागे एक दूसरे के साथ प्रक्रियाओं की तुलना में अधिक आसानी से संवाद कर सकते हैं, और शुरू करने और रोकने के लिए कम लागत - प्रक्रियाएं अन्य प्रक्रियाओं की विफलता के लिए कम कमजोर हैं।

5

एक ही रास्ता मैं यह कर के बारे में सोच सकते हैं एक संकेत हैंडलर, जो बजाय कार्यक्रम निरस्त किया जा रहा है, वर्तमान में चल रहे धागा रद्द कर सकता है, कुछ इस तरह दर्ज की है:

void handler(int sig) 
{ 
    pthread_exit(NULL); 
} 

signal(SIGSEGV, handler); 

ध्यान दें, तथापि, यह है pthread_exit के रूप में असुरक्षित सिग्नल हैंडलर के अंदर सुरक्षित सिस्टम कॉल में से एक के रूप में सूचीबद्ध नहीं है। यह काम कर सकता है और ऐसा नहीं हो सकता है, ओ/एस के आधार पर आप चल रहे हैं, और आप किस सिग्नल पर हैंडल कर रहे हैं।

+0

धन्यवाद। ऐसा लगता है कि यह चाल है, कम से कम अभी के लिए एक साधारण परीक्षण। मुझे आपके द्वारा बात की जाने वाली सुरक्षा समस्याओं का शोध करने की आवश्यकता होगी। – Martin

+0

ऐसा लगता है कि pthread_exit एक SIGABRT का कारण बनता है यदि उस थ्रेड स्टैक पर कोई ऑब्जेक्ट बनाया गया है और उस ऑब्जेक्ट में एक विनाशक परिभाषित है। इससे या तो अनंत लूप का कारण बन जाएगा SIGABRT को पकड़ लिया (यदि उन्हें श्वास में पकड़ रहा है), या फिर एक पूर्ण प्रोग्राम क्रैश। उदाहरण के लिए ऐसा होता है यदि मैं एक बहुत ही सरल संरचना का ऑब्जेक्ट घोषित करता हूं। अगर उस ऑब्जेक्ट में विनाशक परिभाषित होता है तो यह क्रैश हो जाएगा, यहां तक ​​कि केवल ~ ए() {}। लेकिन इस विनाशक के बिना परिभाषित किया गया है, कोई SIGABRT नहीं भेजा जाता है। समस्या तब भी होती है जब मैं उदाहरण के लिए एक वेक्टर घोषित करता हूं। – Martin

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