On 9/15/2025 12:35 PM, Peter Xu wrote:
On Fri, Sep 12, 2025 at 10:49:23AM -0400, Steven Sistare wrote:
On 9/9/2025 11:51 AM, Peter Xu wrote:
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)?

A BH is a good idea, thanks.
It only requires a few lines of code, and no globals.
I will drop this patch and add a BH to patch "migration: cpr-exec mode".

That would be better, thanks.

Then, what happens if we exec() in the migration thread directly?  IOW, is
BH required (to serialize with something happening in the main thread), or
just looks slightly more clean when exec happens in the main thread?

These info would be great to be put into commit message, but if there's no
obvious reason, IMHO we _could_ exec() directly in the migration thread, as
I don't see whatever to be synchronized in the main thread..  Anyway, if we
want to exec(), IMHO it would be best as straightforward as possible.

A direct exec is not desirable for 2 reasons.

One is that cpr_exec_notifier is called in the middle of processing 
MIG_EVENT_PRECOPY_DONE
notifiers, and some notifiers may fall in the list after cpr_exec_notifier, and 
would never
be called.

Two is that cpr_exec_notifier is not called in migration_thread, it is called 
from a bh:
  migration_bh_dispatch_bh -> migration_cleanup -> migration_call_notifiers -> 
cpr_exec_notifier
so it is cleanest to post another bh to do the actual exec.

I will add those notes to the commit message.

- Steve


Reply via email to