From 735d7964b3dfa0f9925e3aa266b380f137685165 Mon Sep 17 00:00:00 2001 From: Mike Gilbert Date: Thu, 23 May 2024 15:28:39 -0400 Subject: [PATCH] openrc-shutdown: broadcast: simplify non-blocking logic Get rid of the setjmp/longjmp and just handle EINTR. This avoids messing with the stack and simplifies program flow. Bug: https://bugs.gentoo.org/923326 Signed-off-by: Mike Gilbert --- src/openrc-shutdown/broadcast.c | 44 ++++++++++++++------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/src/openrc-shutdown/broadcast.c b/src/openrc-shutdown/broadcast.c index f21ee95c4..f400c796c 100644 --- a/src/openrc-shutdown/broadcast.c +++ b/src/openrc-shutdown/broadcast.c @@ -14,11 +14,11 @@ */ +#include #include #include #include #include -#include #include #include #include @@ -37,14 +37,12 @@ # define _PATH_DEV "/dev/" #endif -static sigjmp_buf jbuf; - /* * Alarm handler */ -RC_NORETURN static void handler(int arg RC_UNUSED) +static void handler(int arg RC_UNUSED) { - siglongjmp(jbuf, 1); + /* do nothing */ } static void getuidtty(char **userp, char **ttyp) @@ -124,15 +122,11 @@ void broadcast(char *text) char *p; char *line = NULL; struct sigaction sa; + int fd; + FILE *tp; int flags; char *term = NULL; struct utmpx *utmp; - /* - * These are set across the sigsetjmp call, so they can't be stored on - * the stack, otherwise they might be clobbered. - */ - static int fd; - static FILE *tp; getuidtty(&user, &tty); @@ -159,6 +153,7 @@ void broadcast(char *text) if (fork() != 0) return; + /* Set up a noop signal handler to generate EINTR */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = handler; sigemptyset(&sa.sa_mask); @@ -179,24 +174,23 @@ void broadcast(char *text) } /* - * Open it non-delay + * Open it non-delay + * Set an alarm to generate EINTR in case we block. */ - if (sigsetjmp(jbuf, 1) == 0) { - alarm(2); - flags = O_WRONLY|O_NDELAY|O_NOCTTY; - if (file_isatty(term) && (fd = open(term, flags)) >= 0) { - if (isatty(fd) && (tp = fdopen(fd, "w")) != NULL) { - fputs(line, tp); - fputs(text, tp); - fflush(tp); - } + alarm(2); + flags = O_WRONLY|O_NDELAY|O_NOCTTY; + if (file_isatty(term) && (fd = open(term, flags)) >= 0) { + if (isatty(fd) && (tp = fdopen(fd, "w")) != NULL) { + if ((fputs(line, tp) == EOF || fputs(text, tp) == EOF) + && errno == EINTR) + /* Set another alarm for fclose */ + alarm(1); + fclose(tp); } + else + close(fd); } alarm(0); - if (fd >= 0) - close(fd); - if (tp != NULL) - fclose(tp); free(term); } endutxent();