天天看點

SIGINT信号導緻的usleep無效問題

如果你的程式有多個無限循環的子線程(周期性地完成某一任務),當程式結束的時候,為了能夠優雅地退出這些線程,通常都會先在子線程的while()無限循環中,設定一個(全局)運作标志,例如:

while (g_flag)

{

/

// do something periodically 

/

usleep(1000000); // sleep for 1 second 

}

然後,在主線程中可以注冊一個信号處理函數,在該函數中改變全局變量g_flag的值為false,這樣,向程式發送一個信号的時候,就可以使得子線程的運作标志改變,進而退出,然後程式也就可以退出了。

今天發現一個問題,在為SIGINT信号注冊的處理函數中,改變了全局運作标志的值,程式卻依然沒有退出,究其原因,發現是子線程中使用的usleep函數與觸發的信号發生了一段纏綿悱恻的愛情,進而導緻神經錯亂,然後就不正常了。

其實我們應該使用精度更高的nanosleep()函數,當然追求的并不一定是精度,而是使程式能正常運作。man nanosleep可見如下說明:

Compared to sleep(3) and usleep(3), nanosleep() has the advantage of not affecting any signals, it is standardized by POSIX, it provides higher timing resolution, and it allows to continue a sleep that has been interrupted by a signal more easily.

是以,盡量使用nanosleep函數來完成無限循環中的休眠任務,而不是用usleep()或sleep()。

改為使用nanosleep之後,發現程式正常了,可以優雅地退出各個子線程,然後再退出整個程式。

繼續閱讀