Skip to content

Commit f156f73

Browse files
authored
Merge pull request #1154 from hqhq/sync_child
Sync with grandchild
2 parents a6e649f + 16a2e8b commit f156f73

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

libcontainer/nsenter/nsexec.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ enum sync_t {
3333
SYNC_USERMAP_ACK = 0x41, /* Mapping finished by the parent. */
3434
SYNC_RECVPID_PLS = 0x42, /* Tell parent we're sending the PID. */
3535
SYNC_RECVPID_ACK = 0x43, /* PID was correctly received by parent. */
36+
SYNC_CHILD_READY = 0x44, /* The grandchild is ready to return. */
3637

3738
/* XXX: This doesn't help with segfaults and other such issues. */
3839
SYNC_ERR = 0xFF, /* Fatal error, no turning back. The error code follows. */
@@ -500,7 +501,7 @@ void nsexec(void)
500501
* process.
501502
*/
502503
case JUMP_PARENT: {
503-
int len;
504+
int len, ready = 0;
504505
pid_t child;
505506
char buf[JSON_MAX];
506507

@@ -512,8 +513,14 @@ void nsexec(void)
512513
if (child < 0)
513514
bail("unable to fork: child_func");
514515

515-
/* State machine for synchronisation with the children. */
516-
while (true) {
516+
/*
517+
* State machine for synchronisation with the children.
518+
*
519+
* Father only return when both child and grandchild are
520+
* ready, so we can receive all possible error codes
521+
* generated by children.
522+
*/
523+
while (ready < 2) {
517524
enum sync_t s;
518525

519526
/* This doesn't need to be global, we're in the parent. */
@@ -571,17 +578,22 @@ void nsexec(void)
571578
}
572579
}
573580

574-
/* Leave the loop. */
575-
goto out;
581+
ready++;
582+
break;
576583
case SYNC_RECVPID_ACK:
577584
/* We should _never_ receive acks. */
578585
kill(child, SIGKILL);
579586
bail("failed to sync with child: unexpected SYNC_RECVPID_ACK");
580587
break;
588+
case SYNC_CHILD_READY:
589+
ready++;
590+
break;
591+
default:
592+
bail("unexpected sync value");
593+
break;
581594
}
582595
}
583596

584-
out:
585597
/* Send the init_func pid back to our parent. */
586598
len = snprintf(buf, JSON_MAX, "{\"pid\": %d}\n", child);
587599
if (len < 0) {
@@ -711,6 +723,7 @@ void nsexec(void)
711723
* start_child() code after forking in the parent.
712724
*/
713725
int consolefd = config.consolefd;
726+
enum sync_t s;
714727

715728
/* We're in a child and thus need to tell the parent if we die. */
716729
syncfd = syncpipe[0];
@@ -741,6 +754,10 @@ void nsexec(void)
741754
bail("failed to dup stderr");
742755
}
743756

757+
s = SYNC_CHILD_READY;
758+
if (write(syncfd, &s, sizeof(s)) != sizeof(s))
759+
bail("failed to sync with patent: write(SYNC_CHILD_READY)");
760+
744761
/* Close sync pipes. */
745762
close(syncpipe[0]);
746763
close(syncpipe[1]);

0 commit comments

Comments
 (0)