2012-03-17 187 views
0

我想在進程取消初始化完成之前取消線程,如下所示。pthread取消激活時間

rc2 = pthread_attr_init(&attr); 
ERR_IF(rc2 != 0); 

rc2 = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 
ERR_IF(rc2 != 0); 

rc2 = pthread_create(&destroy_thread, &attr, destroy_expired_sessions, NULL); 
ERR_IF(rc2 != 0); 
... 
rc2 = pthread_cancel(destroy_thread); 
ERR_IF(rc2 != 0); 

usleep(10); // without the sleep here, the real cancellation will be postponed. 

rc2 = authSessionListDeInit(); 
ERR_IF(rc2 != 0); 

... 

static void *destroy_expired_sessions(void *t) 
{ 
    int rc2 = 0; 

    (void)t; 

    pthread_cleanup_push(cleanup_handler, NULL); 

    rc2 = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 
    if (rc2 != 0) 
     AUTH_DEBUG5("pthread_setcancelstate(): rc2 == %d\n", rc2); 

    rc2 = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); 
    if (rc2 != 0) 
     AUTH_DEBUG5("pthread_setcanceltype(): rc2 == %d\n", rc2); 

    ... // real work of the thread is done here 
} 

的問題是,雖然PTHREAD_CANCEL_ASYNCHRONOUS在這裏設置,真正取消線程總是authSessionListDeInit(之後會發生),除非我強制usleep()函式之間。

我的理解是在取消請求通過pthread_cancel()發送後應該會發生取消,不是嗎?

如果我的理解不正確,如何確保在調用authSessionListDeInit()之前取消線程?

回答

1

docs

在目標線程的取消處理應異步相對於調用線程從 pthread_cancel可以返回()運行 。

因此,pthread_cancel可以在取消之前返回,這意味着您的假設是錯誤的。

除了使用pthread_cancel之外,您可以考慮使用取消標誌和/或條件變量在函數實際結束時發出信號的更流行和更安全的方法(帶有pthread_cancel的失敗風險)。

+1

或者您可以在調用'pthread_cancel'後等待同步對象(如信號量),並在完成清理退出時取消線程信號(例如,發佈信號量)。 – 2012-03-17 23:20:19

+0

因此,如果使用pthread_cancel(),看起來我沒有辦法知道何時會發生真正的線程取消,對吧?邁克爾,你能給我一個使用更流行和更安全的方法取消線程的例子嗎? – 2012-03-17 23:25:24

+0

@R:是的,一個sem_wait()可以跟在pthread_cancel()之後,等到它由線程取消清除處理程序(被更早地推入到線程的堆棧)的sem_post()處理。它會工作。只是覺得在這裏使用信號量有點矯枉過正。 :-) – 2012-03-17 23:30:06

0

不,取消發生在cancellation points,例如。系統調用,libc調用 - 查看函數的文檔(例如accept(),close())或者您可以看看here

+0

如果PTHREAD_CANCEL_DEFERRED設置爲取消類型,您說的是真實的,但在此我將該類型設置爲PTHREAD_CANCEL_ASYNCHRONOUS,這意味着線程可以隨時取消(通常,它將在收到取消請求後立即取消,但系統不保證這一點)。 – 2012-03-17 23:34:16