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.hal...@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


------------------------------------------------------------------------------
Learn the latest--Visual Studio 2012, SharePoint 2013, SQL 2012, more!
Discover the easy way to master current and previous Microsoft technologies
and advance your career. Get an incredible 1,500+ hours of step-by-step
tutorial videos with LearnDevNow. Subscribe today and save!
http://pubads.g.doubleclick.net/gampad/clk?id=58040911&iu=/4140/ostg.clktrk
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to