Skip to content

Commit

Permalink
Sync with grandchild
Browse files Browse the repository at this point in the history
Without this, it's possible that father process exit with
0 before grandchild exit with error.

Signed-off-by: Qiang Huang <[email protected]>
  • Loading branch information
hqhq committed Nov 17, 2016
1 parent e7abf30 commit 16a2e8b
Showing 1 changed file with 23 additions and 6 deletions.
29 changes: 23 additions & 6 deletions libcontainer/nsenter/nsexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ enum sync_t {
SYNC_USERMAP_ACK = 0x41, /* Mapping finished by the parent. */
SYNC_RECVPID_PLS = 0x42, /* Tell parent we're sending the PID. */
SYNC_RECVPID_ACK = 0x43, /* PID was correctly received by parent. */
SYNC_CHILD_READY = 0x44, /* The grandchild is ready to return. */

/* XXX: This doesn't help with segfaults and other such issues. */
SYNC_ERR = 0xFF, /* Fatal error, no turning back. The error code follows. */
Expand Down Expand Up @@ -497,7 +498,7 @@ void nsexec(void)
* process.
*/
case JUMP_PARENT: {
int len;
int len, ready = 0;
pid_t child;
char buf[JSON_MAX];

Expand All @@ -509,8 +510,14 @@ void nsexec(void)
if (child < 0)
bail("unable to fork: child_func");

/* State machine for synchronisation with the children. */
while (true) {
/*
* State machine for synchronisation with the children.
*
* Father only return when both child and grandchild are
* ready, so we can receive all possible error codes
* generated by children.
*/
while (ready < 2) {
enum sync_t s;

/* This doesn't need to be global, we're in the parent. */
Expand Down Expand Up @@ -568,17 +575,22 @@ void nsexec(void)
}
}

/* Leave the loop. */
goto out;
ready++;
break;
case SYNC_RECVPID_ACK:
/* We should _never_ receive acks. */
kill(child, SIGKILL);
bail("failed to sync with child: unexpected SYNC_RECVPID_ACK");
break;
case SYNC_CHILD_READY:
ready++;
break;
default:
bail("unexpected sync value");
break;
}
}

out:
/* Send the init_func pid back to our parent. */
len = snprintf(buf, JSON_MAX, "{\"pid\": %d}\n", child);
if (len < 0) {
Expand Down Expand Up @@ -700,6 +712,7 @@ void nsexec(void)
* start_child() code after forking in the parent.
*/
int consolefd = config.consolefd;
enum sync_t s;

/* We're in a child and thus need to tell the parent if we die. */
syncfd = syncpipe[0];
Expand Down Expand Up @@ -730,6 +743,10 @@ void nsexec(void)
bail("failed to dup stderr");
}

s = SYNC_CHILD_READY;
if (write(syncfd, &s, sizeof(s)) != sizeof(s))
bail("failed to sync with patent: write(SYNC_CHILD_READY)");

/* Close sync pipes. */
close(syncpipe[0]);
close(syncpipe[1]);
Expand Down

0 comments on commit 16a2e8b

Please sign in to comment.