В соответствии со стандартом, вы действительно не можете делать многое в обработчике сигналов. Все, что вы гарантированно сможете сделать в функции обработки сигналов, не вызывая неопределенного поведения, - это вызвать signal и присвоить значение энергозависимому статическому объекту типа sig_atomic_t .
Первые несколько раз, когда я запускал эту программу в Ubuntu Linux, выглядело, как будто ваш вызов alarm в обработчике сигналов не работал, поэтому цикл в main просто продолжал работать после первого сигнала тревоги , Когда я попробовал это позже, программа несколько раз запускала обработчик сигнала, а затем зависала. Все это согласуется с неопределенным поведением: иногда происходит сбой программы, а также различными более или менее интересными способами.
Нередко программы с неопределенным поведением по-разному работают в отладчике. Отладчик - это другая среда, и ваша программа и данные могут, например, быть размещены в памяти по-другому, поэтому ошибки могут проявляться по-другому, или не проявляться вовсе.
Я заставил программу работать, добавив переменную:
volatile sig_atomic_t got_interrupt = 0;
А потом я изменил ваш обработчик сигналов на этот очень простой:
void sig_alarm(int signo) {
got_interrupt = 1;
}
А затем я вставил фактическую работу в бесконечный цикл в main:
if (got_interrupt) {
got_interrupt = 0;
signal(SIGALRM, sig_alarm);
struct passwd *rootptr;
printf("in sig_alarm\n");
if ((rootptr = getpwnam("root")) == NULL)
perror("getpwnam error");
alarm(1);
}
Я думаю, что "apue", о котором вы говорите, это книга "Расширенное программирование в среде UNIX", которой у меня нет, поэтому я не знаю, если цель этого примера - показать, что вы не должны не возиться с вещами внутри обработчика сигналов или просто с тем, что сигналы могут вызвать проблемы, нарушая нормальную работу программы.