Handle signals consistently in the event loop

master
Curtis McEnroe 2018-11-30 19:45:34 -05:00
parent 9d769111ae
commit 414f928ac5
No known key found for this signature in database
GPG Key ID: CEA2F97ADCFCD77C
2 changed files with 39 additions and 13 deletions

3
chat.h
View File

@ -20,6 +20,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdnoreturn.h>
#include <time.h> #include <time.h>
#include <wchar.h> #include <wchar.h>
@ -43,7 +44,7 @@ void selfJoin(const char *join);
void eventWait(const char *argv[static 2]); void eventWait(const char *argv[static 2]);
void eventPipe(const char *argv[static 2]); void eventPipe(const char *argv[static 2]);
void eventLoop(void); noreturn void eventLoop(void);
struct Tag { struct Tag {
size_t id; size_t id;

49
event.c
View File

@ -14,16 +14,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <assert.h>
#include <err.h> #include <err.h>
#include <errno.h>
#include <poll.h> #include <poll.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdnoreturn.h>
#include <string.h> #include <string.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sysexits.h> #include <sysexits.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h>
#include "chat.h" #include "chat.h"
@ -86,8 +88,7 @@ static void pipeRead(void) {
} }
} }
static void sigchld(int sig) { static void handleChild(void) {
(void)sig;
int status; int status;
pid_t pid = wait(&status); pid_t pid = wait(&status);
if (pid < 0) err(EX_OSERR, "wait"); if (pid < 0) err(EX_OSERR, "wait");
@ -99,16 +100,31 @@ static void sigchld(int sig) {
spawn.wait = false; spawn.wait = false;
} }
static void sigint(int sig) { static void handleInterrupt(void) {
(void)sig;
input(TagStatus, "/quit"); input(TagStatus, "/quit");
uiExit(); uiExit();
exit(EX_OK); exit(EX_OK);
} }
void eventLoop(void) { static sig_atomic_t sig[NSIG];
signal(SIGINT, sigint); static void handler(int n) {
signal(SIGCHLD, sigchld); sig[n] = 1;
}
noreturn void eventLoop(void) {
sigset_t mask;
sigemptyset(&mask);
struct sigaction sa = {
.sa_handler = handler,
.sa_mask = mask,
.sa_flags = SA_RESTART,
};
sigaction(SIGCHLD, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
struct sigaction curses;
sigaction(SIGWINCH, &sa, &curses);
assert(!(curses.sa_flags & SA_SIGINFO));
int irc = ircConnect(); int irc = ircConnect();
@ -118,6 +134,17 @@ void eventLoop(void) {
{ -1, POLLIN, 0 }, { -1, POLLIN, 0 },
}; };
for (;;) { for (;;) {
if (sig[SIGCHLD]) handleChild();
if (sig[SIGINT]) handleInterrupt();
if (sig[SIGWINCH]) {
curses.sa_handler(SIGWINCH);
uiRead();
uiDraw();
}
sig[SIGCHLD] = 0;
sig[SIGINT] = 0;
sig[SIGWINCH] = 0;
nfds_t nfds = 2; nfds_t nfds = 2;
if (spawn.wait) nfds = 1; if (spawn.wait) nfds = 1;
if (spawn.pipe) { if (spawn.pipe) {
@ -127,10 +154,8 @@ void eventLoop(void) {
int ready = poll(fds, nfds, -1); int ready = poll(fds, nfds, -1);
if (ready < 0) { if (ready < 0) {
if (errno != EINTR) err(EX_IOERR, "poll"); if (errno == EINTR) continue;
uiRead(); err(EX_IOERR, "poll");
uiDraw();
continue;
} }
if (fds[0].revents) ircRead(); if (fds[0].revents) ircRead();