如果你的程式有多個無限循環的子線程(周期性地完成某一任務),當程式結束的時候,為了能夠優雅地退出這些線程,通常都會先在子線程的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之後,發現程式正常了,可以優雅地退出各個子線程,然後再退出整個程式。