When using --daemonize, the initial lead process will fork a child and then wait to be notified that setup is complete via a pipe, before it exits. When using --preconfig there is an extra call to main_loop() before the notification is done from os_setup_post(). Thus the parent process won't exit until the mgmt application connects to the monitor and tells QEMU to leave the RUN_STATE_PRECONFIG. The mgmt application won't connect to the monitor until daemonizing has completed though.
This is a chicken and egg problem, leading to deadlock at startup. The only viable way to fix this is to call os_setup_post() before the early main_loop() call when --preconfig is used. This has the downside that any errors from this point onwards won't be handled well by the mgmt application, because it will think QEMU has started successfully, so not be expecting an abrupt exit. Moving as much user input validation as possible to before the main_loop() call might help, but mgmt application should stop assuming that QEMU has started successfuly and use other means to collect errors from QEMU (logfile). Signed-off-by: Daniel P. Berrangé <berra...@redhat.com> Signed-off-by: Igor Mammedov <imamm...@redhat.com> --- v5: * use original Daniel's patch [1], but addapt it to apply on top of "[PATCH v3 1/2] cli: Don't run early event loop if no --preconfig was specified" with extra comment and massage commit message a little bit. CC: berra...@redhat.com CC: mre...@redhat.com CC: pbonz...@redhat.com CC: ehabk...@redhat.com CC: ldok...@redhat.com CC: ebl...@redhat.com --- vl.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/vl.c b/vl.c index fa44138..ee359e6 100644 --- a/vl.c +++ b/vl.c @@ -3038,6 +3038,7 @@ int main(int argc, char **argv, char **envp) Error *err = NULL; bool list_data_dirs = false; char *dir, **dirs; + bool os_setup_post_done = false; typedef struct BlockdevOptions_queue { BlockdevOptions *bdo; Location loc; @@ -4578,6 +4579,13 @@ int main(int argc, char **argv, char **envp) parse_numa_opts(current_machine); /* do monitor/qmp handling at preconfig state if requested */ + if (!preconfig_exit_requested && is_daemonized()) { + /* signal parent QEMU to exit, libvirt treats it as a sign + * that monitor socket is ready to accept connections + */ + os_setup_post(); + os_setup_post_done = true; + } main_loop(); /* from here on runstate is RUN_STATE_PRELAUNCH */ @@ -4707,8 +4715,10 @@ int main(int argc, char **argv, char **envp) } accel_setup_post(current_machine); - os_setup_post(); + if (!os_setup_post_done) { + os_setup_post(); + } main_loop(); gdbserver_cleanup(); -- 2.7.4