Проблема с сигналом / тревогой в Unix - PullRequest
0 голосов
/ 12 декабря 2010

Проблема должна быть довольно простой, но ... Я не могу понять, что это такое.Он должен продолжать печатать «alaarm» в течение некоторого времени, но он делает это только один раз, и тогда программа умирает:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>

void onAlarm();

void setupAlarm() {
 signal(SIGALRM, onAlarm);
 alarm(1);
}

void onAlarm() {
 setupAlarm();
 printf("alarmmmmmmmmmmmmmmmmm\n");
}

void main()
{
 setupAlarm();
 sleep(1000);
}

Что здесь может не так?Если убрать sleep(1000), программа мгновенно умирает (то есть, не показывая даже этого "alaaarm").

Ответ

Хорошо, работает следующий бит кода:

void onAlarm() {
    printf("alarmmmmmmmmmmmmmmmmm\n");
    alarm(1);
    sleep(1);
}

void main()
{
    signal(SIGALRM, onAlarm);
    alarm(1);
    sleep(2);
}

но я все еще обнимаю это и пытаюсь понять, почему мне нужно кодировать это так.

Ответы [ 4 ]

1 голос
/ 12 декабря 2010

sleep () прерывается сигналом, и errno устанавливается в EINTR.т.е. после вашего первого аварийного сигнала, sleep () возвращается, и ваша программа завершает работу, когда достигает конца main.

Обратите внимание, что вы не должны вызывать printf из обработчика сигнала, printf не является безопасным для сигнала в асинхронном режиме.

Могут быть и другие ошибки, см. здесь

Я не могу воспроизвести поведение вашего исходного кода, ничего не печатая, но если вы хотите знать, чтопродолжайте, просто запустите вашу программу под strace или аналогичными инструментами.

1 голос
/ 12 декабря 2010

Ой, мой предыдущий ответ был совершенно неверным. Посмотрите, что происходит, когда ваш onAlarm() называется:

  1. сбрасывает обработчик сигнала,

  2. сбрасывает будильник

  3. он снова начинает ждать после отмены предыдущего сигнала тревоги.

Какой путь к коду на самом деле достигает вашего вызова printf?

0 голосов
/ 12 декабря 2010

Я не знаю о вашей программе, но это работает для меня (код взят из здесь ):

#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

void catch_alarm (int sig);
void setupAlarm();

/* This flag controls termination of the main loop. */
volatile sig_atomic_t keep_going = 4;


/* The signal handler just clears the flag and re-enables itself. */
void catch_alarm (int sig) {
    keep_going--;
    printf("Alarm!!\n");

    if (keep_going) {
        setupAlarm();
    }
}

void setupAlarm() {
    alarm(1);
    sleep(1);
}

int main (int argc, char **argv) {
    signal(SIGALRM, catch_alarm);
    setupAlarm();

    return EXIT_SUCCESS;
}

Это напечатает четыре Alarm! и выйдет.

Вы можете заменить sleep(1); на while (keep_going); в main для того же результата.

Проблема в том, что alarm не выполняется внутри идентификатора процесса вашей программы, поэтому ваша программа может завершиться независимо от того, сработал сигнал тревоги или нет. Однако sleep переводит процесс вашей программы в , удерживает в течение n секунд, затем продолжает. Без какого-либо способа «приостановить» процесс или сохранить процесс живым в ожидании тревоги, он просто умрет, выполнив все, что должно было быть выполнено. Даже используя поток, без sleep(), while (...) и т. Д. и a pthread_join(), процесс не будет ждать вашего сигнала тревоги и просто завершится (умрет). Поэтому вам нужно каким-то образом поддерживать процесс в ожидании запуска сигнала, иначе он не будет работать.

0 голосов
/ 12 декабря 2010

Ну, для начала вы говорите своей среде генерировать SIGALRM через секунду, затем выходите через секунду.Попробуйте увеличить время ожидания до двух секунд.

...