On Thu, Aug 14, 2025 at 10:17:18AM -0700, Steve Sistare wrote:
> Add a qemu_system_exec_request() hook that causes the main loop to exit and
> exec a command using the specified arguments.  This will be used during CPR
> to exec a new version of QEMU.
> 
> Signed-off-by: Steve Sistare <steven.sist...@oracle.com>
> ---
>  include/system/runstate.h |  3 +++
>  system/runstate.c         | 29 +++++++++++++++++++++++++++++
>  2 files changed, 32 insertions(+)
> 
> diff --git a/include/system/runstate.h b/include/system/runstate.h
> index 929379a..c005f49 100644
> --- a/include/system/runstate.h
> +++ b/include/system/runstate.h
> @@ -128,6 +128,8 @@ typedef enum WakeupReason {
>      QEMU_WAKEUP_REASON_OTHER,
>  } WakeupReason;
>  
> +typedef void (*qemu_exec_func)(char **exec_argv);
> +
>  void qemu_system_reset_request(ShutdownCause reason);
>  void qemu_system_suspend_request(void);
>  void qemu_register_suspend_notifier(Notifier *notifier);
> @@ -139,6 +141,7 @@ void qemu_register_wakeup_support(void);
>  void qemu_system_shutdown_request_with_code(ShutdownCause reason,
>                                              int exit_code);
>  void qemu_system_shutdown_request(ShutdownCause reason);
> +void qemu_system_exec_request(qemu_exec_func func, const strList *args);
>  void qemu_system_powerdown_request(void);
>  void qemu_register_powerdown_notifier(Notifier *notifier);
>  void qemu_register_shutdown_notifier(Notifier *notifier);
> diff --git a/system/runstate.c b/system/runstate.c
> index 6178b00..b4980ff 100644
> --- a/system/runstate.c
> +++ b/system/runstate.c
> @@ -41,6 +41,7 @@
>  #include "qapi/error.h"
>  #include "qapi/qapi-commands-run-state.h"
>  #include "qapi/qapi-events-run-state.h"
> +#include "qapi/type-helpers.h"
>  #include "qemu/accel.h"
>  #include "qemu/error-report.h"
>  #include "qemu/job.h"
> @@ -422,6 +423,8 @@ static NotifierList wakeup_notifiers =
>  static NotifierList shutdown_notifiers =
>      NOTIFIER_LIST_INITIALIZER(shutdown_notifiers);
>  static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE);
> +qemu_exec_func exec_func;
> +static char **exec_argv;
>  
>  ShutdownCause qemu_shutdown_requested_get(void)
>  {
> @@ -443,6 +446,11 @@ static int qemu_shutdown_requested(void)
>      return qatomic_xchg(&shutdown_requested, SHUTDOWN_CAUSE_NONE);
>  }
>  
> +static int qemu_exec_requested(void)
> +{
> +    return exec_argv != NULL;
> +}
> +
>  static void qemu_kill_report(void)
>  {
>      if (!qtest_driver() && shutdown_signal) {
> @@ -803,6 +811,23 @@ void qemu_system_shutdown_request(ShutdownCause reason)
>      qemu_notify_event();
>  }
>  
> +static void qemu_system_exec(void)
> +{
> +    exec_func(exec_argv);
> +
> +    /* exec failed */
> +    g_strfreev(exec_argv);
> +    exec_argv = NULL;
> +    exec_func = NULL;

Would this really happen?

If so, do we at least want to dump something?

> +}
> +
> +void qemu_system_exec_request(qemu_exec_func func, const strList *args)
> +{
> +    exec_func = func;
> +    exec_argv = strv_from_str_list(args);
> +    qemu_notify_event();
> +}
> +
>  static void qemu_system_powerdown(void)
>  {
>      qapi_event_send_powerdown();
> @@ -849,6 +874,10 @@ static bool main_loop_should_exit(int *status)
>      if (qemu_suspend_requested()) {
>          qemu_system_suspend();
>      }
> +    if (qemu_exec_requested()) {
> +        qemu_system_exec();
> +        return false;
> +    }

Some explanation of why it needs to be done explicitly here would be
helpful.  E.g., can we do exec inside a BH scheduled for the main thread?
What if we exec() directly in another thread (rather than the main loop
thread)?

>      request = qemu_shutdown_requested();
>      if (request) {
>          qemu_kill_report();
> -- 
> 1.8.3.1
> 

-- 
Peter Xu


Reply via email to