Skip to content

Commit

Permalink
Pass back the pid of runc:[1:CHILD] so we can wait on it
Browse files Browse the repository at this point in the history
This allows the libcontainer to automatically clean up runc:[1:CHILD]
processes created as part of nsenter.

Signed-off-by: Alex Fang <littlelightlittlefire@gmail.com>
  • Loading branch information
LittleLightLittleFire committed Jul 5, 2017
1 parent 3a5b963 commit 0d21c21
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 7 deletions.
3 changes: 2 additions & 1 deletion libcontainer/init_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ const (
)

type pid struct {
Pid int `json:"pid"`
Pid int `json:"pid"`
PidFirstChild int `json:"pid_first"`
}

// network is an internal struct used to setup container networks.
Expand Down
17 changes: 11 additions & 6 deletions libcontainer/nsenter/nsexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ void nsexec(void)
*/
case JUMP_PARENT: {
int len;
pid_t child;
pid_t child, first_child = -1;
char buf[JSON_MAX];
bool ready = false;

Expand Down Expand Up @@ -607,18 +607,18 @@ void nsexec(void)
}
break;
case SYNC_RECVPID_PLS: {
pid_t old = child;
first_child = child;

/* Get the init_func pid. */
if (read(syncfd, &child, sizeof(child)) != sizeof(child)) {
kill(old, SIGKILL);
kill(first_child, SIGKILL);
bail("failed to sync with child: read(childpid)");
}

/* Send ACK. */
s = SYNC_RECVPID_ACK;
if (write(syncfd, &s, sizeof(s)) != sizeof(s)) {
kill(old, SIGKILL);
kill(first_child, SIGKILL);
kill(child, SIGKILL);
bail("failed to sync with child: write(SYNC_RECVPID_ACK)");
}
Expand Down Expand Up @@ -666,8 +666,13 @@ void nsexec(void)
}
}

/* Send the init_func pid back to our parent. */
len = snprintf(buf, JSON_MAX, "{\"pid\": %d}\n", child);
/*
* Send the init_func pid and the pid of the first child back to our parent.
*
* We need to send both back because we can't reap the first child we created (CLONE_PARENT).
* It becomes the responsibility of our parent to reap the first child.
*/
len = snprintf(buf, JSON_MAX, "{\"pid\": %d, \"pid_first\": %d}\n", child, first_child);
if (len < 0) {
kill(child, SIGKILL);
bail("unable to generate JSON for child pid");
Expand Down
20 changes: 20 additions & 0 deletions libcontainer/process_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,16 @@ func (p *setnsProcess) execSetns() error {
p.cmd.Wait()
return newSystemErrorWithCause(err, "reading pid from init pipe")
}

// Clean up the zombie parent process
firstChildProcess, err := os.FindProcess(pid.PidFirstChild)
if err != nil {
return err
}
if _, err := firstChildProcess.Wait(); err != nil {
return err
}

process, err := os.FindProcess(pid.Pid)
if err != nil {
return err
Expand Down Expand Up @@ -224,6 +234,16 @@ func (p *initProcess) execSetns() error {
p.cmd.Wait()
return err
}

// Clean up the zombie parent process
firstChildProcess, err := os.FindProcess(pid.PidFirstChild)
if err != nil {
return err
}
if _, err := firstChildProcess.Wait(); err != nil {
return err
}

process, err := os.FindProcess(pid.Pid)
if err != nil {
return err
Expand Down

0 comments on commit 0d21c21

Please sign in to comment.