[lxc-devel] [PATCH] start.c: handle potential signal flood
Serge Hallyn
serge.hallyn at ubuntu.com
Thu Aug 29 15:44:41 UTC 2013
Signalfd does not guarantee that we'll get an event for every signal.
So if 3 tasks exit at the same time, we may get only one sigchld
event. Therefore, in signal_handler(), always check whether init has
exited. Do with with WNOWAIT so that we can still wait4 to cleanup
the init after lxc_poll() exists (rather than complicating the code).
Note - there is still a race in the kernel which can cause the
container init to become a defunct child of the host init (!). This
doesn't solve that, but is a potential (if very unlikely) race which
apw pointed out while we were trying to create a reproducer for the
kernel bug.
Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
src/lxc/start.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/lxc/start.c b/src/lxc/start.c
index f552e35..a574a8d 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -162,8 +162,10 @@ static int signal_handler(int fd, void *data,
struct lxc_epoll_descr *descr)
{
struct signalfd_siginfo siginfo;
+ siginfo_t info;
int ret;
pid_t *pid = data;
+ bool init_died = false;
ret = read(fd, &siginfo, sizeof(siginfo));
if (ret < 0) {
@@ -176,16 +178,23 @@ static int signal_handler(int fd, void *data,
return -1;
}
+ // check whether init is running
+ info.si_pid = 0;
+ ret = waitid(P_PID, *pid, &info, WEXITED | WNOWAIT | WNOHANG);
+ if (ret == 0 && info.si_pid == *pid) {
+ init_died = true;
+ }
+
if (siginfo.ssi_signo != SIGCHLD) {
kill(*pid, siginfo.ssi_signo);
INFO("forwarded signal %d to pid %d", siginfo.ssi_signo, *pid);
- return 0;
+ return init_died ? 1 : 0;
}
if (siginfo.ssi_code == CLD_STOPPED ||
siginfo.ssi_code == CLD_CONTINUED) {
INFO("container init process was stopped/continued");
- return 0;
+ return init_died ? 1 : 0;
}
/* more robustness, protect ourself from a SIGCHLD sent
@@ -193,7 +202,7 @@ static int signal_handler(int fd, void *data,
*/
if (siginfo.ssi_pid != *pid) {
WARN("invalid pid for SIGCHLD");
- return 0;
+ return init_died ? 1 : 0;
}
DEBUG("container init process exited");
--
1.8.3.2
More information about the lxc-devel
mailing list