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 <dwmw@amazon.co.uk>
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,