Last active
August 13, 2019 03:42
-
-
Save edef1c/db1e6b3e44d7d3b4ad20241e0bb532aa to your computer and use it in GitHub Desktop.
proof-of-concept of siglongjmp/ppoll-based signal handling in an event loop
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <err.h> | |
#include <errno.h> | |
#include <poll.h> | |
#include <setjmp.h> | |
#include <signal.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
static sigjmp_buf sig_buf; | |
static void sig_handler(int signo) { | |
siglongjmp(sig_buf, signo); | |
} | |
int main(void) { | |
sigset_t jesus, blocked; // none of you are free of sin | |
sigemptyset(&blocked); | |
sigaddset(&blocked, SIGINT); | |
sigprocmask(SIG_BLOCK, &blocked, &jesus); | |
int signo = sigsetjmp(sig_buf, 1); | |
if (signo) { | |
printf("caught signal %d\n", signo); | |
} else if (sigaction(SIGINT, &(struct sigaction) { .sa_handler = sig_handler }, NULL)) { | |
err(1, "signal"); | |
} | |
struct pollfd pfd = { | |
.fd = 0, | |
.events = POLLIN | |
}; | |
for (;;) { | |
int ret = ppoll(&pfd, 1, NULL, signo ? NULL : &jesus); | |
if (ret < 0) err(1, "ppoll"); | |
signo = 0; | |
if (pfd.revents & (POLLIN | POLLERR)) { | |
char buffer[32]; | |
int n; | |
do { n = read(pfd.fd, buffer, sizeof buffer); } | |
while (n < 0 && (errno == EAGAIN || errno == EINTR)); | |
if (n < 0) err(1, "read"); | |
write(1, buffer, n); // XXX: check the return value | |
} else if (pfd.revents & POLLHUP) { | |
break; | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment