timer_settime вызывает функцию обработчика в pthread на uClinux

У меня есть следующая функция, которая вызывается из pthread_create. Эта функция выполняет некоторую работу, устанавливает таймер, выполняет некоторую другую работу, а затем ждет, пока таймер не истечет, прежде чем снова выполнить цикл. Однако при первом запуске таймера по истечении его срока программа завершает работу, и я не совсем понимаю, почему. Он никогда не должен выходить из бесконечного цикла while. Основной поток ничего не получает из этого потока и наоборот (пока).

Я предполагаю, что у меня может быть что-то неправильно настроено с потоком, или таймер неправильно вызывает функцию обработчика. Возможно, изменение глобальной переменной IDLE из потока вызывает проблему.

Я хотел бы вызвать обработчик без сигналов, отсюда и использование SIGEV_THREAD_ID. Я все равно использую сигналы SIGSRx в основном потоке. Любые мысли о том, что я начал здесь, что может быть не так?

#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
    }
}

person wazilian    schedule 18.08.2014    source источник


Ответы (1)


Насколько я могу судить, вы не установили обработчик сигналов для SIGUSR1, поэтому по умолчанию он убивает процесс, когда на него воздействуют.

В любом случае, все это кажется мне чрезвычайно плохим дизайном:

  1. Цикл while даст вам 100% загрузку процессора в ожидании истечения таймера.

  2. Это не тот способ, которым вы используете SIGEV_THREAD_ID, и на самом деле SIGEV_THREAD_ID на самом деле не настроен для использования приложениями. Скорее это libc для внутреннего использования для реализации SIGEV_THREAD.

  3. Вы действительно не хотите использовать сигналы. Они грязные.

Если у вас есть потоки, почему вы просто не вызываете clock_nanosleep в цикле? Таймеры в основном полезны, когда вы не можете этого сделать, например. когда вы не можете использовать потоки.

person R.. GitHub STOP HELPING ICE    schedule 18.08.2014
comment
Я не обрабатывал SIGUSR1 в этом потоке, потому что использую его в основном потоке. Я согласен, что не хочу использовать сигналы с этим. Вся функция не завершена, и я понимаю, что цикл while является более/менее просто загруженным процессором. Я бы не стал держать это там. Я не знал, что SIGEV_THREAD_ID не настроен для такого типа работы. Я хотел бы, чтобы документация была более ясной по этому поводу. Если это так, я, должно быть, неправильно понял. Я хотел использовать таймер, а не функцию сна, потому что между запуском таймера и истечением срока его действия нужно выполнить некоторую работу. Спасибо за ответ. - person wazilian; 19.08.2014