#include #include #include #include #include #include #include #include #include /* * signal and timer example * * timerTest.c */ /* * map timer code to a string * */ #define MAX_LEN_NAME 128 SLIST_HEAD(slisthead, entry) head = SLIST_HEAD_INITIALIZER(head); struct slisthead *headp; /* Singly-linked List head. */ struct entry { char *name; int code; SLIST_ENTRY(entry) entries; /* Singly-linked List. */ } *np; /* * signal handler * */ static int spankme; void sigHandler(int signo, siginfo_t * si, void * /* ucontext_t */ uap) { switch (signo) { case SIGALRM: /* timer timeout */ SLIST_FOREACH(np, &head, entries) { if (np && np->code == si->si_value.sival_int) { flockfile(stdout); printf("%s", np->name); fflush(stdout); funlockfile(stdout); break; } } if (np == NULL) printf("Timeout #%d, unknown.\n", si->si_value.sival_int); break; case SIGINFO: printf("no need to panic.\n"); break; case SIGINT: /* exit flag */ ++spankme; break; default: printf("sig:%d received.", signo); break; } } int main(int argc, char *argv[]) { SLIST_INIT(&head); /* timer pointers */ size_t nb_timers = 5; size_t cols = 0; if (argc > 1) { nb_timers = atoi(argv[1]); } if (nb_timers < 1) { fprintf(stderr, "Invalid timer number.\n"); abort(); } timer_t timerid[nb_timers]; char *names[nb_timers]; /* build text to display for each */ for (size_t i = 0; i < nb_timers; ++i) { names[i] = malloc(MAX_LEN_NAME); if (i == 0) { strncpy(names[i], ".", MAX_LEN_NAME); continue; } if (MAX_LEN_NAME <= snprintf(names[i], MAX_LEN_NAME, "%c", (char)('A' + i - 1))) { warnx("string %zu shorten", i); } } /* signal */ struct sigaction sa; sa.sa_handler = NULL; sa.sa_sigaction = &sigHandler; sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); if (sigaction(SIGINFO, &sa, NULL)) { warn("SIGNFO not caught."); } if (sigaction(SIGALRM, &sa, NULL)) { err(2, "sigaction:ALARM"); } if (sigaction(SIGINT, &sa, NULL)) { err(2, "sigaction:INTERRUPT"); } /* timer */ for (size_t i = 0; i < nb_timers; ++i) { if (timer_create(CLOCK_REALTIME, NULL, &timerid[i])) { warn("timer_create failed for %zu", i); continue; } /* 3 -> TIMER_MAX stored into timerid->oshandle */ np = malloc(sizeof(struct entry)); /* Insert at the head. */ np->code = timer_oshandle_np(timerid[i]); np->name = names[i]; SLIST_INSERT_HEAD(&head, np, entries); /* Set values and start timer */ struct itimerspec its; its.it_interval.tv_sec = 1 + i * 2; its.it_interval.tv_nsec = 0; its.it_value.tv_sec = its.it_interval.tv_sec; its.it_value.tv_nsec = 0; if (timer_settime(timerid[i], 0, &its, NULL)) { warn("timer_settime failed for %zu", i); } printf("Timer %s now created at interval %ld.\n", np->name, its.it_interval.tv_sec); } printf("waiting...\n"); for (; !spankme;) { pause(); if (++cols > 79) { cols = 0; printf("\n"); } } printf("\nbye.\n"); for (size_t i = 0; i < nb_timers; ++i) { timer_delete(timerid[i]); } while (!SLIST_EMPTY(&head)) { np = SLIST_FIRST(&head); SLIST_REMOVE_HEAD(&head, entries); free(np->name); free(np); } return EXIT_SUCCESS; }