2012-05-09 29 views
1

我用Eclispse靛藍+ CDT 8.0.2 + Cygwin來建立一種多線程SYSTERM,代碼如下所示:pthread_coin在調用pthread_cancel後無法返回?

pthread_mutex_t mutexCmd = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t signalCmd = PTHREAD_COND_INITIALIZER; 

void * Func(void * arg) 
{ 
    int iStatus; 
    while (1) 
    { 
     int a = 1; 
     pthread_cleanup_push(pthread_mutex_unlock, &mutexCmd); 
     pthread_mutex_lock(&mutexCmd); 
     iStatus = pthread_cond_wait(&signalCmd, &mutexCmd); 
     if (iStatus) { 
       err_abort(iStatus, "signalCmd status error"); 
     } 
     if(arg->Cmd != navi_Go) //Just a command tag; 
     { 
      pthread_mutex_unlock(&(pNaviCtrl->mutexCmd)); 
      continue; 
     } 
     //do some work 
     //..... 
     pthread_mutex_unlock(&mutexCmd); 
     pthread_cleanup_pop(1); 
    } 
//pthread_detach(pthread_self()); 
return NULL; 
} 

int main() 
{ 
    int iStatus = 0; 
    pthread = tid; 
    iStatus = pthread_create(&tid;NULL, Func, NULL); 
    if(iStatus) 
    { 
    err_abort(iStatus, "Start pthread error"); 
    } 
    // do some work 
    ... 
    //Cancel thread 
    void * retval; 
    iStatus = pthread_cancel(tid) 
    iStatus = pthread_join(tid; &retval); 
    if(iStatus){ 
     err_abort(iStatus,"Stop thread error"); 
    } 
    return iStatus; 
} 

其中程序運行,它停止在「iStatus =在pthread_join(TID1; & RETVAL );」無法繼續前進,我認爲線程可能會陷入僵局,但無法找到原因。我想在調用pthread_cancel()之後,線程將退出並返回到pthread_join(), 誰可以告訴我我的代碼出了什麼問題?

+0

我發現當我刪除「pthread_cleanup_push」和「pthread_cleanup_pop」時,每件事情都可以,但是我想知道原因 – user1383457

回答

1

不要把cleanup_push和_pop放在while循環中。不要多次打電話給他們。如果你看看它們,它們是在{}中包裝它們之間的代碼的宏。他們設置了一個在您調用pthread_cancel時使用的longjump。

+0

這是關鍵,非常感謝。 – user1383457

1

pthread_cleanup_pop(1)告訴pthread庫不僅從堆棧中彈出清理條目,而且還執行它。這樣的電話也會隱式調用:

pthread_mutex_unlock(&mutexCmd); 

既然你已經解鎖的互斥,即呼叫未定義的行爲(假定互斥鎖類型爲PTHREAD_MUTEX_NORMAL)。我想這個電話只是永遠不會回來或什麼。

請注意,您的代碼在處理清理時存在其他問題 - 如果您爲循環執行continue,則會再次調用pthread_cleanup_push()(或更多),這會添加另一個清理上下文。

可能還有其他問題(我不是很熟悉pthread_cancel())。

相關問題