From: David Woodhouse Date: Mon, 23 Jan 2023 15:33:08 +0000 (+0100) Subject: Fix BE watch firing X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=bf5a8754c9d9b87ce3fb2bc2a698de564b4f6cb6;p=people%2Fpauldu%2Fqemu.git Fix BE watch firing We can't do this recursively from *within* the node walk. The callers don't expect that, and we end up calling them with an invalid tree — we glibly declared "we hold the lock so we can steal children from the tree while we go down it, and nobody can notice", and that becomes untrue if we then call *back* into the backends which then call into the XS code again while it's in that state. Defer the watch firing until the main loop goes idle again, which is how it would happen for real Xen watches (which trigger via a pollable file descriptor in the main loop). Signed-off-by: David Woodhouse --- diff --git a/hw/i386/kvm/xen_xenstore.c b/hw/i386/kvm/xen_xenstore.c index 706062dbac..c9f2e01adf 100644 --- a/hw/i386/kvm/xen_xenstore.c +++ b/hw/i386/kvm/xen_xenstore.c @@ -1335,11 +1335,29 @@ struct qemu_xs_watch { void *opaque; }; +struct be_watch_event { + struct qemu_xs_watch *w; + char *path; +}; + +static gboolean delayed_be_watch_fn(gpointer _ev) +{ + struct be_watch_event *ev = _ev; + + ev->w->fn(ev->w->opaque, ev->path); + g_free(ev->path); + g_free(ev); + return false; +} + static void xs_be_watch_cb(void *opaque, const char *path, const char *token) { - struct qemu_xs_watch *w = opaque; + struct be_watch_event *ev = g_new0(struct be_watch_event, 1); + + ev->path = g_strdup(path); + ev->w = opaque; - w->fn(w->opaque, w->path); + g_idle_add(delayed_be_watch_fn, ev); } static struct qemu_xs_watch *xs_be_watch(struct qemu_xs_handle *h,