diff --git a/src/main.c b/src/main.c index ea1d17e..6c63241 100644 --- a/src/main.c +++ b/src/main.c @@ -35,6 +35,7 @@ #include "runtime/forkipc.h" #include "runtime/proctitle.h" +#include "runtime/thread.h" #include "syscall/fuse.h" #include "syscall/path.h" @@ -510,6 +511,16 @@ int main(int argc, char **argv) */ int exit_code = vcpu_run_loop(vcpu, vexit, &g, verbose, timeout_sec); + /* Wait for worker vCPU threads to stop before tearing down guest memory. + * The main thread leaves the run loop as soon as it observes the + * exit_group flag, but sibling vCPU threads may still be mid-iteration in + * their own run loops (e.g. touching shim_globals). cleanup_main_resources + * unmaps the guest slab via guest_destroy, so a still-running worker would + * fault on freed guest memory and crash the host with SIGSEGV, masking the + * real exit code. thread_join_workers() is a no-op once the workers have + * already wound down (the common single-threaded case). */ + thread_join_workers(); + /* Tear down debugger state before freeing guest/vCPU resources. */ gdb_stub_shutdown();