2012-07-11 11 views
5

मुझे सी ++ में एक एसईजीवी मिल रहा है कि मैं pthread_join() पर अपने कॉल में आसानी से पुन: पेश नहीं कर सकता (यह लगभग 100,000 परीक्षण रनों में से एक में होता है) क्योंकि मेरा एप्लिकेशन बंद हो रहा है। मैंने इरनो के मूल्य की जांच की और यह शून्य है। यह Centos v4 पर चल रहा है।दुर्लभ मामलों में pthread_exit() pthread_detach() के बाद बुलाए जाने पर एसईजीवी क्यों करता है?

किस स्थिति में pthread_join() एक एसईजीवी प्राप्त करेगा? यह किसी प्रकार की दौड़ की स्थिति हो सकती है क्योंकि यह बेहद दुर्लभ है। एक व्यक्ति सुझाव देता है कि मुझे pthread_detach() और pthread_exit() को कॉल नहीं करना चाहिए, लेकिन मुझे स्पष्ट क्यों नहीं है।

मेरी पहली कामकाजी परिकल्पना यह थी कि pthread_join() को कहा जा रहा है जबकि pthread_exit() अभी भी दूसरे धागे में चल रहा है और यह किसी भी तरह से एसईजीवी की ओर जाता है, लेकिन कई ने कहा है कि यह कोई मुद्दा नहीं है।

नाकाम रहने कोड आवेदन बाहर निकलने के दौरान मुख्य थ्रेड में SEGV हो रही इस तरह मोटे तौर पर लग रहा है (त्रुटि वापसी कोड के साथ संक्षिप्तता के लिए छोड़े गए जाँच):

// During application startup, this function is called to create the child thread: 

return_val = pthread_create(&_threadId, &attr, 
          (void *(*)(void *))initialize, 
          (void *)this); 

// Apparently this next line is the issue: 
return_val = pthread_detach(_threadId); 

// Later during exit the following code is executed in the main thread: 

// This main thread waits for the child thread exit request to finish: 

// Release condition so child thread will exit: 
releaseCond(mtx(), startCond(), &startCount); 

// Wait until the child thread is done exiting so we don't delete memory it is 
// using while it is shutting down. 
waitOnCond(mtx(), endCond(), &endCount, 0); 
// The above wait completes at the point that the child thread is about 
// to call pthread_exit(). 

// It is unspecified whether a thread that has exited but remains unjoined 
// counts against {PTHREAD_THREADS_MAX}, hence we must do pthread_join() to 
// avoid possibly leaking the threads we destroy. 
pthread_join(_threadId, NULL); // SEGV in here!!! 

बच्चे धागा जो बाहर निकलने पर शामिल हो गए की जा रही है निम्नलिखित चलाता है कोड जो जहां releaseCond() मुख्य थ्रेड में कहा जाता है ऊपर बिंदु पर शुरू होता है:

// Wait for main thread to tell us to exit: 
waitOnCond(mtx(), startCond(), &startCount); 

// Tell the main thread we are done so it will do pthread_join(): 
releaseCond(mtx(), endCond(), &endCount); 
// At this point the main thread could call pthread_join() while we 
// call pthread_exit(). 

pthread_exit(NULL); 

धागा ठीक से आने के लिए दिखाई दिया और कोई त्रुटि कोड आवेदन स्टार्टअप और thre के दौरान अपने निर्माण के दौरान तैयार किए गए विज्ञापन ने अपना कार्य सही ढंग से किया जो आवेदन से बाहर होने से लगभग पांच सेकंड पहले लिया गया।

इस दुर्लभ एसईजीवी को होने का कारण क्या हो सकता है और मैं इसके खिलाफ रक्षात्मक तरीके से प्रोग्राम कैसे कर सकता हूं। एक दावा यह है कि pthread_detach() को मेरा कॉल मुद्दा है, यदि हां, तो मेरे कोड को कैसे ठीक किया जाना चाहिए।

+0

क्या आपने अपने pthread_join() के लिए स्थानीय दस्तावेज की जांच की है, सभी मानक अनुपालन नहीं हैं, आपको एक गैर नल पॉइंटर पास करना पड़ सकता है। –

+0

"बाल धागा" को पता है कि उस निकास कोड को कब कॉल करना है? वह निकास कोड कैसे लागू किया जाता है? – jxh

+1

केंद्र 4? बहुत रेट्रो लिनक्स थ्रेड या एनपीटीएल? – pilcrow

उत्तर

4

मान लिया जाये:

  1. pthread_create रिटर्न शून्य (? आप, यह जाँच कर रहे हैं सही)
  2. attr एक वैध pthread_attr_t वस्तु है (क्या आप इसे कैसे पैदा कर रहे क्यों सिर्फ बजाय शून्य से पारित नहीं?)
  3. attr निर्दिष्ट नहीं करता कि धागा अलग बनाया जाना है
  4. आप pthread_detach या pthread_join धागे पर कहीं और फोन नहीं किया

... तो यह असफल होने के लिए pthread_join के लिए "असंभव" है, और आपके पास या तो आपके रनटाइम में कुछ अन्य स्मृति भ्रष्टाचार या बग है।

[अद्यतन]

pthread_detach के लिए तर्क अनुभाग का कहना है:

* pthread_join *() या * pthread_detach *() कार्यों चाहिए अंततः हर धागा है कि इतना है कि बनाई गई है के लिए कहा जाता हो थ्रेड के साथ से जुड़े संग्रहण को पुनः दावा किया जा सकता है।

हालांकि यह कहना नहीं है इन परस्पर अनन्य हैं, pthread_join documentation निर्दिष्ट करता है: यदि धागा तर्क द्वारा निर्दिष्ट मान * pthread_join *() का उल्लेख नहीं करता

व्यवहार अपरिभाषित है एक जुड़ने योग्य धागे के लिए।

मुझे सटीक शब्द खोजने में परेशानी हो रही है जो कहता है कि एक अलग धागा शामिल नहीं है, लेकिन मुझे पूरा यकीन है कि यह सच है।

तो, या तो pthread_join या pthread_detach पर कॉल करें, लेकिन दोनों नहीं।

+0

1) वापसी मूल्य की जांच शून्य है। 2) यह वैध है, 'pthread_attr_init (&attr);' और 'pthread_attr_setstacksize (& attr, stackSize);' 64 एमबी स्टैक आकार का उपयोग करें। 3) अटर में कुछ और नहीं है, बाकी सब कुछ डिफॉल्ट है। 4) मैंने * pthread_detach (_threadId) को कॉल किया; 'pthread_create()' के तुरंत बाद। तो मुझे इसे सही करने के लिए कैसे अपडेट करना चाहिए? – WilliamKF

+1

आपको एक अलग थ्रेड में शामिल होने की आवश्यकता नहीं है; ऐसा करने के लिए एक त्रुटि है। जब मैं घर जाता हूं तो मैं अपने उत्तर को संदर्भ के साथ अपडेट कर दूंगा ... – Nemo

+1

मुझे यह भी हैरान है कि POSIX दस्तावेज़ों में "जुड़ने योग्य धागा" क्या है (या कम से कम एक जो ढूंढना आसान है) के बारे में अधिक स्पष्ट विवरण नहीं है। । 'Pthread_attr_getdetachstate()' के लिए दस्तावेज़ में प्रासंगिक जानकारी का एक और बिट है: http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getdetachstate.html# जो कहता है "यदि धागा अलग हो गया है, तो pthread_detach() या pthread_join() फ़ंक्शन द्वारा नव निर्मित थ्रेड की आईडी का उपयोग एक त्रुटि है " –

0

आप pthread_join और pthread_exit के लिए मानकों दस्तावेज और संबंधित पृष्ठों, निलंबित निष्पादन में शामिल होने के "जब तक लक्ष्य धागा समाप्त हो जाता है", और धागा बुला pthread_exit समाप्त नहीं करता जब तक यह pthread_exit बुला किया है, तो आप ऐसा क्या कर रहे हैं पढ़ें चिंतित समस्या नहीं हो सकती है।

आपके पास कहीं भी दूषित स्मृति हो सकती है (जैसा कि निमो सुझाव देता है), या क्लीनअप हैंडलर (उपयोगकर्ता 315052 सुझावों के रूप में) से pthread_exit कहा जाता है, या कुछ और। लेकिन यह "pthread_join() और pthread_exit()" के बीच दौड़ की स्थिति नहीं है, जब तक कि आप एक छोटी गाड़ी या गैर-अनुपालन कार्यान्वयन पर न हों।

0

आपकी समस्या का पूर्ण निदान करने के लिए अपर्याप्त जानकारी है। मैं अन्य पोस्ट उत्तरों के साथ सहमत हूं कि समस्या pthread_join और pthread_exit के बीच दौड़ की स्थिति की तुलना में आपके कोड में अनिश्चित व्यवहार की संभावना है। लेकिन मैं इस तरह की दौड़ के अस्तित्व से भी सहमत हूं pthread पुस्तकालय कार्यान्वयन में एक बग का गठन करेगा।

pthread_join के बारे में:

return_val = pthread_create(&_threadId, &attr, 
          (void *(*)(void *))initialize, 
          (void *)this); 
//... 
pthread_join(_threadId, NULL); // SEGV in here!!! 

ऐसा लगता है कि में शामिल होने के एक कक्षा में है। इससे संभावना है कि ऑब्जेक्ट को हटाया जा सकता है जबकि main शामिल होने का प्रयास कर रहा है। यदि pthread_join मुक्त स्मृति तक पहुंच रहा है, तो परिणाम अपरिभाषित व्यवहार है। मैं इस संभावना की ओर झुका रहा हूं, क्योंकि मुक्त स्मृति तक पहुंच अक्सर अनदेखा होती है।

pthread_exit के बारे में: लिनक्स पर आदमी पेज, और POSIX कल्पना राज्य:

एक अंतर्निहित कॉल pthread_exit करने के लिए() जब एक धागा धागा है जो मुख्य में() पहले जताने के अलावा और रिटर्न लागू किया जाता है प्रारंभिक दिनचर्या से इसे बनाने के लिए इस्तेमाल किया गया था। फ़ंक्शन का रिटर्न मान थ्रेड की निकास स्थिति के रूप में कार्य करेगा।

pthread_exit() का व्यवहार किसी रद्दीकरण क्लीनअप हैंडलर या विनाशक फ़ंक्शन से बुलाया जाता है जिसे किसी भी अंतर्निहित या स्पष्ट कॉल के परिणामस्वरूप pthread_exit() के रूप में बुलाया जाता है।

यदि pthread_exit कॉल क्लीनअप हैंडलर में किया गया है, तो आपके पास अपरिभाषित व्यवहार होगा।

+0

हां, यह कक्षा में है, ctor pthread_create() करता है और dtor pthread_join() करता है। – WilliamKF

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