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 <tobias@stoeckmann.org>
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);
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);
}