From 8ce2afd6347dcf01e33fe1ff257e2b0fffa8edfe Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 14 Oct 2013 19:53:56 +0200 Subject: [PATCH] bus: make sure that we always keep a ref to the bus when we dispatch callbacks Otherwise the callback might unref the bus we are processing and destroy the object while we are processing it. --- src/libsystemd-bus/bus-internal.h | 6 ++++++ src/libsystemd-bus/bus-objects.c | 3 +++ src/libsystemd-bus/sd-bus.c | 1 + 3 files changed, 10 insertions(+) diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h index 6499d6b013a..31e10b2c273 100644 --- a/src/libsystemd-bus/bus-internal.h +++ b/src/libsystemd-bus/bus-internal.h @@ -294,3 +294,9 @@ bool bus_pid_changed(sd_bus *bus); for (char *_slash = ({ strcpy((prefix), (path)); streq((prefix), "/") ? NULL : strrchr((prefix), '/'); }) ; \ _slash && !(_slash[(_slash) == (prefix)] = 0); \ _slash = streq((prefix), "/") ? NULL : strrchr((prefix), '/')) + +/* If we are invoking callbacks of a bus object, ensure unreffing the + * bus from the callback doesn't destroy the object we are working + * on */ +#define BUS_DONT_DESTROY(bus) \ + _cleanup_bus_unref_ sd_bus *_dont_destroy_##bus = sd_bus_ref(bus) diff --git a/src/libsystemd-bus/bus-objects.c b/src/libsystemd-bus/bus-objects.c index cd56d13d6bf..9142fab37a9 100644 --- a/src/libsystemd-bus/bus-objects.c +++ b/src/libsystemd-bus/bus-objects.c @@ -1843,6 +1843,7 @@ int sd_bus_emit_properties_changed_strv( const char *interface, char **names) { + BUS_DONT_DESTROY(bus); char *prefix; int r; @@ -1987,6 +1988,8 @@ static int interfaces_added_append_one( } int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) { + BUS_DONT_DESTROY(bus); + _cleanup_bus_message_unref_ sd_bus_message *m = NULL; char **i; int r; diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 44c13d36a4f..ee5f3955695 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -1870,6 +1870,7 @@ null_message: } int sd_bus_process(sd_bus *bus, sd_bus_message **ret) { + BUS_DONT_DESTROY(bus); int r; /* Returns 0 when we didn't do anything. This should cause the