2011-10-31 18 views
20

मैं एक धागा बना सकते हैं और मैं इसे एक अनंत लूप में डाल दिया। मैं जब valgrind साथ कोड की जाँच मेमोरी लीक मिलता है। यहां मेरा कोड है:मैं लूप के बाहर से एक अनंत लूप में एक पाथ्रेड कैसे मार सकता हूं?

#include <pthread.h> 
#include <time.h> 

void thread_do(void){ 
    while(1){} 
} 

int main(){ 
    pthread_t th; 
    pthread_create(&th, NULL, (void *)thread_do, NULL); 

    sleep(2); 
    /* I want to kill thread here */ 
    sleep(2); 
    return 0; 
} 

तो एक धागा मुख्य में बनाया गया है और केवल थ्रेड_do() चलाता है। वहाँ 2 मुख्य के बाद अंदर सेकंड से यह मारने के लिए एक तरीका है? मैं दोनों pthread_detach(th) और pthread_cancel(th) की कोशिश की है लेकिन मैं अभी भी लीक मिलता है।

+3

pthreads को रद्द करना मतलब है कि थ्रेड को आवंटित किसी भी स्मृति को साफ़ करने का कोई मौका नहीं है। –

+2

ठीक है मैंने इसे वैश्विक 'keepalive = 1' के द्वारा हल किया है। तब मैंने '1 (1)' से 'जबकि (रखरखाव)' बदल दिया। धागे को मारने के लिए अब मुझे परिवर्तनीय रखरखाव के मूल्य को 0 और वॉयला में बदलना होगा! – Pithikos

उत्तर

32

रूप @sarnold ने बताया डिफ़ॉल्ट अपने धागा किसी भी कार्य करता है कि रद्द अंक हैं बुला बिना pthread_cancel() साथ रद्द नहीं किया जा सकता से ... लेकिन यह कर सकते हैं थ्रेड के रद्दीकरण प्रकार को स्थगित करने के बजाय एसिंक्रोनस पर सेट करने के लिए pthread_setcanceltype() का उपयोग कर बदला जा सकता है। ऐसा करने के लिए, आप लूप शुरू करने से पहले, अपने थ्रेड फ़ंक्शन की शुरुआत के करीब pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); जैसे कुछ जोड़ देंगे। इसके बाद आप main() से pthread_cancel(th) फोन करके धागा समाप्त करने में सक्षम हो जाएगा।

नोट, हालांकि, धागे को इस तरह से रद्द करना (चाहे असीमित या नहीं) थ्रेड फ़ंक्शन में आवंटित किसी भी संसाधन को साफ़ नहीं करता है (जैसा कि केविन द्वारा टिप्पणी में उल्लेख किया गया है)। आदेश में इस सफाई से करने के लिए, आप कर सकते हैं:

  • सुनिश्चित करें कि धागा कुछ भी यह (जैसे malloc() का उपयोग कर एक बफर आवंटित करने के लिए)
  • सुनिश्चित करें कि आप किसी तरह से है कि बाहर निकलने से पहले साफ करने के लिए की जरूरत है ऐसा नहीं करता है कहीं और धागा के बाद सफाई, धागा के बाद
  • उपयोग pthread_cleanup_push() और pthread_cleanup_pop() सफाई संचालकों को जोड़ने के लिए संसाधनों को साफ करने के लिए जब धागा रद्द कर दिए जाने से निकल जाता है की। ध्यान दें कि रद्दीकरण प्रकार असीमित है, तो यह अभी भी जोखिम भरा है, क्योंकि संसाधन को आवंटित करने और क्लीनअप हैंडलर जोड़ने के बीच धागा रद्द किया जा सकता है।
  • pthread_cancel() का उपयोग करने से बचें और थ्रेड को निर्धारित करने के लिए कुछ शर्त जांचें (जिसे लंबे समय तक चलने वाले लूप में चेक किया जाएगा)। चूंकि आपका धागा समाप्त होने के बाद जांचता है, यह जांच के बाद जो कुछ भी सफाई की आवश्यकता है, वह कर सकता है। धागा नहीं है, तो

    #include <pthread.h> 
    #include <unistd.h> 
    #include <errno.h> 
    
    /* Returns 1 (true) if the mutex is unlocked, which is the 
    * thread's signal to terminate. 
    */ 
    int needQuit(pthread_mutex_t *mtx) 
    { 
        switch(pthread_mutex_trylock(mtx)) { 
        case 0: /* if we got the lock, unlock and return 1 (true) */ 
         pthread_mutex_unlock(mtx); 
         return 1; 
        case EBUSY: /* return 0 (false) if the mutex was locked */ 
         return 0; 
        } 
        return 1; 
    } 
    
    /* Thread function, containing a loop that's infinite except that it checks for 
    * termination with needQuit() 
    */ 
    void *thread_do(void *arg) 
    { 
        pthread_mutex_t *mx = arg; 
        while(!needQuit(mx)) {} 
        return NULL; 
    } 
    
    int main(int argc, char *argv[]) 
    { 
        pthread_t th; 
        pthread_mutex_t mxq; /* mutex used as quit flag */ 
    
        /* init and lock the mutex before creating the thread. As long as the 
        mutex stays locked, the thread should keep running. A pointer to the 
        mutex is passed as the argument to the thread function. */ 
        pthread_mutex_init(&mxq,NULL); 
        pthread_mutex_lock(&mxq); 
        pthread_create(&th,NULL,thread_do,&mxq); 
    
        sleep(2); 
    
        /* unlock mxq to tell the thread to terminate, then join the thread */ 
        pthread_mutex_unlock(&mxq); 
        pthread_join(th,NULL); 
    
        sleep(2); 
        return 0; 
    } 
    

    : अंतिम विकल्प को लागू करने की

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

+0

एकाधिक pthread के लिए इस mutex समाधान का उपयोग करने के लिए मुझे प्रति mutex एक थ्रेड की आवश्यकता होगी, है ना? क्या आप इस मामले में इस समाधान की सिफारिश करेंगे? –

+2

@ रिकार्डोक्रूडो नहीं, केवल एक म्यूटेक्स ... यदि 'needQuit()' सफलतापूर्वक इसे लॉक करता है, तो यह ठीक से इसे अनलॉक करता है ... केवल 'मुख्य()' एक विस्तारित अवधि के लिए म्यूटेक्स रखता है। किसी भी थ्रेड को 'needQuit()' का उपयोग करके जांचना है कि क्या छोड़ना है या नहीं, एक बार छोड़ने के बाद म्यूटेक्स लॉक हो जाएगा, और वे इसे स्वयं को (बहुत ही संक्षिप्त) पल के लिए लॉक कर देंगे। केवल एक 'needQuit() 'कॉल एक समय में सफल हो जाएगा, लेकिन प्रत्येक थ्रेड को एक के बाद एक सफल कॉल मिलेगा। – Dmitri

5

कुछ छोटे विचार:

  1. आप अपने धागा रद्द करना चाहते हैं, लेकिन अगर जगह में रद्द करने की नीति एक आस्थगित रद्द करने के लिए है, अपने thread_do(), रद्द किया जा कभी नहीं होगा, क्योंकि यह कभी नहीं किसी भी कॉल कार्यों कि रद्द बिंदु हैं:

    A thread's cancellation type, determined by 
    pthread_setcanceltype(3), may be either asynchronous or 
    deferred (the default for new threads). Asynchronous 
    cancelability means that the thread can be canceled at any 
    time (usually immediately, but the system does not guarantee 
    this). Deferred cancelability means that cancellation will 
    be delayed until the thread next calls a function that is a 
    cancellation point. A list of functions that are or may be 
    cancellation points is provided in pthreads(7). 
    
  2. आप अपने साधारण उदाहरण कोड में धागा में शामिल होने नहीं कर रहे हैं; अपने कार्यक्रम के अंत से पहले pthread_join(3) फोन:

    After a canceled thread has terminated, a join with that 
    thread using pthread_join(3) obtains PTHREAD_CANCELED as the 
    thread's exit status. (Joining with a thread is the only way 
    to know that cancellation has completed.) 
    

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

  • कोई संबंधित समस्या नहीं^_^