2011-08-19 47 views

回答

4

這真的取決於你在哪個系統下運行。例如,如果您在符合POSIX的系統下運行並且線程可以取消,那麼當您取消線程時,recv()調用將被中斷,因爲它是一個取消點。

如果你使用的是老式插座實現,你可以設置你的線程像SIGUSR1並希望大家都不信號處理其他任何人想它和信號,因爲的recv()將中斷的信號。如果可能的話,你最好的選擇是不要阻塞。

+0

取消似乎是一個有前途的想法。線程的取消點是否有任何文檔可用?我看到[鏈接](http://www.mkssoftware.com/docs/man3/pthread_cancel.3.asp)它沒有列出任何套接字相關的調用。或者'recv()'反過來使用'read()'等其他調用,例如 – jogabonito

+0

@jogabonito如果你的系統符合posix並且使用符合posix的套接字,它將會是。 [posix取消點數](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_05_02) –

3

我不認爲關閉參與阻塞操作插座是終止操作的安全保障方式。例如,kernel.org警告黑暗:

這可能是不明智的關閉文件描述符,而他們可能會在 通過使用在同一過程中的其他線程的系統調用。由於 文件描述符可能會被重複使用,有一些模糊的競爭條件 可能會導致意想不到的副作用。

  • 相反,你可以使用一個信號,使recv失敗,EINTR (確保未啓用SA_RESTART)。您可以將信號發送到 特定線程與pthread_kill

  • 您可以啓用插槽上SO_RCVTIMEO開始的recv 調用之前

個人而言,我通常會盡量避開所有的信號污穢的,但是這是一個可行的選擇。

+0

+1爲kernel.org警告.. – jogabonito

2

你有一對夫婦的該選項。信號會中斷讀取操作,所以您只需確保信號消失即可。 recv操作應該失敗,錯誤編號爲EINTR。

最簡單的方法是設置一個計時器超時一些例如之後中斷自己的過程30秒:

itimerval timer 
timeval time; 
time.tv_sec = 30; 
time.tv_usec = 0; 
timer.it_value = time; 
if(setitimer(ITIMER_REAL, &timer, NULL) != 0) 
    printf("failed to start timer\n"); 

你會在指定時間後得到一個SIGALRM,這會打斷你的阻塞操作,給你重複操作或退出的機會。

2

,而另一個線程是不能解除分配共享資源,也可能使用它。在實踐中,你會發現你甚至無法編寫代碼來執行你的建議。

想一想。當你去打電話close,你怎麼可能知道另一個線程實際上被阻止在recv?如果它要調用recv,但是接着另一個線程調用socket並獲取剛纔關閉的描述符?現在,該線程不但不會檢測到任何錯誤,而且還會在錯誤的套接字上調用recv

可能有一個很好的方法來解決你的外部問題,你需要退出阻塞UDP套接字讀取的原因。也有幾個醜陋的黑客可用。基本的方法是使套接字非阻塞,而不是阻塞UDP套接字讀取,僞造阻塞讀取selectpoll。然後你可以用幾種方法中止這個循環:

一種方法是select超時並在select返回時檢查'abort'標誌。

另一種方法是在管道的讀取端也是select。發送一個字節到管道來中止select

1

如果POSIX complient系統,你可以嘗試監視你的線程: 在pthread_create與功能,使你的的recvpthread_cond_signal會剛過,然後返回。
調用線程使pthread_cond_timedwait具有所需的超時值,並在timed_out時終止被調用的線程。