Попросили младшие курсы помочь с лабами по операционным системам... Кинули мне мой же исходник с претензиями, что работает криво. Сам я уже не помню насколько прога была рабочая, времени прошло уже 3 года.
Но проблема действительно есть: Первый вызов alarm() устанавливает таймер, в назначенное время приходит сигнал, обрабатывается, все довольны. Обработчик сигнала устанавливается обратно, снова вызывается alarm()... и все. На этом месте начинается бесконечный цикл, прерываемый только ^C.
Суть проги в кратце: компьютер играет сам с собой в кости. Визуализуется бросок крутящейся в терминале палочкой, длительность броска задается вышеозначенным алармом. Принимает два аргумента - время в секундах для каждого из 2 игроков.
Код:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
unsigned int i;
jmp_buf pos;
char *who[] = {"Com1: ", "Com2: "};
char *ind[] = {"|\b", "/\b", "-\b", "\\\b"};
char digit[] = {"1\n"};
void handler()
{
	static int j=0;
	digit[0] = '1' + i%6;
	write(1, digit, 2);
	longjmp(pos, ++j);
}
int main(int argc, char **argv)
{
	int time[2], j=0;
	if (argc<3 || (time[0] = atoi(argv[1]))<1 || (time[1] = atoi(argv[2]))<1) {
		write(1, "Usage: lab6_19 time1 time2\nTimes must be > 0\n", 45);
		exit(-1);
	}
	
	struct sigaction s;
	memset(&s, 0, sizeof(struct sigaction));
	s.sa_handler = handler;
	if ((j = setjmp(pos)) < 2) {
		sigaction(SIGALRM, &s, 0);
		alarm(time[j]);
		write(1, who[j], 6);
	}
	for (i=getpid()%6; j<2; i++) {
		write(1, ind[i%4], 2);
		usleep(250000);
	}
	exit(0);
}
Результат strace, наглядно иллюстрирующий, что сигнал повторно не приходит:
rt_sigaction(SIGALRM, {0x8048584, [], SA_RESETHAND}, NULL, 8) = 0
alarm(1)                                = 0
write(1, "Com1: "..., 6Com1: )                = 6
getpid()                                = 29333
write(1, "/\10"..., 2)                  = 2
nanosleep({0, 250000000}, NULL)         = 0
write(1, "-\10"..., 2)                  = 2
nanosleep({0, 250000000}, NULL)         = 0
write(1, "\\\10"..., 2)                 = 2
nanosleep({0, 250000000}, NULL)         = 0
write(1, "|\10"..., 2)                  = 2
nanosleep({0, 250000000}, 0)            = ? ERESTART_RESTARTBLOCK (To be restarted)
--- SIGALRM (Alarm clock) @ 0 (0) ---
write(1, "3\n"..., 23
)                   = 2
alarm(1)                                = 0
write(1, "Com2: "..., 6Com2: )                = 6
write(1, "/\10"..., 2)                  = 2
nanosleep({0, 250000000}, NULL)         = 0
write(1, "-\10"..., 2)                  = 2
nanosleep({0, 250000000}, NULL)         = 0
write(1, "\\\10"..., 2)                 = 2
nanosleep({0, 250000000}, NULL)         = 0
write(1, "|\10"..., 2)                  = 2
nanosleep({0, 250000000}, NULL)         = 0
write(1, "/\10"..., 2)                  = 2
nanosleep({0, 250000000}, NULL)         = 0
write(1, "-\10"..., 2)                  = 2
nanosleep({0, 250000000}, NULL)         = 0
write(1, "\\\10"..., 2)                 = 2
nanosleep({0, 250000000}, NULL)         = 0
write(1, "|\10"..., 2)                  = 2
... и далее до бесконечности
Куча write вместо printf и иже с ним - условие лаб.
