2010-08-20 6 views
6

मेरे पास pthread_cond_wait का उपयोग कर एक कंडीशन चर पर प्रतीक्षा करने वाला एक पर्थ्रेड है। यह एक कतार संरचना से डेटा की प्रतीक्षा कर रहा है जो किसी अन्य धागे से भरा हुआ है। मैं इस थ्रेड को मारना चाहता हूं, अधिमानतः बिना pthread_kill के। लिनक्स और WinPthreads पर एक pthread_cancel(); pthread_join() इसे मारने के लिए पर्याप्त है। हालांकि, ओएस एक्स पर यह pthread_join कॉल पर लटकता है। कोई सुझाव?एक पंड्रेड को एक कंडीशन वैरिएबल पर प्रतीक्षा कर रहा है

+0

मैं एसडीएल का उपयोग कर रहा हूं इसलिए शायद समस्या को उलझाना है। मुझे पता है कि एसडीएल अपने स्वयं के धागे कार्यान्वयन प्रदान करता है, और शायद मुझे इसका उपयोग करना चाहिए क्योंकि पर्थ्रेड/एसडीएल में कुछ विचित्र इंटरैक्शन हैं, लेकिन मेरे पास पहले से ही कुछ लिथ्रेड कोड लिखा गया है और मैं इसे इस तरह से रखना पसंद करूंगा। – CarbonAsh

उत्तर

6

क्या आपके पास कतार तक पहुंच है, और वस्तुओं के लिए ऑब्जेक्ट स्कीमा का नियंत्रण है? यदि ऐसा है, तो एक कतार ऑब्जेक्ट प्रकार को परिभाषित करें कि जब डी-कतारबद्ध किया गया है, तो उस थ्रेड को निर्देशित करता है जो आइटम को प्रसंस्करण से बाहर निकलने के लिए प्रसंस्करण कर रहा है।

अब, इन धागों को बंद करने के लिए, बस क्यू के किसी थ्रेड कतार सेवा कर रहे हैं की संख्या से मेल खाती है की प्रमुख करने के लिए इन "छोड़" वस्तुओं के एक नंबर पोस्ट करते हैं, और धागे पर शामिल हो।

यह pthread_cancel/kill के "परमाणु विकल्प" से कहीं अधिक साफ दिखता है।

+0

यह वास्तव में वही है जो मैंने किया था! सुझाव के लिए धन्यवाद, इस तरह मेरा धागा अभी भी अंधेरे में रह सकता है और गैर थ्रेडेड उदाहरणों में चलाया जा सकता है और मेरी कतार जो पहले से ही थ्रेड जागरूक है, गंदे काम का ख्याल रख सकती है और थ्रेड को मारने के लिए pthread_exit को कॉल कर सकती है। – CarbonAsh

0

पहली चीज जो मैं कोशिश करूंगा, वह रद्द करने और जुड़ने के बीच में कंडीशन वैरिएबल को लात मारना होगा, और स्थिति लक्ष्य से लौटने के बाद स्पष्ट रूप से रद्दीकरण के लिए अपना लक्षित थ्रेड जांचना होगा।

ऐसा इसलिए है क्योंकि यह हो सकता है कि थ्रेड रद्दीकरण का जवाब नहीं दे रहा है, जबकि यह स्थिति प्रतीक्षा में है (या बिल्कुल)।

POSIX.1c -2004 (v6) में कहा गया:

cancelability राज्य और किसी भी हाल में बनाई गई धागे के प्रकार, धागा है जो मुख्य में() पहले लागू किया गया था, PTHREAD_CANCEL_ENABLE और PTHREAD_CANCEL_DEFERRED क्रमशः होगा भी शामिल है।

इसका मतलब है कि आपको स्पष्ट रूप से pthread_testcancel() के साथ रद्दीकरण की जांच करनी है। यह सोचते हैं कि समस्या क्या है है,

int junk; 
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &junk); 
std::cout 
    << ((junk==PTHREAD_CANCEL_DEFERRED) ? "Was deferred" : "Wasn't") 
    << std::endl; 

कि निश्चित रूप से है,:

अन्य विकल्प वास्तव में स्थापित करने के लिए सूत्र, PTHREAD_CANCEL_ASYNCHRONOUS के प्रकार को रद्द जब वह पहली बार चलाने के लिए शुरू होता है की तरह कुछ है। यदि आप ऊपर की तीसरी पंक्ति के आउटपुट की जांच कर रहे हैं तो आपको परीक्षण करने में सक्षम होना चाहिए।

रद्दीकरण को लक्ष्य थ्रेड पर अनुरोध करता है, जो इसे और अधिक बुराई pthread_kill() के विपरीत, अनदेखा करने के लिए स्वतंत्र है। मैं धागे को अपने जीवनकाल को नियंत्रित करने में एक महान आस्तिक हूं क्योंकि मुझे लगता है कि यह हमेशा कम समकालिक समस्याओं की ओर जाता है।

एक तरफ: वास्तव में,, pthreads की बहुत प्रारंभिक संस्करणों में खरीदा गया है यहां तक ​​कि DCE में एकीकरण से पहले, मैं अभी भी अपने आप को सिर्फ प्रत्येक थ्रेड का संकेत है जब यह बाहर निकलने चाहिए के लिए एक वैश्विक चर का उपयोग कर पाते हैं , धागे को उठाने के लिए मैन्युअल रूप से म्यूटेक्स या हालत चर को लात मारने के साथ-साथ। मुझे लगता है कि मुझे अपनी विधियों को अपडेट करना चाहिए (या अगर मैं स्पष्ट लाभ देख सकता हूं)। :-)

+0

ठीक है, मैं निश्चित रूप से कुछ गैर-रद्द करने की विधि रखना पसंद करूंगा लेकिन मेरे पास है लेकिन जो धागा रद्द हो जाता है वह वास्तव में नहीं जानता है कि यह थ्रेड में चल रहा है। मैंने कंडीशन वैरिएबल को सिग्नल करने का प्रयास किया है, लेकिन फिर यह कतार और segfaults से पढ़ता है क्योंकि इसमें कुछ भी नहीं है। हालांकि इस कार्यक्रम से बाहर निकलने का वांछित व्यवहार है, ऐसा लगता है कि 'बस गलत है।' – CarbonAsh

+0

बीटीडब्ल्यू, आपको यह कभी नहीं मानना ​​चाहिए, सिर्फ इसलिए कि आप cond_wait से वापस आते हैं, वहां काम उपलब्ध है। दो धागे जागने की प्रतीक्षा कर रहे हैं, काम पाने वाले पहले और दूसरे को कोई काम उपलब्ध नहीं होना चाहिए और प्रतीक्षा करने के लिए वापस जाना चाहिए। – paxdiablo

+1

स्थगित रद्दीकरण स्थिति का मतलब यह नहीं है कि आपको 'pthread_testcancel()' के साथ रद्दीकरण की स्पष्ट रूप से जांच करनी है; यह फ़ंक्शन पॉज़िक्स परिभाषित कई रद्दीकरण बिंदुओं में से एक है। * बहुत * लाइब्रेरी कॉल के साथ लंबे संख्यात्मक गणनाओं को निष्पादित करते समय आप बहुत अधिक * कभी * एसिंक्रोनस रद्दीकरण नहीं चाहते हैं। एसिंक्रोनस रद्दीकरण सक्षम होने पर आप एकमात्र लाइब्रेरी कॉल कर सकते हैं, एसिंक्रोनस रद्दीकरण को अक्षम करना है। :-) –

6

pthread_cancel एक धागा है कि pthread_cond_wait में अवरुद्ध है जगा दिया तो --- यह आवश्यक रद्द बिंदुओं में से एक है। अगर यह काम नहीं करता है तो कुछ गलत है।

जांच करने वाली पहली बात यह है कि रद्दीकरण वास्तव में लक्ष्य धागे पर सक्षम है --- सुनिश्चित करने के लिए लक्ष्य थ्रेड पर स्पष्ट रूप से pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&oldstate) पर कॉल करें। यदि यह काम नहीं करता है, तो आपके प्लेटफ़ॉर्म पर रद्दीकरण टूट गया है और आपको "कृपया अभी रोकें" ध्वज सेट करने और स्थिति चर को सिग्नल करने जैसे विकल्पों का सहारा लेना होगा।

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

संयोग से pthread_kill धागे को मारता है --- यह इसके लिए संकेत भेजता है।

+0

मैंने pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, और पुरानास्टेट) किया था। पुराना राज्य PTHREAD_CANCEL_ENABLE था और इसका कोई प्रभाव नहीं पड़ा। मैक ओएस एक्स के pthreads तोड़ दिया गया था, तो मुझे बहुत आश्चर्य होगा, लेकिन मुझे यकीन नहीं है कि और क्या गलत हो सकता है, क्योंकि यह कोड दोनों विंडोज़ और लिनक्स पर काम करता है। – CarbonAsh

+0

pthreads ठीक काम करता है, मैंने थोड़ा प्रोग्राम लिखा: pthread_cond_t cond; pthread_mutex_t लॉक; शून्य * tmain (शून्य *) { pthread_mutex_lock (&lock); pthread_cond_wait (और cond, &lock); pthread_mutex_unlock (&lock); } पूर्णांक मुख्य() { pthread_t धागा; pthread_cond_init (और cond, शून्य); pthread_mutex_init (और ताला, शून्य); pthread_create (और धागा, शून्य, tmain, शून्य); नींद (1); pthread_cancel (धागा); pthread_join (धागा, शून्य);} इसका परीक्षण करने के लिए और यह एक सेकंड के बाद बाहर निकलता है। मेरे कोड में मेरे पास कुछ अन्य बग होना चाहिए। – CarbonAsh

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