Merge pull request #1154 from hqhq/sync_child

Sync with grandchild
This commit is contained in:
Daniel, Dao Quang Minh 2016-11-23 09:10:00 -08:00 committed by GitHub
commit f156f73c2a
1 changed files with 23 additions and 6 deletions

View File

@ -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. */
@ -500,7 +501,7 @@ void nsexec(void)
* process.
*/
case JUMP_PARENT: {
int len;
int len, ready = 0;
pid_t child;
char buf[JSON_MAX];
@ -512,8 +513,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. */
@ -571,17 +578,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) {
@ -711,6 +723,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];
@ -741,6 +754,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]);