2013年9月18日水曜日

[debug][posix] sleep, usleepの知らないとはまる(かもしれない)恐ろしい仕様

POSIXのAPIであるsleep(), usleep()について、引数で指定した時間だけスリープしないで途中で起きてくることがある、という仕様はご存じでしょうか?
意外と知らずに使っている方が多いのでは、と思います。自分も知りませんでした。シグナルが発生すると引数で指定した時間を無視して関数を抜けてきます。

参考:


"The Open Group Base Specifications"のsleepのページにより詳しい説明が記載されていたので引用しておきます。
The sleep() function shall cause the calling thread to be suspended from execution until either the number of realtime seconds specified by the argument seconds has elapsed or a signal is delivered to the calling thread and its action is to invoke a signal-catching function or to terminate the process. The suspension time may be longer than requested due to the scheduling of other activity by the system.
If a SIGALRM signal is generated for the calling process during execution of sleep() and if the SIGALRM signal is being ignored or blocked from delivery, it is unspecified whether sleep() returns when the SIGALRM signal is scheduled. If the signal is being blocked, it is also unspecified whether it remains pending after sleep() returns or it is discarded.
If a SIGALRM signal is generated for the calling process during execution of sleep(), except as a result of a prior call to alarm(), and if the SIGALRM signal is not being ignored or blocked from delivery, it is unspecified whether that signal has any effect other than causing sleep() to return.
If a signal-catching function interrupts sleep() and examines or changes either the time a SIGALRM is scheduled to be generated, the action associated with the SIGALRM signal, or whether the SIGALRM signal is blocked from delivery, the results are unspecified.


この仕様を知ったきっかけですが、sqliteのsqlite3_busy_timeout()で3秒という時間を設定しているにもかかわらず、数百ミリ秒しかロックが解放されるのを待ってくれない、という不具合を追いかけていました。

このsleep()の仕様を知らず、バグの原因追及に思わぬ時間をとられました・・・。皆さんもsleep()の挙動がおかしい場合には、他のプロセス、スレッドから、シグナルが発射されていないかを疑ってみてください。


0 件のコメント:

コメントを投稿