ラスタファクトリ ブログサイト
          clock_nanosleepを使ったタイマ処理
タイマを使って定期的にサーバにPOSTするプログラムを組んだ際、途中でタイマが止まってしまう不具合が発生しました。
これは定期実行のために使っていたsetitimerの設定がlibcurlのタイムアウト処理で上書きされてしまうのが原因でした。
setitimerはプロセスごとに固有なため、lubcurlを使うならsetitimerは使えません。というわけで、clock_nanosleepを使ってやってみました。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | void periodic_invoke (__time_t interval, void(*func)(void), bool* term) {   // パラメータチェック   assert((func != NULL) && "pointer func is NULL.");   assert((term != NULL) && "pointer terminator is NULL.");   // sleep_toに現在の時間をセット   struct timespec sleep_to;   clock_gettime(CLOCK_MONOTONIC, &sleep_to);   struct tm* tm;   // *termがtrueになったら終了   while (*term == false) {     // スリープ終了時間をinterval秒後にセット     sleep_to . tv_sec += interval;     // 関数を実行     func();     // sleep_toの時間になるまでまでスリープ     // シグナルでスリープを途中で抜けた場合に備えてループで回す     struct timespec now; // 現在の時間     while (1) {       // *termがtrueになっていればスリープ終了       if (*term == true) {         break;       }       // sleep_toまでスリープ       clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &sleep_to, NULL);       // sleep_toと現在の時間を比較       clock_gettime(CLOCK_MONOTONIC, &now);       // 秒がタイマ設定を超えていればスリープ終了       if (now . tv_sec > sleep_to . tv_sec) {         break;       // 秒が同じでナノ秒がタイマ設定以上ならスリープ終了       } else if (now . tv_sec == sleep_to . tv_sec && now . tv_nsec >= sleep_to . tv_nsec) {         break;       }     }   } } | 
interval秒ごとにfunc関数を呼び出します。
別スレッドやシグナルハンドラで*termがtrueにセットされるとループを抜けます。