From: Tobias Stoeckmann Date: Mon, 23 Feb 2026 18:51:25 +0000 (+0100) Subject: lib/pager: Use async-signal safe signal handler X-Git-Tag: v2.43-devel~48^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=89588ac31e48d25292406b932b6479f12e30bf42;p=thirdparty%2Futil-linux.git lib/pager: Use async-signal safe signal handler Accessing pager_process.pid from within a signal handler is, by strict C language interpretation, not signal safe. Wait for all children (and thus for pager_process.pid as well) instead. The current users dmesg and fdisk have no further children so this is a good compromise here. The signal handler is used for SIGINT, SIGHUP, SIGTERM, SIGQUIT. From a terminal perspective, these are normally intercepted by the child, not the parent. Since wait_for_pager is never reached by a signal handler anymore, a regular err() call is now possible. Just make sure that no exit function handler could ever loop endlessly. Signed-off-by: Tobias Stoeckmann --- diff --git a/lib/pager.c b/lib/pager.c index 3dc213dc9..b6321d2b0 100644 --- a/lib/pager.c +++ b/lib/pager.c @@ -109,9 +109,12 @@ static int wait_for_pager(void) do { waiting = waitpid(pager_process.pid, &status, 0); - if (waiting == -1 && errno != EINTR) - ul_sig_err(EXIT_FAILURE, "waitpid failed"); - } while (waiting == -1); + } while (waiting == -1 && errno == EINTR); + + pager_process.pid = 0; + + if (waiting == -1) + err(EXIT_FAILURE, "waitpid failed"); if (waiting == pager_process.pid && WIFEXITED(status)) return WEXITSTATUS(status); @@ -137,7 +140,10 @@ static void wait_for_pager_signal(int signo __attribute__ ((__unused__))) close(STDOUT_FILENO); close(STDERR_FILENO); - wait_for_pager(); + /* async-signal safe: wait for all children, including pager */ + while (wait(NULL) != -1 || errno == EINTR) + ; + _exit(EXIT_FAILURE); }