2012-01-29 94 views
5

在我的應用程序中,主線程創建兩個連接的線程;一個通過在循環中調用scanf()等待用戶輸入,另一個通過在循環中調用accept()來偵聽傳入套接字連接。新的連接在分離的獨立線程中處理。通過信號中斷兩個阻塞線程

我希望程序在收到SIGINT信號時正常關閉。這意味着監聽線程應該停止接受新連接,等待當前正在服務連接的線程關閉,然後再等待。等待用戶輸入的線程也應該結束,從而允許主線程結束。

Scanf()和accept()都被阻塞,但可以被信號中斷,但發送到進程的信號只能由一個線程(AFAIK)處理。我的想法是阻止所有線程中的SIGINT信號,除了等待它的主線程。當它收到一個SIGINT時,它會發送SIGUSR1給兩個線程(一個在scanf()上阻塞,一個在accept()上阻塞),然後加入這些線程。

這是一個很好的解決方案嗎?有沒有更好的或者標準的方法來實現這一目標?

回答

5

像這樣的問題的規範解決方案是Thread Cancellation。當一個線程在作爲取消點的函數中被阻塞時,到達的取消請求將立即執行;否則,它在下一次線程調用一個取消點的函數時執行。

使用取消可能會很痛苦的唯一事情是它建立在異常處理模型上,而不是失敗返回。您需要在大多數時間保持取消阻止(並且僅在您想要處理取消的操作期間啓用它),或者在每個調用幀級別安裝取消清除處理程序(基本上,C中的半醜陋的異常處理程序)可能有中間狀態/分配/等等。清除你的線程被取消時。我個人更喜歡第一種方法,通常只需要安裝一個取消處理程序。

基於中斷信號的任何方法固有地具有競爭條件。如果信號是在調用阻塞函數之前發送的,那麼當信號處理程序返回時,阻塞函數將被調用並將無限期阻塞(因爲檢查「是否該退出?」已成功通過)。

+0

謝謝 - 我暗自希望你能回答這個問題!問題是,一旦一個線程被取消,例如在accept()上被阻塞時,它之後的任何邏輯都不會運行。我需要線程等待處理連接的分離線程,然後在退出之前釋放資源。我怎麼能做到這一點? – SlappyTheFish 2012-01-29 21:25:50

+0

啊,是pthread_cleanup_push()你的意思是清理處理程序?看起來它會做的伎倆。 – SlappyTheFish 2012-01-29 21:35:17

+0

是的,這就是你如何使用取消。 – 2012-01-29 23:04:46