0

pthread_create から呼び出される次の関数があります。この関数は、いくつかの作業を行い、タイマーを設定し、他の作業を行ってから、タイマーが期限切れになるのを待ってから、ループを再度実行します。ただし、タイマーの最初の実行時に、タイマーの有効期限が切れた後、プログラムが終了し、その理由が完全にはわかりません。無限 while ループから出てはなりません。メイン スレッドはこのスレッドから何もアクセスせず、その逆も同様です (今のところ)。

私の推測では、スレッドで何かが正しくセットアップされていないか、タイマーがハンドラー関数を正しく呼び出していない可能性があります。スレッドから IDLE グローバル変数を変更すると、問題が発生する可能性があります。

シグナルなしでハンドラーを呼び出したいので、SIGEV_THREAD_ID を使用します。とにかく、メインスレッドで SIGUSRx シグナルを使用しています。私がここで始めたことについて何か考えがありますか?何が間違っているのでしょうか?

#ifndef sigev_notify_thread_id
#define sigev_notify_thread_id _sigev_un._tid
#endif

volatile sig_atomic_t IDLE = 0;
timer_t timer_id;
struct sigevent sev;

void handler() {
    printf("Timer expired.\n");
    IDLE = 0;
}

void *thread_worker() {
    struct itimerspec ts;

    /* setup the handler for timer event */
    memset (&sev, 0, sizeof(struct sigevent));
    sev.sigev_notify = SIGEV_THREAD_ID;
    sev.sigev_value.sival_ptr = NULL;
    sev.sigev_notify_function = handler;
    sev.sigev_notify_attributes = NULL;
    sev.sigev_signo = SIGRTMIN + 1;
    sev.sigev_notify_thread_id = syscall(SYS_gettid);

    /* setup "idle" timer */
    ts.it_value.tv_sec = 55;
    ts.it_value.tv_nsec = 0;
    ts.it_interval.tv_sec = 0;
    ts.it_interval.tv_nsec = 0;

    if (timer_create(0, &sev, &timer_id) == -1) {
        printf("timer_create failed: %d: %s\n", errno, strerror(errno));
        exit(3);
    }

    while (1) {
        // do work here before timer gets started that takes 5 seconds

        while (IDLE);   /* wait here until timer_id expires */

        /* setup timer */
        if (timer_settime(timer_id, 0, &ts, NULL) == -1) {
            printf("timer_settime failed: %d\n", errno);
            exit(3);
        }

        IDLE = 1;

        // do work here while timer is running but that does not take 10 seconds
    }
}
4

1 に答える 1