@@ -260,7 +260,7 @@ pub fn run_supervisor(
260260 cmd : & [ String ] ,
261261 policy : OciPolicy ,
262262 pid_write_fd : i32 ,
263- ) -> Result < ( ) > {
263+ ) -> Result < Option < crate :: state :: ExitInfo > > {
264264 if cmd. is_empty ( ) {
265265 anyhow:: bail!( "OCI spec error: process.args is empty" ) ;
266266 }
@@ -316,7 +316,7 @@ async fn supervisor_main(
316316 mut sandbox : sandlock_core:: Sandbox ,
317317 sock_path : PathBuf ,
318318 pid_write_fd : i32 ,
319- ) -> Result < ( ) > {
319+ ) -> Result < Option < crate :: state :: ExitInfo > > {
320320 use tokio:: io:: { AsyncReadExt , AsyncWriteExt } ;
321321 use tokio:: net:: UnixListener ;
322322
@@ -405,7 +405,10 @@ async fn supervisor_main(
405405 // Notify the CLI: `OK <pid>` on success. Before OCI `start` there is no
406406 // workload yet, so the reported/recorded PID is sandlock-init's (the
407407 // container PID-1); OCI `start` updates state.pid to the workload PID.
408- pipe_write ( pid_write_fd, & format ! ( "OK {}" , init_pid) ) ;
408+ // Report two pids: the supervisor daemon's own pid (this process, which is
409+ // the containerd shim's child and what the shim reaps to detect exit) and
410+ // sandlock-init's pid (the OCI container init, recorded as state.pid).
411+ pipe_write ( pid_write_fd, & format ! ( "OK {} {}" , std:: process:: id( ) , init_pid) ) ;
409412
410413 {
411414 let mut state = SandboxState :: load ( id)
@@ -420,7 +423,7 @@ async fn supervisor_main(
420423 loop {
421424 let ( mut stream, _) = match listener. accept ( ) . await {
422425 Ok ( pair) => pair,
423- Err ( _) => return Ok ( ( ) ) ,
426+ Err ( _) => return Ok ( None ) ,
424427 } ;
425428
426429 let mut buf = vec ! [ 0u8 ; 4096 ] ;
@@ -472,25 +475,25 @@ async fn supervisor_main(
472475 serve_running_init ( id, & link, & mut sandbox, & listener, pid, main_exit)
473476 . await ;
474477 if let Ok ( mut s) = SandboxState :: load ( id) {
475- s. set_stopped ( exit_info) ;
478+ s. set_stopped ( exit_info. clone ( ) ) ;
476479 s. save ( ) . ok ( ) ;
477480 }
478- return Ok ( ( ) ) ;
481+ return Ok ( exit_info ) ;
479482 }
480483 Ok ( Resp :: Err { msg } ) => {
481484 let reply = serde_json:: to_vec ( & SupervisorReply :: Err { msg } )
482485 . unwrap_or_default ( ) ;
483486 let _ = stream. write_all ( & reply) . await ;
484487 let _ = stream. write_all ( b"\n " ) . await ;
485- return Ok ( ( ) ) ;
488+ return Ok ( None ) ;
486489 }
487490 other => {
488491 let msg = format ! ( "unexpected init reply to RunMain: {:?}" , other) ;
489492 let reply = serde_json:: to_vec ( & SupervisorReply :: Err { msg } )
490493 . unwrap_or_default ( ) ;
491494 let _ = stream. write_all ( & reply) . await ;
492495 let _ = stream. write_all ( b"\n " ) . await ;
493- return Ok ( ( ) ) ;
496+ return Ok ( None ) ;
494497 }
495498 }
496499 }
@@ -501,7 +504,7 @@ async fn supervisor_main(
501504 let reply = serde_json:: to_vec ( & SupervisorReply :: Ok ) . unwrap_or_default ( ) ;
502505 let _ = stream. write_all ( & reply) . await ;
503506 let _ = stream. write_all ( b"\n " ) . await ;
504- return Ok ( ( ) ) ;
507+ return Ok ( None ) ;
505508 }
506509 SupervisorCmd :: Checkpoint { dir } => {
507510 let reply = match sandbox. checkpoint ( ) . await {
0 commit comments