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