シグナル受信をepollで監視
Linuxのsignalfdを使ってシグナルをepollで監視する。
signalfd.c
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <sys/epoll.h> #include <sys/signalfd.h> #include <errno.h> #define MAX_EVENTS 10 #define RET_OK (0) #define RET_NG (-1) #define PERROR(X) \ {\ char __strerr[128] = {0};\ int errcode = errno;\ \ strerror_r(errcode, __strerr, sizeof(__strerr));\ printf(X " failed(%d:%s)\n", errcode, __strerr);\ } static int createSignalFd(int* sfd); static int waitSignalEvent(int sfd); int main(void) { int sfd = -1; int ret = RET_OK; do { ret = createSignalFd(&sfd); if (RET_OK != ret) { printf("createSignalFd() failed(%d)\n", ret); break; } ret = waitSignalEvent(sfd); if (RET_OK != ret) { printf("waitSignalEvent"); close(sfd); break; } close(sfd); } while(0); return 0; } static int createSignalFd(int* sfd) { int ret = RET_OK; sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGQUIT); do { if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { PERROR("sigprocmask()"); break; } *sfd = signalfd(-1, &mask, 0); if (*sfd < 0) { PERROR("signalfd()"); ret = RET_NG; break; } } while(0); return ret; } static int waitSignalEvent(int sfd) { int ret = RET_OK; int rc = 0; int epollfd = -1; int nfds = -1; struct epoll_event events[MAX_EVENTS]; struct epoll_event evt = { .events = EPOLLIN, .data = { .fd = sfd, }, }; epollfd = epoll_create(MAX_EVENTS); if (epollfd < 0) { PERROR("epoll_create()"); goto error_end; } rc = epoll_ctl(epollfd, EPOLL_CTL_ADD, sfd, &evt); if (rc != 0) { PERROR("epoll_ctl()"); close(epollfd); goto error_end; } for(;;) { nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); if (nfds < 0) { PERROR("epoll_wait()"); close(epollfd); break; } int fd = 0; for (fd = 0; fd < MAX_EVENTS; fd++) { if (events[fd].data.fd == sfd) { struct signalfd_siginfo fdsi; ssize_t sz = read(sfd, &fdsi, sizeof(fdsi)); if (sz < 0) { PERROR("read()"); close(epollfd); break; } printf("ssi_signo = %d\n", fdsi.ssi_signo); } } } close(epollfd); error_end: return ret; }
実行結果
$ gcc -std=gnu99 signalfd.c -o signalfd $ ./signalfd ssi_signo = 1 ssi_signo = 2 ssi_signo = 3 Terminated #別端末から $ killall -SIGHUP signalfd $ killall -SIGINT signalfd $ killall -SIGQUIT signalfd $ killall -SIGTERM signalfd