Проблема с alarm() и SIGALRM в C

У меня проблема с SIGALRM, которая, кажется, не запускается. Я использую signal(), а не sigaction() для простоты кода.

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

volatile sig_atomic_t restartBool;

void    catch_alarm(int sig)
{
    fprintf(stderr, "ALARM CALLED\n");
    restartBool = 1;
}

int     main(void)
{

     int n, fd_in = 0;
     char newChar;

    signal(SIGALRM, catch_alarm);

    while (1) {                     /* main loop */

            restartBool = 0;

            // Set a timer before we start reading
            alarm(2);

            while (restartBool == 0 && (n = read(fd_in, &newChar, 1)) == 1) {       /* parse input */
                /* ..... */
            }
            fprintf(stderr, "EXITED THE LOOP");

            // Cancel the alarm/timer
            alarm(0);
    }
}

Что ж, оператор fprintf() в функции catch_alarm() никогда не вызывается, и я не уверен, почему (я работаю в Linux).

Любая помощь будет отличной,

Большое Вам спасибо,

Джари


person Jary    schedule 07.02.2011    source источник
comment
-1 за поддельный код. Код не компилируется как есть, и когда я добавляю int n, fd_in=0, newChar; в начало main, он работает нормально (сообщение печатается).   -  person R.. GitHub STOP HELPING ICE    schedule 08.02.2011
comment
fprintf не является реентерабельным: вызывать из обработчика сигнала небезопасно, потому что вы можете находиться в середине вызова к нему, когда сигнал доставлен.   -  person Adam Rosenfield    schedule 08.02.2011
comment
Извините, Р.., я пытался сделать код более кратким, я это исправил. У меня он не печатается, я слышал, что это может быть проблема с некоторыми версиями Linux на некоторых форумах, но я не уверен, что это может быть так. Он определенно ничего не печатает для меня.   -  person Jary    schedule 08.02.2011
comment
Спасибо Адам, я не думал об этом. Я просто храню его для тестирования, пока он не напечатает один раз, а затем я его удалю.   -  person Jary    schedule 08.02.2011
comment
У вас есть sleep или что-то подобное в цикле while?   -  person Hasturkun    schedule 08.02.2011
comment
Это действительно работает на другой машине, вы правы. Я могу использовать другую машину, так что моя проблема вроде как исправлена. Спасибо.   -  person Jary    schedule 08.02.2011
comment
@Jary: если это работает на одной машине, а не на другой, вам, вероятно, следует предположить, что в какой-то момент в будущем она перестанет работать. Я бы продолжил копать.   -  person John Zwinck    schedule 08.02.2011
comment
fprintf не является безопасным для асинхронных сигналов, но, похоже, это не проблема. Конечно, если вы вызовете неопределенное поведение таким образом, может произойти что угодно, но в реальном мире почти наверняка произойдет сбой или взаимоблокировка. Если вы хотите проверить, в этом ли проблема, используйте write(2, message\n, 8); вместо fprintf в обработчике сигнала.   -  person R.. GitHub STOP HELPING ICE    schedule 08.02.2011


Ответы (1)


Скорее всего, ваше чтение возвращает 0 (не осталось байтов) задолго до того, как сработает ваш таймер. IE, цикл завершается, потому что у вас закончились данные, а затем вы отменяете сигнал тревоги (который еще не сработал).

person Wes Hardaker    schedule 08.02.2011