@@ -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. */
@@ -497,7 +498,7 @@ void nsexec(void)
497498 * process.
498499 */
499500 case JUMP_PARENT : {
500- int len ;
501+ int len , ready = 0 ;
501502 pid_t child ;
502503 char buf [JSON_MAX ];
503504
@@ -509,8 +510,14 @@ void nsexec(void)
509510 if (child < 0 )
510511 bail ("unable to fork: child_func" );
511512
512- /* State machine for synchronisation with the children. */
513- while (true) {
513+ /*
514+ * State machine for synchronisation with the children.
515+ *
516+ * Father only return when both child and grandchild are
517+ * ready, so we can receive all possible error codes
518+ * generated by children.
519+ */
520+ while (ready < 2 ) {
514521 enum sync_t s ;
515522
516523 /* This doesn't need to be global, we're in the parent. */
@@ -568,17 +575,22 @@ void nsexec(void)
568575 }
569576 }
570577
571- /* Leave the loop. */
572- goto out ;
578+ ready ++ ;
579+ break ;
573580 case SYNC_RECVPID_ACK :
574581 /* We should _never_ receive acks. */
575582 kill (child , SIGKILL );
576583 bail ("failed to sync with child: unexpected SYNC_RECVPID_ACK" );
577584 break ;
585+ case SYNC_CHILD_READY :
586+ ready ++ ;
587+ break ;
588+ default :
589+ bail ("unexpected sync value" );
590+ break ;
578591 }
579592 }
580593
581- out :
582594 /* Send the init_func pid back to our parent. */
583595 len = snprintf (buf , JSON_MAX , "{\"pid\": %d}\n" , child );
584596 if (len < 0 ) {
@@ -700,6 +712,7 @@ void nsexec(void)
700712 * start_child() code after forking in the parent.
701713 */
702714 int consolefd = config .consolefd ;
715+ enum sync_t s ;
703716
704717 /* We're in a child and thus need to tell the parent if we die. */
705718 syncfd = syncpipe [0 ];
@@ -730,6 +743,10 @@ void nsexec(void)
730743 bail ("failed to dup stderr" );
731744 }
732745
746+ s = SYNC_CHILD_READY ;
747+ if (write (syncfd , & s , sizeof (s )) != sizeof (s ))
748+ bail ("failed to sync with patent: write(SYNC_CHILD_READY)" );
749+
733750 /* Close sync pipes. */
734751 close (syncpipe [0 ]);
735752 close (syncpipe [1 ]);
0 commit comments