|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
From 8a7c93d858c342744adf481565d8bb03b9713dcf Mon Sep 17 00:00:00 2001
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
From: Lennart Poettering <lennart@poettering.net>
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
Date: Wed, 27 Aug 2014 21:42:20 +0200
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
Subject: [PATCH] util: fix minimal race where we might miss SIGTERMs when
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
forking off an agent
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
Before forking, block all signals, and unblock them afterwards. This way
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
the child will have them blocked, and we won't lose them.
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
---
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
src/shared/util.c | 35 +++++++++++++++++++++++------------
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
1 file changed, 23 insertions(+), 12 deletions(-)
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
diff --git a/src/shared/util.c b/src/shared/util.c
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
index 9e4ff85ffb..cf9d487b82 100644
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
--- a/src/shared/util.c
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+++ b/src/shared/util.c
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
@@ -5102,9 +5102,9 @@ int fd_inc_rcvbuf(int fd, size_t n) {
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
}
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- pid_t parent_pid, agent_pid;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- int fd;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
bool stdout_is_tty, stderr_is_tty;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ pid_t parent_pid, agent_pid;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ sigset_t ss, saved_ss;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
unsigned n, i;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
va_list ap;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
char **l;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
@@ -5112,16 +5112,25 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
assert(pid);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
assert(path);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- parent_pid = getpid();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
-
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
/* Spawns a temporary TTY agent, making sure it goes away when
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
* we go away */
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ parent_pid = getpid();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ /* First we temporarily block all signals, so that the new
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ * child has them blocked initially. This way, we can be sure
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ * that SIGTERMs are not lost we might send to the agent. */
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ assert_se(sigfillset(&ss) >= 0);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
agent_pid = fork();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- if (agent_pid < 0)
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ if (agent_pid < 0) {
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
return -errno;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ }
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
if (agent_pid != 0) {
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
*pid = agent_pid;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
return 0;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
}
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
@@ -5132,24 +5141,26 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
_exit(EXIT_FAILURE);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ /* Make sure we actually can kill the agent, if we need to, in
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ * case somebody invoked us from a shell script that trapped
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ * SIGTERM or so... */
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ reset_all_signal_handlers();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ reset_signal_mask();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
/* Check whether our parent died before we were able
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- * to set the death signal */
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ * to set the death signal and unblock the signals */
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
if (getppid() != parent_pid)
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
_exit(EXIT_SUCCESS);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
/* Don't leak fds to the agent */
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
close_all_fds(except, n_except);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- /* Make sure we actually can kill the agent, if we need to, in
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- * case somebody invoked us from a shell script that trapped
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- * SIGTERM or so... */
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- reset_all_signal_handlers();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- reset_signal_mask();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
-
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
stdout_is_tty = isatty(STDOUT_FILENO);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
stderr_is_tty = isatty(STDERR_FILENO);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
if (!stdout_is_tty || !stderr_is_tty) {
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ int fd;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
/* Detach from stdout/stderr. and reopen
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
* /dev/tty for them. This is important to
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
* ensure that when systemctl is started via
|