From 780950a2ba584fae3381abeb3d1a5f42b8bedbcb Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 22 Jul 2015 11:16:44 +0200 Subject: Revert "build-sys: hide magic section variables from exported symbols" This reverts commit aac7c5ed8bc6ffaba417b9c0b87bcf342865431b. This visibility bug originated in ld.gold and has been fixed upstream: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=5417c94d1a944d1a27f99240e5d62a6d7cd324f1 --- src/libsystemd/sd-bus/bus-error.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c index 64a5a972ae..dac157be16 100644 --- a/src/libsystemd/sd-bus/bus-error.c +++ b/src/libsystemd/sd-bus/bus-error.c @@ -70,11 +70,9 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = { SD_BUS_ERROR_MAP_END }; -/* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section. - * Hide them; for currently unknown reasons they get exported to the shared libries - * even without being listed in the sym file. */ -extern const sd_bus_error_map __start_BUS_ERROR_MAP[] _hidden_; -extern const sd_bus_error_map __stop_BUS_ERROR_MAP[] _hidden_; +/* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section */ +extern const sd_bus_error_map __start_BUS_ERROR_MAP[]; +extern const sd_bus_error_map __stop_BUS_ERROR_MAP[]; /* Additional maps registered with sd_bus_error_add_map() are in this * NULL terminated array */ -- cgit v1.2.3-54-g00ecf From ca2f6384aa2076576b316c7253964be90b102d96 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 Aug 2016 18:13:36 -0400 Subject: core: rename cg_unified() to cg_all_unified() A following patch will update cgroup handling so that the systemd controller (/sys/fs/cgroup/systemd) can use the unified hierarchy even if the kernel resource controllers are on the legacy hierarchies. This would require distinguishing whether all controllers are on cgroup v2 or only the systemd controller is. In preparation, this patch renames cg_unified() to cg_all_unified(). This patch doesn't cause any functional changes. --- src/basic/cgroup-util.c | 30 +++++++++++++++--------------- src/basic/cgroup-util.h | 2 +- src/cgls/cgls.c | 2 +- src/cgtop/cgtop.c | 10 +++++----- src/core/cgroup.c | 16 ++++++++-------- src/core/manager.c | 2 +- src/core/scope.c | 2 +- src/core/service.c | 2 +- src/core/unit.c | 2 +- src/libsystemd/sd-bus/test-bus-creds.c | 2 +- src/nspawn/nspawn-cgroup.c | 4 ++-- src/nspawn/nspawn-mount.c | 4 ++-- src/nspawn/nspawn.c | 2 +- 13 files changed, 40 insertions(+), 40 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 25ef8a5c76..5473fec0dd 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -623,7 +623,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch if (!cg_controller_is_valid(controller)) return -EINVAL; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; @@ -651,7 +651,7 @@ static int controller_is_accessible(const char *controller) { if (!cg_controller_is_valid(controller)) return -EINVAL; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified > 0) { @@ -869,7 +869,7 @@ int cg_set_task_access( if (r < 0) return r; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified) @@ -893,7 +893,7 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) { assert(path); assert(pid >= 0); - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified == 0) { @@ -969,7 +969,7 @@ int cg_install_release_agent(const char *controller, const char *agent) { assert(agent); - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified) /* doesn't apply to unified hierarchy */ @@ -1020,7 +1020,7 @@ int cg_uninstall_release_agent(const char *controller) { _cleanup_free_ char *fs = NULL; int r, unified; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified) /* Doesn't apply to unified hierarchy */ @@ -1076,7 +1076,7 @@ int cg_is_empty_recursive(const char *controller, const char *path) { if (controller && (isempty(path) || path_equal(path, "/"))) return false; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; @@ -1962,7 +1962,7 @@ int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path return r; /* If we are in the unified hierarchy, we are done now */ - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified > 0) @@ -1992,7 +1992,7 @@ int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_m if (r < 0) return r; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified > 0) @@ -2044,7 +2044,7 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to return r; } - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified > 0) @@ -2077,7 +2077,7 @@ int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root) if (r < 0) return r; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified > 0) @@ -2103,7 +2103,7 @@ int cg_mask_supported(CGroupMask *ret) { * includes controllers we can make sense of and that are * actually accessible. */ - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified > 0) { @@ -2226,7 +2226,7 @@ int cg_kernel_controllers(Set *controllers) { static thread_local int unified_cache = -1; -int cg_unified(void) { +int cg_all_unified(void) { struct statfs fs; /* Checks if we support the unified hierarchy. Returns an @@ -2264,7 +2264,7 @@ int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p) { if (supported == 0) return 0; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (!unified) /* on the legacy hiearchy there's no joining of controllers defined */ @@ -2303,7 +2303,7 @@ bool cg_is_unified_wanted(void) { /* If the hierarchy is already mounted, then follow whatever * was chosen for it. */ - unified = cg_unified(); + unified = cg_all_unified(); if (unified >= 0) return unified; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index a509a1775c..5fa856affc 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -225,7 +225,7 @@ int cg_kernel_controllers(Set *controllers); bool cg_ns_supported(void); -int cg_unified(void); +int cg_all_unified(void); void cg_unified_flush(void); bool cg_is_unified_wanted(void); diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index dcb5912b83..adf488e8e1 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -166,7 +166,7 @@ static int get_cgroup_root(char **ret) { static void show_cg_info(const char *controller, const char *path) { - if (cg_unified() <= 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER)) + if (cg_all_unified() <= 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER)) printf("Controller %s; ", controller); printf("Control group %s:\n", isempty(path) ? "/" : path); diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 6045ae0437..aba17c9829 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -213,7 +213,7 @@ static int process( uint64_t new_usage; nsec_t timestamp; - if (cg_unified() > 0) { + if (cg_all_unified() > 0) { const char *keys[] = { "usage_usec", NULL }; _cleanup_free_ char *val = NULL; @@ -273,7 +273,7 @@ static int process( } else if (streq(controller, "memory")) { _cleanup_free_ char *p = NULL, *v = NULL; - if (cg_unified() <= 0) + if (cg_all_unified() <= 0) r = cg_get_path(controller, path, "memory.usage_in_bytes", &p); else r = cg_get_path(controller, path, "memory.current", &p); @@ -293,11 +293,11 @@ static int process( if (g->memory > 0) g->memory_valid = true; - } else if ((streq(controller, "io") && cg_unified() > 0) || - (streq(controller, "blkio") && cg_unified() <= 0)) { + } else if ((streq(controller, "io") && cg_all_unified() > 0) || + (streq(controller, "blkio") && cg_all_unified() <= 0)) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; - bool unified = cg_unified() > 0; + bool unified = cg_all_unified() > 0; uint64_t wr = 0, rd = 0; nsec_t timestamp; diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 910a64b4da..7c6fc01c0e 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -665,7 +665,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { bool has_weight = cgroup_context_has_cpu_weight(c); bool has_shares = cgroup_context_has_cpu_shares(c); - if (cg_unified() > 0) { + if (cg_all_unified() > 0) { uint64_t weight; if (has_weight) @@ -846,7 +846,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { } if ((mask & CGROUP_MASK_MEMORY) && !is_root) { - if (cg_unified() > 0) { + if (cg_all_unified() > 0) { uint64_t max = c->memory_max; if (cgroup_context_has_unified_memory_config(c)) @@ -1019,7 +1019,7 @@ CGroupMask unit_get_own_mask(Unit *u) { e = unit_get_exec_context(u); if (!e || exec_context_maintains_privileges(e) || - cg_unified() > 0) + cg_all_unified() > 0) return _CGROUP_MASK_ALL; } @@ -1245,7 +1245,7 @@ int unit_watch_cgroup(Unit *u) { return 0; /* Only applies to the unified hierarchy */ - r = cg_unified(); + r = cg_all_unified(); if (r < 0) return log_unit_error_errno(u, r, "Failed detect whether the unified hierarchy is used: %m"); if (r == 0) @@ -1645,7 +1645,7 @@ int unit_watch_all_pids(Unit *u) { if (!u->cgroup_path) return -ENOENT; - if (cg_unified() > 0) /* On unified we can use proper notifications */ + if (cg_all_unified() > 0) /* On unified we can use proper notifications */ return 0; return unit_watch_pids_in_path(u, u->cgroup_path); @@ -1755,7 +1755,7 @@ int manager_setup_cgroup(Manager *m) { if (r < 0) return log_error_errno(r, "Cannot find cgroup mount point: %m"); - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m"); if (unified > 0) @@ -1953,7 +1953,7 @@ int unit_get_memory_current(Unit *u, uint64_t *ret) { if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0) return -ENODATA; - if (cg_unified() <= 0) + if (cg_all_unified() <= 0) r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v); else r = cg_get_attribute("memory", u->cgroup_path, "memory.current", &v); @@ -1998,7 +1998,7 @@ static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) { if (!u->cgroup_path) return -ENODATA; - if (cg_unified() > 0) { + if (cg_all_unified() > 0) { const char *keys[] = { "usage_usec", NULL }; _cleanup_free_ char *val = NULL; uint64_t us; diff --git a/src/core/manager.c b/src/core/manager.c index c20e185d78..108591c464 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -766,7 +766,7 @@ static int manager_setup_cgroups_agent(Manager *m) { if (!MANAGER_IS_SYSTEM(m)) return 0; - if (cg_unified() > 0) /* We don't need this anymore on the unified hierarchy */ + if (cg_all_unified() > 0) /* We don't need this anymore on the unified hierarchy */ return 0; if (m->cgroups_agent_fd < 0) { diff --git a/src/core/scope.c b/src/core/scope.c index b278aed3d6..7c72bb7091 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -441,7 +441,7 @@ static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) { /* If the PID set is empty now, then let's finish this off (On unified we use proper notifications) */ - if (cg_unified() <= 0 && set_isempty(u->pids)) + if (cg_all_unified() <= 0 && set_isempty(u->pids)) scope_notify_cgroup_empty_event(u); } diff --git a/src/core/service.c b/src/core/service.c index 4a37702f52..29e53867bf 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2866,7 +2866,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { /* If the PID set is empty now, then let's finish this off (On unified we use proper notifications) */ - if (cg_unified() <= 0 && set_isempty(u->pids)) + if (cg_all_unified() <= 0 && set_isempty(u->pids)) service_notify_cgroup_empty_event(u); } diff --git a/src/core/unit.c b/src/core/unit.c index 952604e0db..b24c32569c 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3695,7 +3695,7 @@ int unit_kill_context( * there we get proper events. Hence rely on * them.*/ - if (cg_unified() > 0 || + if (cg_all_unified() > 0 || (detect_container() == 0 && !unit_cgroup_delegate(u))) wait_for_exit = true; diff --git a/src/libsystemd/sd-bus/test-bus-creds.c b/src/libsystemd/sd-bus/test-bus-creds.c index e9ef483bdd..82237af115 100644 --- a/src/libsystemd/sd-bus/test-bus-creds.c +++ b/src/libsystemd/sd-bus/test-bus-creds.c @@ -27,7 +27,7 @@ int main(int argc, char *argv[]) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; int r; - if (cg_unified() == -ENOMEDIUM) { + if (cg_all_unified() == -ENOMEDIUM) { puts("Skipping test: /sys/fs/cgroup/ not available"); return EXIT_TEST_SKIP; } diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c index b1580236c9..ea3cab513c 100644 --- a/src/nspawn/nspawn-cgroup.c +++ b/src/nspawn/nspawn-cgroup.c @@ -70,7 +70,7 @@ int sync_cgroup(pid_t pid, bool unified_requested) { const char *fn; int unified, r; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m"); @@ -132,7 +132,7 @@ int create_subcgroup(pid_t pid, bool unified_requested) { if (!unified_requested) return 0; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m"); if (unified == 0) diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 803caef3dd..b5d83d481a 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -721,7 +721,7 @@ static int mount_legacy_cgns_supported( return log_error_errno(errno, "Failed to mount /sys/fs/cgroup: %m"); } - if (cg_unified() > 0) + if (cg_all_unified() > 0) goto skip_controllers; controllers = set_new(&string_hash_ops); @@ -813,7 +813,7 @@ static int mount_legacy_cgns_unsupported( return log_error_errno(errno, "Failed to mount /sys/fs/cgroup: %m"); } - if (cg_unified() > 0) + if (cg_all_unified() > 0) goto skip_controllers; controllers = set_new(&string_hash_ops); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index fcf14bba4c..429b6ddc4f 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -332,7 +332,7 @@ static int detect_unified_cgroup_hierarchy(void) { } /* Otherwise inherit the default from the host system */ - r = cg_unified(); + r = cg_all_unified(); if (r < 0) return log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m"); -- cgit v1.2.3-54-g00ecf From ae1a2efa8b72c30b46528fa6469ce6686527dec7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 Aug 2016 14:58:09 +0200 Subject: sd-bus: add a "recursive" mode to sd_bus_track This adds an optional "recursive" counting mode to sd_bus_track. If enabled adding the same name multiple times to an sd_bus_track object is counted individually, so that it also has to be removed the same number of times before it is gone again from the tracking object. This functionality is useful for implementing local ref counted objects that peers make take references on. --- src/libsystemd/libsystemd.sym | 8 ++ src/libsystemd/sd-bus/bus-track.c | 188 +++++++++++++++++++++++++++++++------- src/systemd/sd-bus.h | 8 +- 3 files changed, 172 insertions(+), 32 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 542254295c..ae60e346eb 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -500,3 +500,11 @@ LIBSYSTEMD_231 { global: sd_event_get_iteration; } LIBSYSTEMD_230; + +LIBSYSTEMD_232 { +global: + sd_bus_track_set_recursive; + sd_bus_track_get_recursive; + sd_bus_track_count_name; + sd_bus_track_count_sender; +} LIBSYSTEMD_231; diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 1f436fe560..6ece2244c2 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -24,6 +24,12 @@ #include "bus-track.h" #include "bus-util.h" +struct track_item { + unsigned n_ref; + char *name; + sd_bus_slot *slot; +}; + struct sd_bus_track { unsigned n_ref; sd_bus *bus; @@ -32,8 +38,9 @@ struct sd_bus_track { Hashmap *names; LIST_FIELDS(sd_bus_track, queue); Iterator iterator; - bool in_queue; - bool modified; + bool in_queue:1; + bool modified:1; + bool recursive:1; }; #define MATCH_PREFIX \ @@ -56,6 +63,20 @@ struct sd_bus_track { _x; \ }) +static struct track_item* track_item_free(struct track_item *i) { + + if (!i) + return NULL; + + sd_bus_slot_unref(i->slot); + free(i->name); + free(i); + + return NULL; +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free); + static void bus_track_add_to_queue(sd_bus_track *track) { assert(track); @@ -79,6 +100,25 @@ static void bus_track_remove_from_queue(sd_bus_track *track) { track->in_queue = false; } +static int bus_track_remove_name_fully(sd_bus_track *track, const char *name) { + struct track_item *i; + + assert(track); + assert(name); + + i = hashmap_remove(track->names, name); + if (!i) + return 0; + + track_item_free(i); + + if (hashmap_isempty(track->names)) + bus_track_add_to_queue(track); + + track->modified = true; + return 1; +} + _public_ int sd_bus_track_new( sd_bus *bus, sd_bus_track **track, @@ -121,7 +161,7 @@ _public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) { } _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { - const char *n; + struct track_item *i; if (!track) return NULL; @@ -133,8 +173,8 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { return NULL; } - while ((n = hashmap_first_key(track->names))) - sd_bus_track_remove_name(track, n); + while ((i = hashmap_steal_first(track->names))) + track_item_free(i); bus_track_remove_from_queue(track); hashmap_free(track->names); @@ -156,49 +196,64 @@ static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus if (r < 0) return 0; - sd_bus_track_remove_name(track, name); + bus_track_remove_name_fully(track, name); return 0; } _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { - _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; - _cleanup_free_ char *n = NULL; + _cleanup_(track_item_freep) struct track_item *n = NULL; + struct track_item *i; const char *match; int r; assert_return(track, -EINVAL); assert_return(service_name_is_valid(name), -EINVAL); + i = hashmap_get(track->names, name); + if (i) { + if (track->recursive) { + unsigned k = track->n_ref + 1; + + if (k < track->n_ref) /* Check for overflow */ + return -EOVERFLOW; + + track->n_ref = k; + } + + bus_track_remove_from_queue(track); + return 0; + } + r = hashmap_ensure_allocated(&track->names, &string_hash_ops); if (r < 0) return r; - n = strdup(name); + n = new0(struct track_item, 1); if (!n) return -ENOMEM; + n->name = strdup(name); + if (!n->name) + return -ENOMEM; /* First, subscribe to this name */ - match = MATCH_FOR_NAME(n); - r = sd_bus_add_match(track->bus, &slot, match, on_name_owner_changed, track); + match = MATCH_FOR_NAME(name); + r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track); if (r < 0) return r; - r = hashmap_put(track->names, n, slot); - if (r == -EEXIST) - return 0; + r = hashmap_put(track->names, n->name, n); if (r < 0) return r; - /* Second, check if it is currently existing, or maybe - * doesn't, or maybe disappeared already. */ - r = sd_bus_get_name_creds(track->bus, n, 0, NULL); + /* Second, check if it is currently existing, or maybe doesn't, or maybe disappeared already. */ + r = sd_bus_get_name_creds(track->bus, name, 0, NULL); if (r < 0) { - hashmap_remove(track->names, n); + hashmap_remove(track->names, name); return r; } + n->n_ref = 1; n = NULL; - slot = NULL; bus_track_remove_from_queue(track); track->modified = true; @@ -207,37 +262,48 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { } _public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) { - _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; - _cleanup_free_ char *n = NULL; + struct track_item *i; assert_return(name, -EINVAL); - if (!track) + if (!track) /* Treat a NULL track object as an empty track object */ return 0; - slot = hashmap_remove2(track->names, (char*) name, (void**) &n); - if (!slot) - return 0; + if (!track->recursive) + return bus_track_remove_name_fully(track, name); - if (hashmap_isempty(track->names)) - bus_track_add_to_queue(track); + i = hashmap_get(track->names, name); + if (!i) + return -EUNATCH; + if (i->n_ref <= 0) + return -EUNATCH; - track->modified = true; + i->n_ref--; + + if (i->n_ref <= 0) + return bus_track_remove_name_fully(track, name); return 1; } _public_ unsigned sd_bus_track_count(sd_bus_track *track) { - if (!track) + + if (!track) /* Let's consider a NULL object equivalent to an empty object */ return 0; + /* This signature really should have returned an int, so that we can propagate errors. But well, ... Also, note + * that this returns the number of names being watched, and multiple references to the same name are not + * counted. */ + return hashmap_size(track->names); } _public_ const char* sd_bus_track_contains(sd_bus_track *track, const char *name) { - assert_return(track, NULL); assert_return(name, NULL); + if (!track) /* Let's consider a NULL object equivalent to an empty object */ + return NULL; + return hashmap_get(track->names, (void*) name) ? name : NULL; } @@ -273,6 +339,9 @@ _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) { assert_return(track, -EINVAL); assert_return(m, -EINVAL); + if (sd_bus_message_get_bus(m) != track->bus) + return -EINVAL; + sender = sd_bus_message_get_sender(m); if (!sender) return -EINVAL; @@ -283,9 +352,14 @@ _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) { _public_ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m) { const char *sender; - assert_return(track, -EINVAL); assert_return(m, -EINVAL); + if (!track) /* Treat a NULL track object as an empty track object */ + return 0; + + if (sd_bus_message_get_bus(m) != track->bus) + return -EINVAL; + sender = sd_bus_message_get_sender(m); if (!sender) return -EINVAL; @@ -335,3 +409,55 @@ _public_ void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) { return ret; } + +_public_ int sd_bus_track_set_recursive(sd_bus_track *track, int b) { + assert_return(track, -EINVAL); + + if (track->recursive == !!b) + return 0; + + if (!hashmap_isempty(track->names)) + return -EBUSY; + + track->recursive = b; + return 0; +} + +_public_ int sd_bus_track_get_recursive(sd_bus_track *track) { + assert_return(track, -EINVAL); + + return track->recursive; +} + +_public_ int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m) { + const char *sender; + + assert_return(m, -EINVAL); + + if (!track) /* Let's consider a NULL object equivalent to an empty object */ + return 0; + + if (sd_bus_message_get_bus(m) != track->bus) + return -EINVAL; + + sender = sd_bus_message_get_sender(m); + if (!sender) + return -EINVAL; + + return sd_bus_track_count_name(track, sender); +} + +_public_ int sd_bus_track_count_name(sd_bus_track *track, const char *name) { + struct track_item *i; + + assert_return(service_name_is_valid(name), -EINVAL); + + if (!track) /* Let's consider a NULL object equivalent to an empty object */ + return 0; + + i = hashmap_get(track->names, name); + if (!i) + return 0; + + return i->n_ref; +} diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 295989cd69..0305c56a8c 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -438,8 +438,14 @@ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m); int sd_bus_track_add_name(sd_bus_track *track, const char *name); int sd_bus_track_remove_name(sd_bus_track *track, const char *name); +int sd_bus_track_set_recursive(sd_bus_track *track, int b); +int sd_bus_track_get_recursive(sd_bus_track *track); + unsigned sd_bus_track_count(sd_bus_track *track); -const char* sd_bus_track_contains(sd_bus_track *track, const char *names); +int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m); +int sd_bus_track_count_name(sd_bus_track *track, const char *name); + +const char* sd_bus_track_contains(sd_bus_track *track, const char *name); const char* sd_bus_track_first(sd_bus_track *track); const char* sd_bus_track_next(sd_bus_track *track); -- cgit v1.2.3-54-g00ecf From 05a98afd3e0513de50c5949b7fa50ff0989d68bc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 Aug 2016 18:12:01 +0200 Subject: core: add Ref()/Unref() bus calls for units This adds two (privileged) bus calls Ref() and Unref() to the Unit interface. The two calls may be used by clients to pin a unit into memory, so that various runtime properties aren't flushed out by the automatic GC. This is necessary to permit clients to race-freely acquire runtime results (such as process exit status/code or accumulated CPU time) on successful service termination. Ref() and Unref() are fully recursive, hence act like the usual reference counting concept in C. Taking a reference is a privileged operation, as this allows pinning units into memory which consumes resources. Transient units may also gain a reference at the time of creation, via the new AddRef property (that is only defined for transient units at the time of creation). --- man/systemctl.xml | 12 +-- src/core/dbus-manager.c | 57 +++++++++++ src/core/dbus-unit.c | 155 +++++++++++++++++++++++++++++- src/core/dbus-unit.h | 8 +- src/core/dbus.c | 71 +++++++------- src/core/dbus.h | 5 +- src/core/job.c | 17 ++-- src/core/job.h | 4 +- src/core/manager.c | 27 +++--- src/core/org.freedesktop.systemd1.conf | 8 ++ src/core/unit.c | 52 +++++++--- src/core/unit.h | 7 ++ src/libsystemd/sd-bus/bus-common-errors.c | 1 + src/libsystemd/sd-bus/bus-common-errors.h | 1 + 14 files changed, 341 insertions(+), 84 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/man/systemctl.xml b/man/systemctl.xml index fde4f4f3bb..7e0ac9613a 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -642,13 +642,13 @@ list-units PATTERN... - List units that systemd has loaded. This includes units that - are either referenced directly or through a dependency, or units that were active in the - past and have failed. By default only units which are active, have pending jobs, or have + List units that systemd has loaded. This includes units that are either referenced + directly or through a dependency, units that are pinned by applications programmatically, or units that + were active in the past and have failed. By default only units which are active, have pending jobs, or have failed are shown; this can be changed with option . If one or more - PATTERNs are specified, only units matching one of them are - shown. The units that are shown are additionally filtered by - and if those options are specified. + PATTERNs are specified, only units matching one of them are shown. The units + that are shown are additionally filtered by and if those + options are specified. This is the default command. diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index ef05a75a8b..ea7ced2fd0 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -643,6 +643,54 @@ static int method_set_unit_properties(sd_bus_message *message, void *userdata, s return bus_unit_method_set_properties(message, u, error); } +static int method_ref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_load_unit(m, name, NULL, error, &u); + if (r < 0) + return r; + + r = bus_unit_check_load_state(u, error); + if (r < 0) + return r; + + return bus_unit_method_ref(message, u, error); +} + +static int method_unref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_load_unit(m, name, NULL, error, &u); + if (r < 0) + return r; + + r = bus_unit_check_load_state(u, error); + if (r < 0) + return r; + + return bus_unit_method_unref(message, u, error); +} + static int reply_unit_info(sd_bus_message *reply, Unit *u) { _cleanup_free_ char *unit_path = NULL, *job_path = NULL; Unit *following; @@ -781,6 +829,13 @@ static int transient_unit_from_message( if (r < 0) return r; + /* If the client asked for it, automatically add a reference to this unit. */ + if (u->bus_track_add) { + r = bus_unit_track_add_sender(u, message); + if (r < 0) + return log_error_errno(r, "Failed to watch sender: %m"); + } + /* Now load the missing bits of the unit we just created */ unit_add_to_load_queue(u); manager_dispatch_load_queue(m); @@ -2211,6 +2266,8 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RefUnit", "s", NULL, method_ref_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnrefUnit", "s", NULL, method_unref_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetUnitProcesses", "s", "a(sus)", method_get_unit_processes, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 89e56a2e51..1b86bdde43 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -418,6 +418,7 @@ static int bus_verify_manage_units_async_full( const char *verb, int capability, const char *polkit_message, + bool interactive, sd_bus_message *call, sd_bus_error *error) { @@ -433,7 +434,15 @@ static int bus_verify_manage_units_async_full( details[7] = GETTEXT_PACKAGE; } - return bus_verify_polkit_async(call, capability, "org.freedesktop.systemd1.manage-units", details, false, UID_INVALID, &u->manager->polkit_registry, error); + return bus_verify_polkit_async( + call, + capability, + "org.freedesktop.systemd1.manage-units", + details, + interactive, + UID_INVALID, + &u->manager->polkit_registry, + error); } int bus_unit_method_start_generic( @@ -486,6 +495,7 @@ int bus_unit_method_start_generic( verb, CAP_SYS_ADMIN, job_type < _JOB_TYPE_MAX ? polkit_message_for_job[job_type] : NULL, + true, message, error); if (r < 0) @@ -558,6 +568,7 @@ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error * "kill", CAP_KILL, N_("Authentication is required to kill '$(unit)'."), + true, message, error); if (r < 0) @@ -588,6 +599,7 @@ int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus "reset-failed", CAP_SYS_ADMIN, N_("Authentication is required to reset the \"failed\" state of '$(unit)'."), + true, message, error); if (r < 0) @@ -620,6 +632,7 @@ int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_b "set-property", CAP_SYS_ADMIN, N_("Authentication is required to set properties on '$(unit)'."), + true, message, error); if (r < 0) @@ -634,6 +647,53 @@ int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_b return sd_bus_reply_method_return(message, NULL); } +int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + r = mac_selinux_unit_access_check(u, message, "start", error); + if (r < 0) + return r; + + r = bus_verify_manage_units_async_full( + u, + "ref", + CAP_SYS_ADMIN, + NULL, + false, + message, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = bus_unit_track_add_sender(u, message); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + r = bus_unit_track_remove_sender(u, message); + if (r == -EUNATCH) + return sd_bus_error_setf(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet."); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_VTABLE_START(0), @@ -715,6 +775,8 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Ref", NULL, NULL, bus_unit_method_ref, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Unref", NULL, NULL, bus_unit_method_unref, SD_BUS_VTABLE_UNPRIVILEGED), /* Obsolete properties or obsolete alias names */ SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), @@ -1318,6 +1380,29 @@ static int bus_unit_set_transient_property( return r; return 1; + + } else if (streq(name, "AddRef")) { + + int b; + + /* Why is this called "AddRef" rather than just "Ref", or "Reference"? There's already a "Ref()" method + * on the Unit interface, and it's probably not a good idea to expose a property and a method on the + * same interface (well, strictly speaking AddRef isn't exposed as full property, we just read it for + * transient units, but still). And "References" and "ReferencedBy" is already used as unit reference + * dependency type, hence let's not confuse things with that. + * + * Note that we don't acually add the reference to the bus track. We do that only after the setup of + * the transient unit is complete, so that setting this property multiple times in the same transient + * unit creation call doesn't count as individual references. */ + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) + u->bus_track_add = b; + + return 1; } return 0; @@ -1422,3 +1507,71 @@ int bus_unit_check_load_state(Unit *u, sd_bus_error *error) { return sd_bus_error_set_errnof(error, u->load_error, "Unit %s is not loaded properly: %m.", u->id); } + +static int bus_track_handler(sd_bus_track *t, void *userdata) { + Unit *u = userdata; + + assert(t); + assert(u); + + u->bus_track = sd_bus_track_unref(u->bus_track); /* make sure we aren't called again */ + + unit_add_to_gc_queue(u); + return 0; +} + +static int allocate_bus_track(Unit *u) { + int r; + + assert(u); + + if (u->bus_track) + return 0; + + r = sd_bus_track_new(u->manager->api_bus, &u->bus_track, bus_track_handler, u); + if (r < 0) + return r; + + r = sd_bus_track_set_recursive(u->bus_track, true); + if (r < 0) { + u->bus_track = sd_bus_track_unref(u->bus_track); + return r; + } + + return 0; +} + +int bus_unit_track_add_name(Unit *u, const char *name) { + int r; + + assert(u); + + r = allocate_bus_track(u); + if (r < 0) + return r; + + return sd_bus_track_add_name(u->bus_track, name); +} + +int bus_unit_track_add_sender(Unit *u, sd_bus_message *m) { + int r; + + assert(u); + + r = allocate_bus_track(u); + if (r < 0) + return r; + + return sd_bus_track_add_sender(u->bus_track, m); +} + +int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m) { + assert(u); + + /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet, return an + * error */ + if (!u->bus_track) + return -EUNATCH; + + return sd_bus_track_remove_sender(u->bus_track, m); +} diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h index 4db88dbebc..b280de7a1d 100644 --- a/src/core/dbus-unit.h +++ b/src/core/dbus-unit.h @@ -33,9 +33,15 @@ int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error); -int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error); int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error); int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error); int bus_unit_check_load_state(Unit *u, sd_bus_error *error); + +int bus_unit_track_add_name(Unit *u, const char *name); +int bus_unit_track_add_sender(Unit *u, sd_bus_message *m); +int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m); diff --git a/src/core/dbus.c b/src/core/dbus.c index 3422a02d68..1e41a42aa6 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -1168,60 +1168,57 @@ int bus_foreach_bus( return ret; } -void bus_track_serialize(sd_bus_track *t, FILE *f) { +void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) { const char *n; assert(f); + assert(prefix); - for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) - fprintf(f, "subscribed=%s\n", n); -} - -int bus_track_deserialize_item(char ***l, const char *line) { - const char *e; - int r; - - assert(l); - assert(line); - - e = startswith(line, "subscribed="); - if (!e) - return 0; + for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) { + int c, j; - r = strv_extend(l, e); - if (r < 0) - return r; + c = sd_bus_track_count_name(t, n); - return 1; + for (j = 0; j < c; j++) { + fputs(prefix, f); + fputc('=', f); + fputs(n, f); + fputc('\n', f); + } + } } -int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) { +int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l) { + char **i; int r = 0; assert(m); assert(t); - assert(l); - - if (!strv_isempty(*l) && m->api_bus) { - char **i; - if (!*t) { - r = sd_bus_track_new(m->api_bus, t, NULL, NULL); - if (r < 0) - return r; - } + if (strv_isempty(l)) + return 0; - r = 0; - STRV_FOREACH(i, *l) { - int k; + if (!m->api_bus) + return 0; - k = sd_bus_track_add_name(*t, *i); - if (k < 0) - r = k; - } + if (!*t) { + r = sd_bus_track_new(m->api_bus, t, NULL, NULL); + if (r < 0) + return r; } - *l = strv_free(*l); + r = sd_bus_track_set_recursive(*t, recursive); + if (r < 0) + return r; + + r = 0; + STRV_FOREACH(i, l) { + int k; + + k = sd_bus_track_add_name(*t, *i); + if (k < 0) + r = k; + } return r; } diff --git a/src/core/dbus.h b/src/core/dbus.h index 6baaffbd75..a092ed9d76 100644 --- a/src/core/dbus.h +++ b/src/core/dbus.h @@ -28,9 +28,8 @@ void bus_done(Manager *m); int bus_fdset_add_all(Manager *m, FDSet *fds); -void bus_track_serialize(sd_bus_track *t, FILE *f); -int bus_track_deserialize_item(char ***l, const char *line); -int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l); +void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix); +int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l); int manager_sync_bus_names(Manager *m, sd_bus *bus); diff --git a/src/core/job.c b/src/core/job.c index 7557874d4d..7faf2ef686 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -997,7 +997,10 @@ char *job_dbus_path(Job *j) { return p; } -int job_serialize(Job *j, FILE *f, FDSet *fds) { +int job_serialize(Job *j, FILE *f) { + assert(j); + assert(f); + fprintf(f, "job-id=%u\n", j->id); fprintf(f, "job-type=%s\n", job_type_to_string(j->type)); fprintf(f, "job-state=%s\n", job_state_to_string(j->state)); @@ -1008,15 +1011,16 @@ int job_serialize(Job *j, FILE *f, FDSet *fds) { if (j->begin_usec > 0) fprintf(f, "job-begin="USEC_FMT"\n", j->begin_usec); - bus_track_serialize(j->clients, f); + bus_track_serialize(j->clients, f, "subscribed"); /* End marker */ fputc('\n', f); return 0; } -int job_deserialize(Job *j, FILE *f, FDSet *fds) { +int job_deserialize(Job *j, FILE *f) { assert(j); + assert(f); for (;;) { char line[LINE_MAX], *l, *v; @@ -1106,7 +1110,7 @@ int job_deserialize(Job *j, FILE *f, FDSet *fds) { } else if (streq(l, "subscribed")) { if (strv_extend(&j->deserialized_clients, v) < 0) - return log_oom(); + log_oom(); } } } @@ -1118,9 +1122,8 @@ int job_coldplug(Job *j) { /* After deserialization is complete and the bus connection * set up again, let's start watching our subscribers again */ - r = bus_track_coldplug(j->manager, &j->clients, &j->deserialized_clients); - if (r < 0) - return r; + (void) bus_track_coldplug(j->manager, &j->clients, false, j->deserialized_clients); + j->deserialized_clients = strv_free(j->deserialized_clients); if (j->state == JOB_WAITING) job_add_to_run_queue(j); diff --git a/src/core/job.h b/src/core/job.h index d359e8bb3e..85368f0d30 100644 --- a/src/core/job.h +++ b/src/core/job.h @@ -177,8 +177,8 @@ Job* job_install(Job *j); int job_install_deserialized(Job *j); void job_uninstall(Job *j); void job_dump(Job *j, FILE*f, const char *prefix); -int job_serialize(Job *j, FILE *f, FDSet *fds); -int job_deserialize(Job *j, FILE *f, FDSet *fds); +int job_serialize(Job *j, FILE *f); +int job_deserialize(Job *j, FILE *f); int job_coldplug(Job *j); JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts); diff --git a/src/core/manager.c b/src/core/manager.c index 7576d038a2..b58f68fa7a 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1287,10 +1287,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { if (q < 0 && r == 0) r = q; - /* We might have deserialized the kdbus control fd, but if we - * didn't, then let's create the bus now. */ - manager_connect_bus(m, !!serialization); - bus_track_coldplug(m, &m->subscribed, &m->deserialized_subscribed); + /* We might have deserialized the kdbus control fd, but if we didn't, then let's create the bus now. */ + (void) manager_connect_bus(m, !!serialization); + + (void) bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed); + m->deserialized_subscribed = strv_free(m->deserialized_subscribed); /* Third, fire things up! */ manager_coldplug(m); @@ -2490,7 +2491,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { fprintf(f, "kdbus-fd=%i\n", copy); } - bus_track_serialize(m->subscribed, f); + bus_track_serialize(m->subscribed, f, "subscribed"); r = dynamic_user_serialize(m, f, fds); if (r < 0) @@ -2693,15 +2694,13 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { manager_deserialize_uid_refs_one(m, l + 16); else if (startswith(l, "destroy-ipc-gid=")) manager_deserialize_gid_refs_one(m, l + 16); - else { - int k; - - k = bus_track_deserialize_item(&m->deserialized_subscribed, l); - if (k < 0) - log_debug_errno(k, "Failed to deserialize bus tracker object: %m"); - else if (k == 0) - log_debug("Unknown serialization item '%s'", l); - } + else if (startswith(l, "subscribed=")) { + + if (strv_extend(&m->deserialized_subscribed, l+11) < 0) + log_oom(); + + } else + log_debug("Unknown serialization item '%s'", l); } for (;;) { diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf index 14f6aec029..647e5f736c 100644 --- a/src/core/org.freedesktop.systemd1.conf +++ b/src/core/org.freedesktop.systemd1.conf @@ -182,6 +182,14 @@ send_interface="org.freedesktop.systemd1.Manager" send_member="Reexecute"/> + + + + diff --git a/src/core/unit.c b/src/core/unit.c index c58c501bc3..6d92eb0c30 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -329,6 +329,9 @@ bool unit_check_gc(Unit *u) { if (u->refs) return true; + if (sd_bus_track_count(u->bus_track) > 0) + return true; + if (UNIT_VTABLE(u)->check_gc) if (UNIT_VTABLE(u)->check_gc(u)) return true; @@ -509,6 +512,9 @@ void unit_free(Unit *u) { sd_bus_slot_unref(u->match_bus_slot); + sd_bus_track_unref(u->bus_track); + u->deserialized_refs = strv_free(u->deserialized_refs); + unit_free_requires_mounts_for(u); SET_FOREACH(t, u->names, i) @@ -897,6 +903,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { Unit *following; _cleanup_set_free_ Set *following_set = NULL; int r; + const char *n; assert(u); assert(u->type >= 0); @@ -1038,6 +1045,8 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { else if (u->load_state == UNIT_ERROR) fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->load_error)); + for (n = sd_bus_track_first(u->bus_track); n; n = sd_bus_track_next(u->bus_track)) + fprintf(f, "%s\tBus Ref: %s\n", prefix, n); if (u->job) job_dump(u->job, f, prefix2); @@ -2622,15 +2631,17 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { if (gid_is_valid(u->ref_gid)) unit_serialize_item_format(u, f, "ref-gid", GID_FMT, u->ref_gid); + bus_track_serialize(u->bus_track, f, "ref"); + if (serialize_jobs) { if (u->job) { fprintf(f, "job\n"); - job_serialize(u->job, f, fds); + job_serialize(u->job, f); } if (u->nop_job) { fprintf(f, "job\n"); - job_serialize(u->nop_job, f, fds); + job_serialize(u->nop_job, f); } } @@ -2760,7 +2771,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { if (!j) return log_oom(); - r = job_deserialize(j, f, fds); + r = job_deserialize(j, f); if (r < 0) { job_free(j); return r; @@ -2880,6 +2891,12 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { else unit_ref_uid_gid(u, UID_INVALID, gid); + } else if (streq(l, "ref")) { + + r = strv_extend(&u->deserialized_refs, v); + if (r < 0) + log_oom(); + continue; } @@ -2955,7 +2972,8 @@ int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep } int unit_coldplug(Unit *u) { - int r = 0, q = 0; + int r = 0, q; + char **i; assert(u); @@ -2966,18 +2984,26 @@ int unit_coldplug(Unit *u) { u->coldplugged = true; - if (UNIT_VTABLE(u)->coldplug) - r = UNIT_VTABLE(u)->coldplug(u); + STRV_FOREACH(i, u->deserialized_refs) { + q = bus_unit_track_add_name(u, *i); + if (q < 0 && r >= 0) + r = q; + } + u->deserialized_refs = strv_free(u->deserialized_refs); - if (u->job) - q = job_coldplug(u->job); + if (UNIT_VTABLE(u)->coldplug) { + q = UNIT_VTABLE(u)->coldplug(u); + if (q < 0 && r >= 0) + r = q; + } - if (r < 0) - return r; - if (q < 0) - return q; + if (u->job) { + q = job_coldplug(u->job); + if (q < 0 && r >= 0) + r = q; + } - return 0; + return r; } static bool fragment_mtime_newer(const char *path, usec_t mtime) { diff --git a/src/core/unit.h b/src/core/unit.h index 53875653d7..e5a2a77b7b 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -108,6 +108,10 @@ struct Unit { /* The slot used for watching NameOwnerChanged signals */ sd_bus_slot *match_bus_slot; + /* References to this unit from clients */ + sd_bus_track *bus_track; + char **deserialized_refs; + /* Job timeout and action to take */ usec_t job_timeout; FailureAction job_timeout_action; @@ -247,6 +251,9 @@ struct Unit { /* Did we already invoke unit_coldplug() for this unit? */ bool coldplugged:1; + + /* For transient units: whether to add a bus track reference after creating the unit */ + bool bus_track_add:1; }; struct UnitStatusMessageFormats { diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index 32be3cdc38..a69193aa32 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -45,6 +45,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN, ECANCELED), SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH), + SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED, EUNATCH), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT), diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index befb6fbfe0..5df21c8926 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -41,6 +41,7 @@ #define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown" #define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning" #define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser" +#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced" #define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine" #define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage" -- cgit v1.2.3-54-g00ecf From 217fcc7eb3b558e65538cbb42f47b2cb89f2850a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 14:45:34 +0200 Subject: sd-bus: split out handling of reply callbacks on close into its own function When a bus connection is closed we dispatch all reply callbacks. Do so in a new function if its own. No behaviour changes. --- src/libsystemd/sd-bus/sd-bus.c | 92 +++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 42 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index ed5f94e136..95c37d8b19 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -2640,63 +2640,71 @@ null_message: return r; } -static int process_closing(sd_bus *bus, sd_bus_message **ret) { +static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c) { + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; - struct reply_callback *c; + sd_bus_slot *slot; int r; assert(bus); - assert(bus->state == BUS_CLOSING); + assert(c); - c = ordered_hashmap_first(bus->reply_callbacks); - if (c) { - _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; - sd_bus_slot *slot; + r = bus_message_new_synthetic_error( + bus, + c->cookie, + &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"), + &m); + if (r < 0) + return r; - /* First, fail all outstanding method calls */ - r = bus_message_new_synthetic_error( - bus, - c->cookie, - &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"), - &m); - if (r < 0) - return r; + r = bus_seal_synthetic_message(bus, m); + if (r < 0) + return r; - r = bus_seal_synthetic_message(bus, m); - if (r < 0) - return r; + if (c->timeout != 0) { + prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); + c->timeout = 0; + } - if (c->timeout != 0) { - prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); - c->timeout = 0; - } + ordered_hashmap_remove(bus->reply_callbacks, &c->cookie); + c->cookie = 0; + + slot = container_of(c, sd_bus_slot, reply_callback); - ordered_hashmap_remove(bus->reply_callbacks, &c->cookie); - c->cookie = 0; + bus->iteration_counter++; - slot = container_of(c, sd_bus_slot, reply_callback); + bus->current_message = m; + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_handler = c->callback; + bus->current_userdata = slot->userdata; + r = c->callback(m, slot->userdata, &error_buffer); + bus->current_userdata = NULL; + bus->current_handler = NULL; + bus->current_slot = NULL; + bus->current_message = NULL; - bus->iteration_counter++; + if (slot->floating) { + bus_slot_disconnect(slot); + sd_bus_slot_unref(slot); + } - bus->current_message = m; - bus->current_slot = sd_bus_slot_ref(slot); - bus->current_handler = c->callback; - bus->current_userdata = slot->userdata; - r = c->callback(m, slot->userdata, &error_buffer); - bus->current_userdata = NULL; - bus->current_handler = NULL; - bus->current_slot = NULL; - bus->current_message = NULL; + sd_bus_slot_unref(slot); - if (slot->floating) { - bus_slot_disconnect(slot); - sd_bus_slot_unref(slot); - } + return bus_maybe_reply_error(m, r, &error_buffer); +} - sd_bus_slot_unref(slot); +static int process_closing(sd_bus *bus, sd_bus_message **ret) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + struct reply_callback *c; + int r; - return bus_maybe_reply_error(m, r, &error_buffer); - } + assert(bus); + assert(bus->state == BUS_CLOSING); + + /* First, fail all outstanding method calls */ + c = ordered_hashmap_first(bus->reply_callbacks); + if (c) + return process_closing_reply_callback(bus, c); /* Then, synthesize a Disconnected message */ r = sd_bus_message_new_signal( -- cgit v1.2.3-54-g00ecf From 8b6e65ac32627e371ee61f7d086ed33bc47e4b4c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 16:09:15 +0200 Subject: sd-bus: ensure we don't dispatch track objects while we are adding names to them In order to add a name to a bus tracking object we need to do some bus operations: we need to check if the name already exists and add match for it. Both are synchronous bus calls. While processing those we need to make sure that the tracking object is not dispatched yet, as it might still be empty, but is not going to be empty for very long. hence, block dispatching by removing the object from the dispatch queue while adding it, and readding it on error. --- src/libsystemd/sd-bus/bus-track.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 6ece2244c2..90e0c7ae01 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -32,6 +32,7 @@ struct track_item { struct sd_bus_track { unsigned n_ref; + unsigned n_adding; /* are we in the process of adding a new name? */ sd_bus *bus; sd_bus_track_handler_t handler; void *userdata; @@ -80,9 +81,23 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free); static void bus_track_add_to_queue(sd_bus_track *track) { assert(track); + /* Adds the bus track object to the queue of objects we should dispatch next, subject to a number of + * conditions. */ + + /* Already in the queue? */ if (track->in_queue) return; + /* if we are currently in the process of adding a new name, then let's not enqueue this just yet, let's wait + * until the addition is complete. */ + if (track->n_adding > 0) + return; + + /* still referenced? */ + if (hashmap_size(track->names) > 0) + return; + + /* Nothing to call? */ if (!track->handler) return; @@ -112,8 +127,7 @@ static int bus_track_remove_name_fully(sd_bus_track *track, const char *name) { track_item_free(i); - if (hashmap_isempty(track->names)) - bus_track_add_to_queue(track); + bus_track_add_to_queue(track); track->modified = true; return 1; @@ -237,18 +251,30 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { /* First, subscribe to this name */ match = MATCH_FOR_NAME(name); + + bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */ + + track->n_adding++; /* make sure we aren't dispatched while we synchronously add this match */ r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track); - if (r < 0) + track->n_adding--; + if (r < 0) { + bus_track_add_to_queue(track); return r; + } r = hashmap_put(track->names, n->name, n); - if (r < 0) + if (r < 0) { + bus_track_add_to_queue(track); return r; + } /* Second, check if it is currently existing, or maybe doesn't, or maybe disappeared already. */ + track->n_adding++; /* again, make sure this isn't dispatch while we are working in it */ r = sd_bus_get_name_creds(track->bus, name, 0, NULL); + track->n_adding--; if (r < 0) { hashmap_remove(track->names, name); + bus_track_add_to_queue(track); return r; } -- cgit v1.2.3-54-g00ecf From 232f367766b35fa248476d0ded49781a06a80ae1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 16:11:54 +0200 Subject: sd-bus: when the server-side disconnects, make sure to dispatch all tracking objects immediately If the server side kicks us from the bus, from our view no names are on the bus anymore, hence let's make sure to dispatch all tracking objects immediately. --- src/libsystemd/sd-bus/bus-internal.h | 1 + src/libsystemd/sd-bus/bus-track.c | 44 ++++++++++++++++++++++++++++++++++-- src/libsystemd/sd-bus/bus-track.h | 1 + src/libsystemd/sd-bus/sd-bus.c | 7 ++++++ 4 files changed, 51 insertions(+), 2 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 216d9f62bc..13357075bf 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -320,6 +320,7 @@ struct sd_bus { sd_bus_track *track_queue; LIST_HEAD(sd_bus_slot, slots); + LIST_HEAD(sd_bus_track, tracks); }; #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 90e0c7ae01..00e93a215f 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -39,9 +39,12 @@ struct sd_bus_track { Hashmap *names; LIST_FIELDS(sd_bus_track, queue); Iterator iterator; - bool in_queue:1; + bool in_list:1; /* In bus->tracks? */ + bool in_queue:1; /* In bus->track_queue? */ bool modified:1; bool recursive:1; + + LIST_FIELDS(sd_bus_track, tracks); }; #define MATCH_PREFIX \ @@ -101,6 +104,10 @@ static void bus_track_add_to_queue(sd_bus_track *track) { if (!track->handler) return; + /* Already closed? */ + if (!track->in_list) + return; + LIST_PREPEND(queue, track->bus->track_queue, track); track->in_queue = true; } @@ -156,6 +163,9 @@ _public_ int sd_bus_track_new( t->userdata = userdata; t->bus = sd_bus_ref(bus); + LIST_PREPEND(tracks, bus->tracks, t); + t->in_list = true; + bus_track_add_to_queue(t); *track = t; @@ -190,6 +200,9 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { while ((i = hashmap_steal_first(track->names))) track_item_free(i); + if (track->in_list) + LIST_REMOVE(tracks, track->bus->tracks, track); + bus_track_remove_from_queue(track); hashmap_free(track->names); sd_bus_unref(track->bus); @@ -403,7 +416,6 @@ void bus_track_dispatch(sd_bus_track *track) { int r; assert(track); - assert(track->in_queue); assert(track->handler); bus_track_remove_from_queue(track); @@ -419,6 +431,34 @@ void bus_track_dispatch(sd_bus_track *track) { sd_bus_track_unref(track); } +void bus_track_close(sd_bus_track *track) { + struct track_item *i; + + assert(track); + + /* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it + * immediately, as we are closing now, but first flush out all names. */ + + if (!track->in_list) + return; /* We already closed this one, don't close it again. */ + + /* Remember that this one is closed now */ + LIST_REMOVE(tracks, track->bus->tracks, track); + track->in_list = false; + + /* If there's no name in this one anyway, we don't have to dispatch */ + if (hashmap_isempty(track->names)) + return; + + /* Let's flush out all names */ + while ((i = hashmap_steal_first(track->names))) + track_item_free(i); + + /* Invoke handler */ + if (track->handler) + bus_track_dispatch(track); +} + _public_ void *sd_bus_track_get_userdata(sd_bus_track *track) { assert_return(track, NULL); diff --git a/src/libsystemd/sd-bus/bus-track.h b/src/libsystemd/sd-bus/bus-track.h index 7d93a727d6..26bd05f5c7 100644 --- a/src/libsystemd/sd-bus/bus-track.h +++ b/src/libsystemd/sd-bus/bus-track.h @@ -20,3 +20,4 @@ ***/ void bus_track_dispatch(sd_bus_track *track); +void bus_track_close(sd_bus_track *track); diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 95c37d8b19..6ee5f82e12 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -107,6 +107,7 @@ static void bus_free(sd_bus *b) { assert(b); assert(!b->track_queue); + assert(!b->tracks); b->state = BUS_CLOSED; @@ -2706,6 +2707,12 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) { if (c) return process_closing_reply_callback(bus, c); + /* Then, fake-drop all remaining bus tracking references */ + if (bus->tracks) { + bus_track_close(bus->tracks); + return 1; + } + /* Then, synthesize a Disconnected message */ r = sd_bus_message_new_signal( bus, -- cgit v1.2.3-54-g00ecf From 70cb8b7b16d2f1c63b21d90a493d895018fe8f67 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 16:13:19 +0200 Subject: sd-bus: add a small test case for sd_bus_track This tests in particular that disconnecting results in the tracking object's handlers to be called. --- .gitignore | 1 + Makefile.am | 11 ++++ src/libsystemd/sd-bus/test-bus-track.c | 113 +++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 src/libsystemd/sd-bus/test-bus-track.c (limited to 'src/libsystemd/sd-bus') diff --git a/.gitignore b/.gitignore index 6caa8218bd..565a3a3839 100644 --- a/.gitignore +++ b/.gitignore @@ -152,6 +152,7 @@ /test-bus-policy /test-bus-server /test-bus-signature +/test-bus-track /test-bus-zero-copy /test-calendarspec /test-cap-list diff --git a/Makefile.am b/Makefile.am index 431975de8b..3a617560e0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3323,6 +3323,7 @@ tests += \ test-bus-error \ test-bus-creds \ test-bus-gvariant \ + test-bus-track \ test-event \ test-netlink \ test-local-addresses \ @@ -3366,6 +3367,16 @@ test_bus_cleanup_CFLAGS = \ test_bus_cleanup_LDADD = \ libsystemd-shared.la +test_bus_track_SOURCES = \ + src/libsystemd/sd-bus/test-bus-track.c + +test_bus_track_CFLAGS = \ + $(AM_CFLAGS) \ + $(SECCOMP_CFLAGS) + +test_bus_track_LDADD = \ + libsystemd-shared.la + test_bus_server_SOURCES = \ src/libsystemd/sd-bus/test-bus-server.c diff --git a/src/libsystemd/sd-bus/test-bus-track.c b/src/libsystemd/sd-bus/test-bus-track.c new file mode 100644 index 0000000000..4beb61f05a --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-track.c @@ -0,0 +1,113 @@ +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +#include "macro.h" + +static bool track_cb_called_x = false; +static bool track_cb_called_y = false; + +static int track_cb_x(sd_bus_track *t, void *userdata) { + + log_error("TRACK CB X"); + + assert_se(!track_cb_called_x); + track_cb_called_x = true; + + /* This means b's name disappeared. Let's now disconnect, to make sure the track handling on disconnect works + * as it should. */ + + assert_se(shutdown(sd_bus_get_fd(sd_bus_track_get_bus(t)), SHUT_RDWR) >= 0); + return 1; +} + +static int track_cb_y(sd_bus_track *t, void *userdata) { + int r; + + log_error("TRACK CB Y"); + + assert_se(!track_cb_called_y); + track_cb_called_y = true; + + /* We got disconnected, let's close everything */ + + r = sd_event_exit(sd_bus_get_event(sd_bus_track_get_bus(t)), EXIT_SUCCESS); + assert_se(r >= 0); + + return 0; +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_(sd_bus_track_unrefp) sd_bus_track *x = NULL, *y = NULL; + _cleanup_(sd_bus_unrefp) sd_bus *a = NULL, *b = NULL; + const char *unique; + int r; + + r = sd_event_default(&event); + assert_se(r >= 0); + + r = sd_bus_open_system(&a); + if (IN_SET(r, -ECONNREFUSED, -ENOENT)) { + log_info("Failed to connect to bus, skipping tests."); + return EXIT_TEST_SKIP; + } + assert_se(r >= 0); + + r = sd_bus_attach_event(a, event, SD_EVENT_PRIORITY_NORMAL); + assert_se(r >= 0); + + r = sd_bus_open_system(&b); + assert_se(r >= 0); + + r = sd_bus_attach_event(b, event, SD_EVENT_PRIORITY_NORMAL); + assert_se(r >= 0); + + /* Watch b's name from a */ + r = sd_bus_track_new(a, &x, track_cb_x, NULL); + assert_se(r >= 0); + + r = sd_bus_get_unique_name(b, &unique); + assert_se(r >= 0); + + r = sd_bus_track_add_name(x, unique); + assert_se(r >= 0); + + /* Watch's a's own name from a */ + r = sd_bus_track_new(a, &y, track_cb_y, NULL); + assert_se(r >= 0); + + r = sd_bus_get_unique_name(a, &unique); + assert_se(r >= 0); + + r = sd_bus_track_add_name(y, unique); + assert_se(r >= 0); + + /* Now make b's name disappear */ + sd_bus_close(b); + + r = sd_event_loop(event); + assert_se(r >= 0); + + assert_se(track_cb_called_x); + assert_se(track_cb_called_y); + + return 0; +} -- cgit v1.2.3-54-g00ecf From fbb4603d487d329bdd7aff744ff9ba7a7c2a2965 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 17:19:12 +0200 Subject: sd-bus: optionally, exit process or event loop on disconnect Old libdbus has a feature that the process is terminated whenever the the bus connection receives a disconnect. This is pretty useful on desktop apps (where a disconnect indicates session termination), as well as on command line apps (where we really shouldn't stay hanging in most cases if dbus daemon goes down). Add a similar feature to sd-bus, but make it opt-in rather than opt-out, like it is on libdbus. Also, if the bus is attached to an event loop just exit the event loop rather than the the whole process. --- src/libsystemd/libsystemd.sym | 2 ++ src/libsystemd/sd-bus/bus-internal.h | 3 +++ src/libsystemd/sd-bus/sd-bus.c | 47 ++++++++++++++++++++++++++++++++++++ src/systemd/sd-bus.h | 2 ++ 4 files changed, 54 insertions(+) (limited to 'src/libsystemd/sd-bus') diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index ae60e346eb..70ea347361 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -507,4 +507,6 @@ global: sd_bus_track_get_recursive; sd_bus_track_count_name; sd_bus_track_count_sender; + sd_bus_set_exit_on_disconnect; + sd_bus_get_exit_on_disconnect; } LIBSYSTEMD_231; diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 13357075bf..2608f5469c 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -209,6 +209,9 @@ struct sd_bus { bool is_system:1; bool is_user:1; bool allow_interactive_authorization:1; + bool exit_on_disconnect:1; + bool exited:1; + bool exit_triggered:1; int use_memfd; diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 6ee5f82e12..d746348544 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -2641,6 +2641,31 @@ null_message: return r; } +static int bus_exit_now(sd_bus *bus) { + assert(bus); + + /* Exit due to close, if this is requested. If this is bus object is attached to an event source, invokes + * sd_event_exit(), otherwise invokes libc exit(). */ + + if (bus->exited) /* did we already exit? */ + return 0; + if (!bus->exit_triggered) /* was the exit condition triggered? */ + return 0; + if (!bus->exit_on_disconnect) /* Shall we actually exit on disconnection? */ + return 0; + + bus->exited = true; /* never exit more than once */ + + log_debug("Bus connection disconnected, exiting."); + + if (bus->event) + return sd_event_exit(bus->event, EXIT_FAILURE); + else + exit(EXIT_FAILURE); + + assert_not_reached("exit() didn't exit?"); +} + static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c) { _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; @@ -2742,6 +2767,10 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) { if (r != 0) goto finish; + /* Nothing else to do, exit now, if the condition holds */ + bus->exit_triggered = true; + (void) bus_exit_now(bus); + if (ret) { *ret = m; m = NULL; @@ -3804,3 +3833,21 @@ _public_ void sd_bus_default_flush_close(void) { flush_close(default_user_bus); flush_close(default_system_bus); } + +_public_ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + + /* Turns on exit-on-disconnect, and triggers it immediately if the bus connection was already + * disconnected. Note that this is triggered exclusively on disconnections triggered by the server side, never + * from the client side. */ + bus->exit_on_disconnect = b; + + /* If the exit condition was triggered already, exit immediately. */ + return bus_exit_now(bus); +} + +_public_ int sd_bus_get_exit_on_disconnect(sd_bus *bus) { + assert_return(bus, -EINVAL); + + return bus->exit_on_disconnect; +} diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 0305c56a8c..c47459c9ad 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -147,6 +147,8 @@ int sd_bus_can_send(sd_bus *bus, char type); int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *creds_mask); int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b); int sd_bus_get_allow_interactive_authorization(sd_bus *bus); +int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b); +int sd_bus_get_exit_on_disconnect(sd_bus *bus); int sd_bus_start(sd_bus *ret); -- cgit v1.2.3-54-g00ecf From 5ddda46f18384d51c74df6daca58a8bc87b46ad1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 31 Aug 2016 20:09:31 +0200 Subject: sd-bus: bump message queue size Let's bump it further, as this the current limit turns out to be problematic IRL. Let's bump it to more than twice what we know of is needed. Fixes: #4068 --- src/libsystemd/sd-bus/bus-internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 2608f5469c..bb0414c4d6 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -328,8 +328,8 @@ struct sd_bus { #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) -#define BUS_WQUEUE_MAX 1024 -#define BUS_RQUEUE_MAX 64*1024 +#define BUS_WQUEUE_MAX (192*1024) +#define BUS_RQUEUE_MAX (192*1024) #define BUS_MESSAGE_SIZE_MAX (64*1024*1024) #define BUS_AUTH_SIZE_MAX (64*1024) -- cgit v1.2.3-54-g00ecf From 9eec7d12eda398fbc4a1db880bd4a13bc1c58db4 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 12 Sep 2016 19:55:34 +0100 Subject: tests: get rid of strerror --- src/journal/test-journal-interleaving.c | 7 +++---- src/libsystemd/sd-bus/test-bus-chat.c | 2 +- src/test/test-engine.c | 2 +- src/test/test-execute.c | 2 +- src/test/test-path.c | 2 +- src/test/test-sched-prio.c | 2 +- src/test/test-unit-file.c | 8 ++++---- 7 files changed, 12 insertions(+), 13 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c index 5e063f4d04..35cae23bf8 100644 --- a/src/journal/test-journal-interleaving.c +++ b/src/journal/test-journal-interleaving.c @@ -36,10 +36,9 @@ static bool arg_keep = false; -noreturn static void log_assert_errno(const char *text, int eno, const char *file, int line, const char *func) { - log_internal(LOG_CRIT, 0, file, line, func, - "'%s' failed at %s:%u (%s): %s.", - text, file, line, func, strerror(eno)); +noreturn static void log_assert_errno(const char *text, int error, const char *file, int line, const char *func) { + log_internal(LOG_CRIT, error, file, line, func, + "'%s' failed at %s:%u (%s): %m", text, file, line, func); abort(); } diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c index 048c0d19e2..fc60830059 100644 --- a/src/libsystemd/sd-bus/test-bus-chat.c +++ b/src/libsystemd/sd-bus/test-bus-chat.c @@ -351,7 +351,7 @@ finish: static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { bool *x = userdata; - log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m))); + log_error_errno(sd_bus_message_get_errno(m), "Quit callback: %m"); *x = 1; return 1; diff --git a/src/test/test-engine.c b/src/test/test-engine.c index 23da10fa1a..a651f6b683 100644 --- a/src/test/test-engine.c +++ b/src/test/test-engine.c @@ -43,7 +43,7 @@ int main(int argc, char *argv[]) { assert_se(set_unit_path(TEST_DIR) >= 0); r = manager_new(UNIT_FILE_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return EXIT_TEST_SKIP; } assert_se(r >= 0); diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 05ec1d2eb1..1db7f78041 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -324,7 +324,7 @@ static int run_tests(UnitFileScope scope, test_function_t *tests) { r = manager_new(scope, true, &m); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %n"); return EXIT_TEST_SKIP; } assert_se(r >= 0); diff --git a/src/test/test-path.c b/src/test/test-path.c index 62181e22a0..4d3f0e9948 100644 --- a/src/test/test-path.c +++ b/src/test/test-path.c @@ -47,7 +47,7 @@ static int setup_test(Manager **m) { r = manager_new(UNIT_FILE_USER, true, &tmp); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return -EXIT_TEST_SKIP; } assert_se(r >= 0); diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c index c068f5c39e..7b37910c33 100644 --- a/src/test/test-sched-prio.c +++ b/src/test/test-sched-prio.c @@ -40,7 +40,7 @@ int main(int argc, char *argv[]) { assert_se(set_unit_path(TEST_DIR) >= 0); r = manager_new(UNIT_FILE_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return EXIT_TEST_SKIP; } assert_se(r >= 0); diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c index ade0ff2a63..a5009f98ef 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-unit-file.c @@ -56,12 +56,12 @@ static int test_unit_file_get_set(void) { r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL); if (r == -EPERM || r == -EACCES) { - printf("Skipping test: unit_file_get_list: %s", strerror(-r)); + log_notice_errno(r, "Skipping test: unit_file_get_list: %m"); return EXIT_TEST_SKIP; } - log_full(r == 0 ? LOG_INFO : LOG_ERR, - "unit_file_get_list: %s", strerror(-r)); + log_full_errno(r == 0 ? LOG_INFO : LOG_ERR, r, + "unit_file_get_list: %m"); if (r < 0) return EXIT_FAILURE; @@ -117,7 +117,7 @@ static void test_config_parse_exec(void) { r = manager_new(UNIT_FILE_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return; } -- cgit v1.2.3-54-g00ecf From 1cf03a4f8e5de53ca1ecc8a6dc64cb32ab8de536 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 24 Sep 2016 20:18:02 -0400 Subject: systemctl,networkctl,busctl,backlight: use STRPTR_IN_SET --- src/backlight/backlight.c | 2 +- src/libsystemd/sd-bus/busctl.c | 3 +-- src/network/networkctl.c | 2 +- src/systemctl/systemctl.c | 12 +++++------- 4 files changed, 8 insertions(+), 11 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c index 45be135a23..7c59f60d5f 100644 --- a/src/backlight/backlight.c +++ b/src/backlight/backlight.c @@ -167,7 +167,7 @@ static bool validate_device(struct udev *udev, struct udev_device *device) { continue; v = udev_device_get_sysattr_value(other, "type"); - if (!streq_ptr(v, "platform") && !streq_ptr(v, "firmware")) + if (!STRPTR_IN_SET(v, "platform", "firmware")) continue; /* OK, so there's another backlight device, and it's a diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c index eb042e9c81..2c3f591053 100644 --- a/src/libsystemd/sd-bus/busctl.c +++ b/src/libsystemd/sd-bus/busctl.c @@ -2003,8 +2003,7 @@ int main(int argc, char *argv[]) { goto finish; } - if (streq_ptr(argv[optind], "monitor") || - streq_ptr(argv[optind], "capture")) { + if (STRPTR_IN_SET(argv[optind], "monitor", "capture")) { r = sd_bus_set_monitor(bus, true); if (r < 0) { diff --git a/src/network/networkctl.c b/src/network/networkctl.c index d2df9b7560..6f7f41bf7d 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -122,7 +122,7 @@ static void setup_state_to_color(const char *state, const char **on, const char } else if (streq_ptr(state, "configuring")) { *on = ansi_highlight_yellow(); *off = ansi_normal(); - } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) { + } else if (STRPTR_IN_SET(state, "failed", "linger")) { *on = ansi_highlight_red(); *off = ansi_normal(); } else diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index dc8f61b049..02224896ff 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3622,7 +3622,7 @@ static void print_status_info( if (streq_ptr(i->active_state, "failed")) { active_on = ansi_highlight_red(); active_off = ansi_normal(); - } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) { + } else if (STRPTR_IN_SET(i->active_state, "active", "reloading")) { active_on = ansi_highlight_green(); active_off = ansi_normal(); } else @@ -3703,12 +3703,10 @@ static void print_status_info( if (!isempty(i->result) && !streq(i->result, "success")) printf(" (Result: %s)", i->result); - timestamp = (streq_ptr(i->active_state, "active") || - streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp : - (streq_ptr(i->active_state, "inactive") || - streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp : - streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp : - i->active_exit_timestamp; + timestamp = STRPTR_IN_SET(i->active_state, "active", "reloading") ? i->active_enter_timestamp : + STRPTR_IN_SET(i->active_state, "inactive", "failed") ? i->inactive_enter_timestamp : + STRPTR_IN_SET(i->active_state, "activating") ? i->inactive_exit_timestamp : + i->active_exit_timestamp; s1 = format_timestamp_relative(since1, sizeof(since1), timestamp); s2 = format_timestamp(since2, sizeof(since2), timestamp); -- cgit v1.2.3-54-g00ecf From 9aa8fa701b79b74d118df8dbda0940f74aa8735b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 26 Sep 2016 22:22:28 +0200 Subject: test-bus-creds: are more debugging info This test sometimes fails in semaphore, but not when run interactively, so it's hard to debug. --- src/libsystemd/sd-bus/test-bus-creds.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/libsystemd/sd-bus') diff --git a/src/libsystemd/sd-bus/test-bus-creds.c b/src/libsystemd/sd-bus/test-bus-creds.c index 82237af115..6fdcfa4128 100644 --- a/src/libsystemd/sd-bus/test-bus-creds.c +++ b/src/libsystemd/sd-bus/test-bus-creds.c @@ -27,12 +27,17 @@ int main(int argc, char *argv[]) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; int r; + log_set_max_level(LOG_DEBUG); + log_parse_environment(); + log_open(); + if (cg_all_unified() == -ENOMEDIUM) { - puts("Skipping test: /sys/fs/cgroup/ not available"); + log_info("Skipping test: /sys/fs/cgroup/ not available"); return EXIT_TEST_SKIP; } r = sd_bus_creds_new_from_pid(&creds, 0, _SD_BUS_CREDS_ALL); + log_full_errno(r < 0 ? LOG_ERR : LOG_DEBUG, r, "sd_bus_creds_new_from_pid: %m"); assert_se(r >= 0); bus_creds_dump(creds, NULL, true); -- cgit v1.2.3-54-g00ecf From 19526c66795d7f7d2e956f10422dc76a7429901c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Oct 2016 15:50:30 +0200 Subject: sd-bus: add a few missing entries to the error translation tables These were forgotten, let's add some useful mappings for all errors we define. --- src/libsystemd/sd-bus/bus-common-errors.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/libsystemd/sd-bus') diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index a69193aa32..de7b65ca14 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -52,6 +52,8 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_NO_MACHINE_FOR_PID, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_MACHINE_EXISTS, EEXIST), SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRIVATE_NETWORKING, ENOSYS), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_USER_MAPPING, ENXIO), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_GROUP_MAPPING, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SESSION, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SESSION_FOR_PID, ENXIO), @@ -64,6 +66,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_NOT_TAKEN, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS, EINPROGRESS), SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, EOPNOTSUPP), + SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY, EBUSY), SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY), -- cgit v1.2.3-54-g00ecf From 729c6467df4887e55b57b4efe9541bff0d31016b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Oct 2016 16:01:44 +0200 Subject: sd-bus: add DNS errors to the errno translation table We generate these, hence we should also add errno translations for them. --- src/libsystemd/sd-bus/bus-common-errors.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src/libsystemd/sd-bus') diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index de7b65ca14..9cc28ed564 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -85,6 +85,25 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY), SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "FORMERR", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "SERVFAIL", EHOSTDOWN), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXDOMAIN", ENXIO), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTIMP", ENOSYS), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "REFUSED", EACCES), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YXDOMAIN", EEXIST), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YRRSET", EEXIST), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXRRSET", ENOENT), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTAUTH", EACCES), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTZONE", EREMOTE), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADVERS", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADKEY", EKEYREJECTED), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTIME", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADMODE", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADNAME", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADALG", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTRUNC", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADCOOKIE", EBADR), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS, EBUSY), -- cgit v1.2.3-54-g00ecf From 4b58153dd22172d817055d2a09a0cdf3f4bd9db3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Aug 2016 23:18:46 +0200 Subject: core: add "invocation ID" concept to service manager This adds a new invocation ID concept to the service manager. The invocation ID identifies each runtime cycle of a unit uniquely. A new randomized 128bit ID is generated each time a unit moves from and inactive to an activating or active state. The primary usecase for this concept is to connect the runtime data PID 1 maintains about a service with the offline data the journal stores about it. Previously we'd use the unit name plus start/stop times, which however is highly racy since the journal will generally process log data after the service already ended. The "invocation ID" kinda matches the "boot ID" concept of the Linux kernel, except that it applies to an individual unit instead of the whole system. The invocation ID is passed to the activated processes as environment variable. It is additionally stored as extended attribute on the cgroup of the unit. The latter is used by journald to automatically retrieve it for each log logged message and attach it to the log entry. The environment variable is very easily accessible, even for unprivileged services. OTOH the extended attribute is only accessible to privileged processes (this is because cgroupfs only supports the "trusted." xattr namespace, not "user."). The environment variable may be altered by services, the extended attribute may not be, hence is the better choice for the journal. Note that reading the invocation ID off the extended attribute from journald is racy, similar to the way reading the unit name for a logging process is. This patch adds APIs to read the invocation ID to sd-id128: sd_id128_get_invocation() may be used in a similar fashion to sd_id128_get_boot(). PID1's own logging is updated to always include the invocation ID when it logs information about a unit. A new bus call GetUnitByInvocationID() is added that allows retrieving a bus path to a unit by its invocation ID. The bus path is built using the invocation ID, thus providing a path for referring to a unit that is valid only for the current runtime cycleof it. Outlook for the future: should the kernel eventually allow passing of cgroup information along AF_UNIX/SOCK_DGRAM messages via a unique cgroup id, then we can alter the invocation ID to be generated as hash from that rather than entirely randomly. This way we can derive the invocation race-freely from the messages. --- Makefile-man.am | 5 ++ man/sd_id128_get_machine.xml | 34 +++++++----- man/systemd.exec.xml | 10 ++++ src/basic/cgroup-util.c | 38 +++++++++++++ src/basic/cgroup-util.h | 3 ++ src/basic/log.c | 45 +++++++++------- src/basic/log.h | 10 ++-- src/core/automount.c | 4 ++ src/core/busname.c | 4 ++ src/core/cgroup.c | 21 ++++++++ src/core/dbus-manager.c | 59 +++++++++++++++++++++ src/core/dbus-unit.c | 1 + src/core/device.c | 4 ++ src/core/execute.c | 10 +++- src/core/manager.c | 24 ++++++++- src/core/manager.h | 4 ++ src/core/mount.c | 11 ++-- src/core/org.freedesktop.systemd1.conf | 4 ++ src/core/path.c | 4 ++ src/core/scope.c | 4 ++ src/core/service.c | 4 ++ src/core/slice.c | 5 ++ src/core/socket.c | 5 +- src/core/swap.c | 5 ++ src/core/target.c | 5 ++ src/core/timer.c | 6 ++- src/core/unit.c | 88 ++++++++++++++++++++++++++++++- src/core/unit.h | 10 +++- src/journal/journald-server.c | 60 ++++++++++++++++++--- src/journal/journald-server.h | 2 +- src/libsystemd/libsystemd.sym | 1 + src/libsystemd/sd-bus/bus-common-errors.c | 1 + src/libsystemd/sd-bus/bus-common-errors.h | 1 + src/libsystemd/sd-id128/id128-util.c | 13 +++++ src/libsystemd/sd-id128/id128-util.h | 6 +++ src/libsystemd/sd-id128/sd-id128.c | 22 ++++++++ src/network/networkd-link.h | 2 +- src/network/networkd-netdev.h | 2 +- src/shared/bus-util.c | 2 +- src/systemd/sd-id128.h | 2 +- 40 files changed, 486 insertions(+), 55 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/Makefile-man.am b/Makefile-man.am index ef5077cc5a..5760878fe3 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -395,6 +395,7 @@ MANPAGES_ALIAS += \ man/sd_id128_equal.3 \ man/sd_id128_from_string.3 \ man/sd_id128_get_boot.3 \ + man/sd_id128_get_invocation.3 \ man/sd_id128_t.3 \ man/sd_is_mq.3 \ man/sd_is_socket.3 \ @@ -745,6 +746,7 @@ man/sd_event_unrefp.3: man/sd_event_new.3 man/sd_id128_equal.3: man/sd-id128.3 man/sd_id128_from_string.3: man/sd_id128_to_string.3 man/sd_id128_get_boot.3: man/sd_id128_get_machine.3 +man/sd_id128_get_invocation.3: man/sd_id128_get_machine.3 man/sd_id128_t.3: man/sd-id128.3 man/sd_is_mq.3: man/sd_is_fifo.3 man/sd_is_socket.3: man/sd_is_fifo.3 @@ -1519,6 +1521,9 @@ man/sd_id128_from_string.html: man/sd_id128_to_string.html man/sd_id128_get_boot.html: man/sd_id128_get_machine.html $(html-alias) +man/sd_id128_get_invocation.html: man/sd_id128_get_machine.html + $(html-alias) + man/sd_id128_t.html: man/sd-id128.html $(html-alias) diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml index 2ad1f8f728..9a86c24aed 100644 --- a/man/sd_id128_get_machine.xml +++ b/man/sd_id128_get_machine.xml @@ -45,6 +45,7 @@ sd_id128_get_machine sd_id128_get_boot + sd_id128_get_invocation Retrieve 128-bit IDs @@ -62,6 +63,11 @@ sd_id128_t *ret + + int sd_id128_get_invocation + sd_id128_t *ret + + @@ -83,11 +89,15 @@ for more information. This function also internally caches the returned ID to make this call a cheap operation. - Note that sd_id128_get_boot() always - returns a UUID v4 compatible ID. - sd_id128_get_machine() will also return a - UUID v4-compatible ID on new installations but might not on older. - It is possible to convert the machine ID into a UUID v4-compatible + sd_id128_get_invocation() returns the invocation ID of the currently executed + service. In its current implementation, this reads and parses the $INVOCATION_ID environment + variable that the service manager sets when activating a service, see + systemd.exec5 for details. The + ID is cached internally. In future a different mechanism to determine the invocation ID may be added. + + Note that sd_id128_get_boot() and sd_id128_get_invocation() always + return UUID v4 compatible IDs. sd_id128_get_machine() will also return a UUID v4-compatible + ID on new installations but might not on older. It is possible to convert the machine ID into a UUID v4-compatible one. For more information, see machine-id5. @@ -107,11 +117,10 @@ Notes - The sd_id128_get_machine() and - sd_id128_get_boot() interfaces are available - as a shared library, which can be compiled and linked to with the - libsystemd pkg-config1 - file. + The sd_id128_get_machine(), sd_id128_get_boot() and + sd_id128_get_invocation() interfaces are available as a shared library, which can be compiled + and linked to with the libsystemd pkg-config1 file. @@ -121,8 +130,9 @@ systemd1, sd-id1283, machine-id5, - random4, - sd_id128_randomize3 + systemd.exec5, + sd_id128_randomize3, + random4 diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 5e6787338d..c73ccaa493 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1513,6 +1513,16 @@ + + $INVOCATION_ID + + Contains a randomized, unique 128bit ID identifying each runtime cycle of the unit, formatted + as 32 character hexadecimal string. A new ID is assigned each time the unit changes from an inactive state into + an activating or active state, and may be used to identify this specific runtime cycle, in particular in data + stored offline, such as the journal. The same ID is passed to all processes run as part of the + unit. + + $XDG_RUNTIME_DIR diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 7675ab0299..37e6928a46 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "alloc-util.h" @@ -883,6 +884,43 @@ int cg_set_task_access( return 0; } +int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags) { + _cleanup_free_ char *fs = NULL; + int r; + + assert(path); + assert(name); + assert(value || size <= 0); + + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) + return r; + + if (setxattr(fs, name, value, size, flags) < 0) + return -errno; + + return 0; +} + +int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size) { + _cleanup_free_ char *fs = NULL; + ssize_t n; + int r; + + assert(path); + assert(name); + + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) + return r; + + n = getxattr(fs, name, value, size); + if (n < 0) + return -errno; + + return (int) n; +} + int cg_pid_get_path(const char *controller, pid_t pid, char **path) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 1a61c7ad22..7529c9719e 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -185,6 +185,9 @@ int cg_get_keyed_attribute(const char *controller, const char *path, const char int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); +int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags); +int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size); + int cg_install_release_agent(const char *controller, const char *agent); int cg_uninstall_release_agent(const char *controller); diff --git a/src/basic/log.c b/src/basic/log.c index 6a8dad311d..bd6c96c4f8 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -330,8 +330,6 @@ static int write_to_console( const char *file, int line, const char *func, - const char *object_field, - const char *object, const char *buffer) { char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2]; @@ -390,8 +388,6 @@ static int write_to_syslog( const char *file, int line, const char *func, - const char *object_field, - const char *object, const char *buffer) { char header_priority[2 + DECIMAL_STR_MAX(int) + 1], @@ -453,8 +449,6 @@ static int write_to_kmsg( const char *file, int line, const char *func, - const char *object_field, - const char *object, const char *buffer) { char header_priority[2 + DECIMAL_STR_MAX(int) + 1], @@ -485,7 +479,8 @@ static int log_do_header( int level, int error, const char *file, int line, const char *func, - const char *object_field, const char *object) { + const char *object_field, const char *object, + const char *extra_field, const char *extra) { snprintf(header, size, "PRIORITY=%i\n" @@ -495,6 +490,7 @@ static int log_do_header( "%s%s%s" "%s%.*i%s" "%s%s%s" + "%s%s%s" "SYSLOG_IDENTIFIER=%s\n", LOG_PRI(level), LOG_FAC(level), @@ -513,6 +509,9 @@ static int log_do_header( isempty(object) ? "" : object_field, isempty(object) ? "" : object, isempty(object) ? "" : "\n", + isempty(extra) ? "" : extra_field, + isempty(extra) ? "" : extra, + isempty(extra) ? "" : "\n", program_invocation_short_name); return 0; @@ -526,6 +525,8 @@ static int write_to_journal( const char *func, const char *object_field, const char *object, + const char *extra_field, + const char *extra, const char *buffer) { char header[LINE_MAX]; @@ -535,7 +536,7 @@ static int write_to_journal( if (journal_fd < 0) return 0; - log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object); + log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra); IOVEC_SET_STRING(iovec[0], header); IOVEC_SET_STRING(iovec[1], "MESSAGE="); @@ -559,6 +560,8 @@ static int log_dispatch( const char *func, const char *object_field, const char *object, + const char *extra, + const char *extra_field, char *buffer) { assert(buffer); @@ -589,7 +592,7 @@ static int log_dispatch( log_target == LOG_TARGET_JOURNAL_OR_KMSG || log_target == LOG_TARGET_JOURNAL) { - k = write_to_journal(level, error, file, line, func, object_field, object, buffer); + k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer); if (k < 0) { if (k != -EAGAIN) log_close_journal(); @@ -600,7 +603,7 @@ static int log_dispatch( if (log_target == LOG_TARGET_SYSLOG_OR_KMSG || log_target == LOG_TARGET_SYSLOG) { - k = write_to_syslog(level, error, file, line, func, object_field, object, buffer); + k = write_to_syslog(level, error, file, line, func, buffer); if (k < 0) { if (k != -EAGAIN) log_close_syslog(); @@ -615,7 +618,7 @@ static int log_dispatch( log_target == LOG_TARGET_JOURNAL_OR_KMSG || log_target == LOG_TARGET_KMSG)) { - k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer); + k = write_to_kmsg(level, error, file, line, func, buffer); if (k < 0) { log_close_kmsg(); log_open_console(); @@ -623,7 +626,7 @@ static int log_dispatch( } if (k <= 0) - (void) write_to_console(level, error, file, line, func, object_field, object, buffer); + (void) write_to_console(level, error, file, line, func, buffer); buffer = e; } while (buffer); @@ -649,7 +652,7 @@ int log_dump_internal( if (_likely_(LOG_PRI(level) > log_max_level)) return -error; - return log_dispatch(level, error, file, line, func, NULL, NULL, buffer); + return log_dispatch(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer); } int log_internalv( @@ -676,7 +679,7 @@ int log_internalv( vsnprintf(buffer, sizeof(buffer), format, ap); - return log_dispatch(level, error, file, line, func, NULL, NULL, buffer); + return log_dispatch(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer); } int log_internal( @@ -705,6 +708,8 @@ int log_object_internalv( const char *func, const char *object_field, const char *object, + const char *extra_field, + const char *extra, const char *format, va_list ap) { @@ -738,7 +743,7 @@ int log_object_internalv( vsnprintf(b, l, format, ap); - return log_dispatch(level, error, file, line, func, object_field, object, buffer); + return log_dispatch(level, error, file, line, func, object_field, object, extra_field, extra, buffer); } int log_object_internal( @@ -749,13 +754,15 @@ int log_object_internal( const char *func, const char *object_field, const char *object, + const char *extra_field, + const char *extra, const char *format, ...) { va_list ap; int r; va_start(ap, format); - r = log_object_internalv(level, error, file, line, func, object_field, object, format, ap); + r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap); va_end(ap); return r; @@ -780,7 +787,7 @@ static void log_assert( log_abort_msg = buffer; - log_dispatch(level, 0, file, line, func, NULL, NULL, buffer); + log_dispatch(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer); } noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) { @@ -888,7 +895,7 @@ int log_struct_internal( bool fallback = false; /* If the journal is available do structured logging */ - log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL); + log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL); IOVEC_SET_STRING(iovec[n++], header); va_start(ap, format); @@ -935,7 +942,7 @@ int log_struct_internal( if (!found) return -error; - return log_dispatch(level, error, file, line, func, NULL, NULL, buf + 8); + return log_dispatch(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8); } int log_set_target_from_string(const char *e) { diff --git a/src/basic/log.h b/src/basic/log.h index b6356228d9..2afee20bb5 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -100,18 +100,22 @@ int log_object_internal( const char *func, const char *object_field, const char *object, - const char *format, ...) _printf_(8,9); + const char *extra_field, + const char *extra, + const char *format, ...) _printf_(10,11); int log_object_internalv( int level, int error, - const char*file, + const char *file, int line, const char *func, const char *object_field, const char *object, + const char *extra_field, + const char *extra, const char *format, - va_list ap) _printf_(8,0); + va_list ap) _printf_(9,0); int log_struct_internal( int level, diff --git a/src/core/automount.c b/src/core/automount.c index bdc0e06965..7d7a0a6e46 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -800,6 +800,10 @@ static int automount_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + a->result = AUTOMOUNT_SUCCESS; automount_enter_waiting(a); return 1; diff --git a/src/core/busname.c b/src/core/busname.c index 7952cd31aa..63c7dde0bd 100644 --- a/src/core/busname.c +++ b/src/core/busname.c @@ -639,6 +639,10 @@ static int busname_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + n->result = BUSNAME_SUCCESS; busname_enter_making(n); diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 7873f88785..20bdbc39d0 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -1361,6 +1361,26 @@ int unit_attach_pids_to_cgroup(Unit *u) { return 0; } +static void cgroup_xattr_apply(Unit *u) { + char ids[SD_ID128_STRING_MAX]; + int r; + + assert(u); + + if (!MANAGER_IS_SYSTEM(u->manager)) + return; + + if (sd_id128_is_null(u->invocation_id)) + return; + + r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, + "trusted.invocation_id", + sd_id128_to_string(u->invocation_id, ids), 32, + 0); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to set invocation ID on control group %s, ignoring: %m", u->cgroup_path); +} + static bool unit_has_mask_realized(Unit *u, CGroupMask target_mask, CGroupMask enable_mask) { assert(u); @@ -1404,6 +1424,7 @@ static int unit_realize_cgroup_now(Unit *u, ManagerState state) { /* Finally, apply the necessary attributes. */ cgroup_context_apply(u, target_mask, state); + cgroup_xattr_apply(u); return 0; } diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index ea7ced2fd0..12eb55cb7f 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -464,6 +464,64 @@ static int method_get_unit_by_pid(sd_bus_message *message, void *userdata, sd_bu return sd_bus_reply_method_return(message, "o", path); } +static int method_get_unit_by_invocation_id(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *path = NULL; + Manager *m = userdata; + sd_id128_t id; + const void *a; + Unit *u; + size_t sz; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = sd_bus_message_read_array(message, 'y', &a, &sz); + if (r < 0) + return r; + if (sz == 0) + id = SD_ID128_NULL; + else if (sz == 16) + memcpy(&id, a, sz); + else + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid invocation ID"); + + if (sd_id128_is_null(id)) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + pid_t pid; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return r; + + u = manager_get_unit_by_pid(m, pid); + if (!u) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client " PID_FMT " not member of any unit.", pid); + } else { + u = hashmap_get(m->units_by_invocation_id, &id); + if (!u) + return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, "No unit with the specified invocation ID " SD_ID128_FORMAT_STR " known.", SD_ID128_FORMAT_VAL(id)); + } + + r = mac_selinux_unit_access_check(u, message, "status", error); + if (r < 0) + return r; + + /* So here's a special trick: the bus path we return actually references the unit by its invocation ID instead + * of the unit name. This means it stays valid only as long as the invocation ID stays the same. */ + path = unit_dbus_path_invocation_id(u); + if (!path) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", path); +} + static int method_load_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *path = NULL; Manager *m = userdata; @@ -2254,6 +2312,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitByInvocationID", "ay", "o", method_get_unit_by_invocation_id, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 5020dfba4b..245912fc0f 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -764,6 +764,7 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), 0), SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Stop", "s", "o", method_stop, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/core/device.c b/src/core/device.c index 16e56efcc3..8a3e888e5e 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -464,6 +464,10 @@ static void device_update_found_one(Device *d, bool add, DeviceFound found, bool if (!now) return; + /* Didn't exist before, but does now? if so, generate a new invocation ID for it */ + if (previous == DEVICE_NOT_FOUND && d->found != DEVICE_NOT_FOUND) + (void) unit_acquire_invocation_id(UNIT(d)); + if (d->found & DEVICE_FOUND_UDEV) /* When the device is known to udev we consider it * plugged. */ diff --git a/src/core/execute.c b/src/core/execute.c index d5c4e60796..7079aeed6e 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1553,10 +1553,11 @@ static int build_environment( unsigned n_env = 0; char *x; + assert(u); assert(c); assert(ret); - our_env = new0(char*, 13); + our_env = new0(char*, 14); if (!our_env) return -ENOMEM; @@ -1627,6 +1628,13 @@ static int build_environment( our_env[n_env++] = x; } + if (!sd_id128_is_null(u->invocation_id)) { + if (asprintf(&x, "INVOCATION_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(u->invocation_id)) < 0) + return -ENOMEM; + + our_env[n_env++] = x; + } + if (exec_context_needs_term(c)) { const char *tty_path, *term = NULL; diff --git a/src/core/manager.c b/src/core/manager.c index c1dce62a18..3569249788 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -522,6 +522,7 @@ static void manager_clean_environment(Manager *m) { "LISTEN_FDNAMES", "WATCHDOG_PID", "WATCHDOG_USEC", + "INVOCATION_ID", NULL); } @@ -582,9 +583,15 @@ int manager_new(UnitFileScope scope, bool test_run, Manager **_m) { if (MANAGER_IS_SYSTEM(m)) { m->unit_log_field = "UNIT="; m->unit_log_format_string = "UNIT=%s"; + + m->invocation_log_field = "INVOCATION_ID="; + m->invocation_log_format_string = "INVOCATION_ID=" SD_ID128_FORMAT_STR; } else { m->unit_log_field = "USER_UNIT="; m->unit_log_format_string = "USER_UNIT=%s"; + + m->invocation_log_field = "USER_INVOCATION_ID="; + m->invocation_log_format_string = "USER_INVOCATION_ID=" SD_ID128_FORMAT_STR; } m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1; @@ -1062,6 +1069,7 @@ Manager* manager_free(Manager *m) { hashmap_free(m->dynamic_users); hashmap_free(m->units); + hashmap_free(m->units_by_invocation_id); hashmap_free(m->jobs); hashmap_free(m->watch_pids1); hashmap_free(m->watch_pids2); @@ -2268,6 +2276,7 @@ int manager_loop(Manager *m) { int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u) { _cleanup_free_ char *n = NULL; + sd_id128_t invocation_id; Unit *u; int r; @@ -2279,12 +2288,25 @@ int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, if (r < 0) return r; + /* Permit addressing units by invocation ID: if the passed bus path is suffixed by a 128bit ID then we use it + * as invocation ID. */ + r = sd_id128_from_string(n, &invocation_id); + if (r >= 0) { + u = hashmap_get(m->units_by_invocation_id, &invocation_id); + if (u) { + *_u = u; + return 0; + } + + return sd_bus_error_setf(e, BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, "No unit with the specified invocation ID " SD_ID128_FORMAT_STR " known.", SD_ID128_FORMAT_VAL(invocation_id)); + } + + /* If this didn't work, we use the suffix as unit name. */ r = manager_load_unit(m, n, NULL, e, &u); if (r < 0) return r; *_u = u; - return 0; } diff --git a/src/core/manager.h b/src/core/manager.h index 495440b446..29fe14e10b 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -89,6 +89,7 @@ struct Manager { /* Active jobs and units */ Hashmap *units; /* name string => Unit object n:1 */ + Hashmap *units_by_invocation_id; Hashmap *jobs; /* job id => Job object 1:1 */ /* To make it easy to iterate through the units of a specific @@ -319,6 +320,9 @@ struct Manager { const char *unit_log_field; const char *unit_log_format_string; + const char *invocation_log_field; + const char *invocation_log_format_string; + int first_boot; /* tri-state */ }; diff --git a/src/core/mount.c b/src/core/mount.c index 04025b83b9..436c0e1029 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1005,6 +1005,10 @@ static int mount_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + m->result = MOUNT_SUCCESS; m->reload_result = MOUNT_SUCCESS; m->reset_cpu_usage = true; @@ -1742,9 +1746,10 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, case MOUNT_DEAD: case MOUNT_FAILED: - /* This has just been mounted by - * somebody else, follow the state - * change. */ + + /* This has just been mounted by somebody else, follow the state change, but let's + * generate a new invocation ID for this implicitly and automatically. */ + (void) unit_acquire_invocation_id(UNIT(mount)); mount_enter_mounted(mount, MOUNT_SUCCESS); break; diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf index 647e5f736c..6caa15b0b8 100644 --- a/src/core/org.freedesktop.systemd1.conf +++ b/src/core/org.freedesktop.systemd1.conf @@ -52,6 +52,10 @@ send_interface="org.freedesktop.systemd1.Manager" send_member="GetUnitByPID"/> + + diff --git a/src/core/path.c b/src/core/path.c index 10f9b06974..83f794be89 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -577,6 +577,10 @@ static int path_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + path_mkdir(p); p->result = PATH_SUCCESS; diff --git a/src/core/scope.c b/src/core/scope.c index 65fa65493b..e7583f6d89 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -298,6 +298,10 @@ static int scope_start(Unit *u) { if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) return -ENOENT; + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + (void) unit_realize_cgroup(u); (void) unit_reset_cpu_usage(u); diff --git a/src/core/service.c b/src/core/service.c index 99a70395fc..8ce25c494c 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2033,6 +2033,10 @@ static int service_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + s->result = SERVICE_SUCCESS; s->reload_result = SERVICE_SUCCESS; s->main_pid_known = false; diff --git a/src/core/slice.c b/src/core/slice.c index c7700b8857..03fe797f27 100644 --- a/src/core/slice.c +++ b/src/core/slice.c @@ -187,10 +187,15 @@ static void slice_dump(Unit *u, FILE *f, const char *prefix) { static int slice_start(Unit *u) { Slice *t = SLICE(u); + int r; assert(t); assert(t->state == SLICE_DEAD); + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + (void) unit_realize_cgroup(u); (void) unit_reset_cpu_usage(u); diff --git a/src/core/socket.c b/src/core/socket.c index b9032fa5c9..ae8a1f751f 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2354,11 +2354,14 @@ static int socket_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + s->result = SOCKET_SUCCESS; s->reset_cpu_usage = true; socket_enter_start_pre(s); - return 1; } diff --git a/src/core/swap.c b/src/core/swap.c index fb222b6858..0333eaefb8 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -861,6 +861,10 @@ static int swap_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + s->result = SWAP_SUCCESS; s->reset_cpu_usage = true; @@ -1189,6 +1193,7 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v case SWAP_DEAD: case SWAP_FAILED: + (void) unit_acquire_invocation_id(UNIT(swap)); swap_enter_active(swap, SWAP_SUCCESS); break; diff --git a/src/core/target.c b/src/core/target.c index 61a91aad07..765c1f3fa4 100644 --- a/src/core/target.c +++ b/src/core/target.c @@ -124,10 +124,15 @@ static void target_dump(Unit *u, FILE *f, const char *prefix) { static int target_start(Unit *u) { Target *t = TARGET(u); + int r; assert(t); assert(t->state == TARGET_DEAD); + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + target_set_state(t, TARGET_ACTIVE); return 1; } diff --git a/src/core/timer.c b/src/core/timer.c index e2b43f02f8..9538059c13 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -616,6 +616,10 @@ static int timer_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + t->last_trigger = DUAL_TIMESTAMP_NULL; /* Reenable all timers that depend on unit activation time */ @@ -632,7 +636,7 @@ static int timer_start(Unit *u) { /* The timer has never run before, * make sure a stamp file exists. */ - touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID); + (void) touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID); } t->result = TIMER_SUCCESS; diff --git a/src/core/unit.c b/src/core/unit.c index 693f75c928..690f7f7dd9 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -37,6 +37,7 @@ #include "execute.h" #include "fileio-label.h" #include "formats-util.h" +#include "id128-util.h" #include "load-dropin.h" #include "load-fragment.h" #include "log.h" @@ -521,6 +522,9 @@ void unit_free(Unit *u) { SET_FOREACH(t, u->names, i) hashmap_remove_value(u->manager->units, t, u); + if (!sd_id128_is_null(u->invocation_id)) + hashmap_remove_value(u->manager->units_by_invocation_id, &u->invocation_id, u); + if (u->job) { Job *j = u->job; job_uninstall(j); @@ -953,6 +957,10 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { SET_FOREACH(t, u->names, i) fprintf(f, "%s\tName: %s\n", prefix, t); + if (!sd_id128_is_null(u->invocation_id)) + fprintf(f, "%s\tInvocation ID: " SD_ID128_FORMAT_STR "\n", + prefix, SD_ID128_FORMAT_VAL(u->invocation_id)); + STRV_FOREACH(j, u->documentation) fprintf(f, "%s\tDocumentation: %s\n", prefix, *j); @@ -1054,7 +1062,6 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { if (u->nop_job) job_dump(u->nop_job, f, prefix2); - } /* Common implementation for multiple backends */ @@ -2392,6 +2399,15 @@ char *unit_dbus_path(Unit *u) { return unit_dbus_path_from_name(u->id); } +char *unit_dbus_path_invocation_id(Unit *u) { + assert(u); + + if (sd_id128_is_null(u->invocation_id)) + return NULL; + + return unit_dbus_path_from_name(u->invocation_id_string); +} + int unit_set_slice(Unit *u, Unit *slice) { assert(u); assert(slice); @@ -2640,6 +2656,9 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { if (gid_is_valid(u->ref_gid)) unit_serialize_item_format(u, f, "ref-gid", GID_FMT, u->ref_gid); + if (!sd_id128_is_null(u->invocation_id)) + unit_serialize_item_format(u, f, "invocation-id", SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(u->invocation_id)); + bus_track_serialize(u->bus_track, f, "ref"); if (serialize_jobs) { @@ -2914,6 +2933,19 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { if (r < 0) log_oom(); + continue; + } else if (streq(l, "invocation-id")) { + sd_id128_t id; + + r = sd_id128_from_string(v, &id); + if (r < 0) + log_unit_debug(u, "Failed to parse invocation id %s, ignoring.", v); + else { + r = unit_set_invocation_id(u, id); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to set invocation ID for unit: %m"); + } + continue; } @@ -4153,3 +4185,57 @@ void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid) { if (r > 0) bus_unit_send_change_signal(u); } + +int unit_set_invocation_id(Unit *u, sd_id128_t id) { + int r; + + assert(u); + + /* Set the invocation ID for this unit. If we cannot, this will not roll back, but reset the whole thing. */ + + if (sd_id128_equal(u->invocation_id, id)) + return 0; + + if (!sd_id128_is_null(u->invocation_id)) + (void) hashmap_remove_value(u->manager->units_by_invocation_id, &u->invocation_id, u); + + if (sd_id128_is_null(id)) { + r = 0; + goto reset; + } + + r = hashmap_ensure_allocated(&u->manager->units_by_invocation_id, &id128_hash_ops); + if (r < 0) + goto reset; + + u->invocation_id = id; + sd_id128_to_string(id, u->invocation_id_string); + + r = hashmap_put(u->manager->units_by_invocation_id, &u->invocation_id, u); + if (r < 0) + goto reset; + + return 0; + +reset: + u->invocation_id = SD_ID128_NULL; + u->invocation_id_string[0] = 0; + return r; +} + +int unit_acquire_invocation_id(Unit *u) { + sd_id128_t id; + int r; + + assert(u); + + r = sd_id128_randomize(&id); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to generate invocation ID for unit: %m"); + + r = unit_set_invocation_id(u, id); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to set invocation ID for unit: %m"); + + return 0; +} diff --git a/src/core/unit.h b/src/core/unit.h index 3584c16d8c..a8dd3e602c 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -207,6 +207,10 @@ struct Unit { /* How to start OnFailure units */ JobMode on_failure_job_mode; + /* The current invocation ID */ + sd_id128_t invocation_id; + char invocation_id_string[SD_ID128_STRING_MAX]; /* useful when logging */ + /* Garbage collect us we nobody wants or requires us anymore */ bool stop_when_unneeded; @@ -546,6 +550,7 @@ bool unit_job_is_applicable(Unit *u, JobType j); int set_unit_path(const char *p); char *unit_dbus_path(Unit *u); +char *unit_dbus_path_invocation_id(Unit *u); int unit_load_related_unit(Unit *u, const char *type, Unit **_found); @@ -643,12 +648,15 @@ void unit_unref_uid_gid(Unit *u, bool destroy_now); void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid); +int unit_set_invocation_id(Unit *u, sd_id128_t id); +int unit_acquire_invocation_id(Unit *u); + /* Macros which append UNIT= or USER_UNIT= to the message */ #define log_unit_full(unit, level, error, ...) \ ({ \ const Unit *_u = (unit); \ - _u ? log_object_internal(level, error, __FILE__, __LINE__, __func__, _u->manager->unit_log_field, _u->id, ##__VA_ARGS__) : \ + _u ? log_object_internal(level, error, __FILE__, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \ log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 015b74b203..f01cf1d937 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -44,6 +44,7 @@ #include "fs-util.h" #include "hashmap.h" #include "hostname-util.h" +#include "id128-util.h" #include "io-util.h" #include "journal-authenticate.h" #include "journal-file.h" @@ -56,6 +57,7 @@ #include "journald-server.h" #include "journald-stream.h" #include "journald-syslog.h" +#include "log.h" #include "missing.h" #include "mkdir.h" #include "parse-util.h" @@ -69,7 +71,6 @@ #include "string-table.h" #include "string-util.h" #include "user-util.h" -#include "log.h" #define USER_JOURNALS_MAX 1024 @@ -675,6 +676,44 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned server_schedule_sync(s, priority); } +static int get_invocation_id(const char *cgroup_root, const char *slice, const char *unit, char **ret) { + _cleanup_free_ char *escaped = NULL, *slice_path = NULL, *p = NULL; + char *copy, ids[SD_ID128_STRING_MAX]; + int r; + + /* Read the invocation ID of a unit off a unit. It's stored in the "trusted.invocation_id" extended attribute + * on the cgroup path. */ + + r = cg_slice_to_path(slice, &slice_path); + if (r < 0) + return r; + + escaped = cg_escape(unit); + if (!escaped) + return -ENOMEM; + + p = strjoin(cgroup_root, "/", slice_path, "/", escaped, NULL); + if (!p) + return -ENOMEM; + + r = cg_get_xattr(SYSTEMD_CGROUP_CONTROLLER, p, "trusted.invocation_id", ids, 32); + if (r < 0) + return r; + if (r != 32) + return -EINVAL; + ids[32] = 0; + + if (!id128_is_valid(ids)) + return -EINVAL; + + copy = strdup(ids); + if (!copy) + return -ENOMEM; + + *ret = copy; + return 0; +} + static void dispatch_message_real( Server *s, struct iovec *iovec, unsigned n, unsigned m, @@ -771,6 +810,7 @@ static void dispatch_message_real( r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &c); if (r >= 0) { + _cleanup_free_ char *raw_unit = NULL, *raw_slice = NULL; char *session = NULL; x = strjoina("_SYSTEMD_CGROUP=", c); @@ -790,9 +830,8 @@ static void dispatch_message_real( IOVEC_SET_STRING(iovec[n++], owner_uid); } - if (cg_path_get_unit(c, &t) >= 0) { - x = strjoina("_SYSTEMD_UNIT=", t); - free(t); + if (cg_path_get_unit(c, &raw_unit) >= 0) { + x = strjoina("_SYSTEMD_UNIT=", raw_unit); IOVEC_SET_STRING(iovec[n++], x); } else if (unit_id && !session) { x = strjoina("_SYSTEMD_UNIT=", unit_id); @@ -808,9 +847,8 @@ static void dispatch_message_real( IOVEC_SET_STRING(iovec[n++], x); } - if (cg_path_get_slice(c, &t) >= 0) { - x = strjoina("_SYSTEMD_SLICE=", t); - free(t); + if (cg_path_get_slice(c, &raw_slice) >= 0) { + x = strjoina("_SYSTEMD_SLICE=", raw_slice); IOVEC_SET_STRING(iovec[n++], x); } @@ -820,6 +858,14 @@ static void dispatch_message_real( IOVEC_SET_STRING(iovec[n++], x); } + if (raw_slice && raw_unit) { + if (get_invocation_id(s->cgroup_root, raw_slice, raw_unit, &t) >= 0) { + x = strjoina("_SYSTEMD_INVOCATION_ID=", t); + free(t); + IOVEC_SET_STRING(iovec[n++], x); + } + } + free(c); } else if (unit_id) { x = strjoina("_SYSTEMD_UNIT=", unit_id); diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 784d24833d..dfb5724794 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -153,7 +153,7 @@ struct Server { #define SERVER_MACHINE_ID(s) ((s)->machine_id_field + strlen("_MACHINE_ID=")) -#define N_IOVEC_META_FIELDS 21 +#define N_IOVEC_META_FIELDS 22 #define N_IOVEC_KERNEL_FIELDS 64 #define N_IOVEC_UDEV_FIELDS 32 #define N_IOVEC_OBJECT_FIELDS 14 diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 70ea347361..d48ef6bbe2 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -509,4 +509,5 @@ global: sd_bus_track_count_sender; sd_bus_set_exit_on_disconnect; sd_bus_get_exit_on_disconnect; + sd_id128_get_invocation; } LIBSYSTEMD_231; diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index 9cc28ed564..d2a826bf6e 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -27,6 +27,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_UNIT, ENOENT), SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_PID, ESRCH), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, ENOENT), SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_EXISTS, EEXIST), SD_BUS_ERROR_MAP(BUS_ERROR_LOAD_FAILED, EIO), SD_BUS_ERROR_MAP(BUS_ERROR_JOB_FAILED, EREMOTEIO), diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index 5df21c8926..525b79fa77 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -23,6 +23,7 @@ #define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit" #define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID" +#define BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID "org.freedesktop.systemd1.NoUnitForInvocationID" #define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists" #define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed" #define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed" diff --git a/src/libsystemd/sd-id128/id128-util.c b/src/libsystemd/sd-id128/id128-util.c index c3f527d657..337eae24b4 100644 --- a/src/libsystemd/sd-id128/id128-util.c +++ b/src/libsystemd/sd-id128/id128-util.c @@ -192,3 +192,16 @@ int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) { return id128_write_fd(fd, f, id, do_sync); } + +void id128_hash_func(const void *p, struct siphash *state) { + siphash24_compress(p, 16, state); +} + +int id128_compare_func(const void *a, const void *b) { + return memcmp(a, b, 16); +} + +const struct hash_ops id128_hash_ops = { + .hash = id128_hash_func, + .compare = id128_compare_func, +}; diff --git a/src/libsystemd/sd-id128/id128-util.h b/src/libsystemd/sd-id128/id128-util.h index 3ba59acbca..6b3855acbb 100644 --- a/src/libsystemd/sd-id128/id128-util.h +++ b/src/libsystemd/sd-id128/id128-util.h @@ -22,6 +22,8 @@ #include #include "sd-id128.h" + +#include "hash-funcs.h" #include "macro.h" char *id128_to_uuid_string(sd_id128_t id, char s[37]); @@ -43,3 +45,7 @@ int id128_read(const char *p, Id128Format f, sd_id128_t *ret); int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync); int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync); + +void id128_hash_func(const void *p, struct siphash *state); +int id128_compare_func(const void *a, const void *b) _pure_; +extern const struct hash_ops id128_hash_ops; diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c index 9f47d04e61..d4450c70a0 100644 --- a/src/libsystemd/sd-id128/sd-id128.c +++ b/src/libsystemd/sd-id128/sd-id128.c @@ -129,6 +129,28 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) { return 0; } +_public_ int sd_id128_get_invocation(sd_id128_t *ret) { + static thread_local sd_id128_t saved_invocation_id = {}; + int r; + + assert_return(ret, -EINVAL); + + if (sd_id128_is_null(saved_invocation_id)) { + const char *e; + + e = secure_getenv("INVOCATION_ID"); + if (!e) + return -ENXIO; + + r = sd_id128_from_string(e, &saved_invocation_id); + if (r < 0) + return r; + } + + *ret = saved_invocation_id; + return 0; +} + static sd_id128_t make_v4_uuid(sd_id128_t id) { /* Stolen from generate_random_uuid() of drivers/char/random.c * in the kernel sources */ diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 05b2a2b323..77f72d070e 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -187,7 +187,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); #define log_link_full(link, level, error, ...) \ ({ \ const Link *_l = (link); \ - _l ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, ##__VA_ARGS__) : \ + _l ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \ log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }) \ diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h index 31b55e2791..70ff947b99 100644 --- a/src/network/networkd-netdev.h +++ b/src/network/networkd-netdev.h @@ -182,7 +182,7 @@ const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, unsign #define log_netdev_full(netdev, level, error, ...) \ ({ \ const NetDev *_n = (netdev); \ - _n ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _n->ifname, ##__VA_ARGS__) : \ + _n ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _n->ifname, NULL, NULL, ##__VA_ARGS__) : \ log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }) diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 64fcf9295f..bb90c89cc2 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1338,7 +1338,7 @@ int bus_property_get_id128( if (sd_id128_is_null(*id)) /* Add an empty array if the ID is zero */ return sd_bus_message_append(reply, "ay", 0); else - return sd_bus_message_append_array(reply, 'b', id->bytes, 16); + return sd_bus_message_append_array(reply, 'y', id->bytes, 16); } #if __SIZEOF_SIZE_T__ != 8 diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h index 4dff0b9b81..ee011b1861 100644 --- a/src/systemd/sd-id128.h +++ b/src/systemd/sd-id128.h @@ -45,8 +45,8 @@ int sd_id128_from_string(const char *s, sd_id128_t *ret); int sd_id128_randomize(sd_id128_t *ret); int sd_id128_get_machine(sd_id128_t *ret); - int sd_id128_get_boot(sd_id128_t *ret); +int sd_id128_get_invocation(sd_id128_t *ret); #define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \ ((const sd_id128_t) { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \ -- cgit v1.2.3-54-g00ecf From 6b430fdb7c0c2c52ea69a7d56f23d739218b13d0 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 18:28:30 -0400 Subject: tree-wide: use mfree more --- coccinelle/mfree_return.cocci | 6 ++++++ src/basic/bitmap.c | 6 ++---- src/basic/env-util.c | 3 +-- src/basic/prioq.c | 4 +--- src/basic/replace-var.c | 3 +-- src/basic/strbuf.c | 3 +-- src/basic/string-util.c | 6 ++---- src/basic/strv.c | 9 +++------ src/core/dynamic-user.c | 4 +--- src/core/execute.c | 4 +--- src/core/manager.c | 3 +-- src/core/transaction.c | 6 ++---- src/core/unit.c | 6 ++---- src/cryptsetup/cryptsetup-generator.c | 9 +++------ src/import/curl-util.c | 4 +--- src/import/export-raw.c | 4 +--- src/import/export-tar.c | 4 +--- src/import/import-raw.c | 4 +--- src/import/import-tar.c | 4 +--- src/import/importd.c | 6 ++---- src/import/pull-job.c | 4 +--- src/import/pull-raw.c | 4 +--- src/import/pull-tar.c | 4 +--- src/journal-remote/journal-remote-write.c | 10 +++------- src/journal/journal-file.c | 3 +-- src/journal/mmap-cache.c | 6 ++---- src/journal/sd-journal.c | 9 +++------ src/libsystemd-network/ndisc-router.c | 3 +-- src/libsystemd-network/sd-dhcp-client.c | 4 +--- src/libsystemd-network/sd-dhcp-lease.c | 4 +--- src/libsystemd-network/sd-dhcp-server.c | 4 +--- src/libsystemd-network/sd-dhcp6-client.c | 4 +--- src/libsystemd-network/sd-dhcp6-lease.c | 4 +--- src/libsystemd-network/sd-ipv4acd.c | 4 +--- src/libsystemd-network/sd-ipv4ll.c | 4 +--- src/libsystemd-network/sd-lldp.c | 4 +--- src/libsystemd-network/sd-ndisc.c | 4 +--- src/libsystemd/sd-bus/bus-slot.c | 4 +--- src/libsystemd/sd-bus/bus-track.c | 8 ++------ src/libudev/libudev-list.c | 14 ++++++-------- src/libudev/libudev-monitor.c | 3 +-- src/login/logind-button.c | 9 +++------ src/login/logind-device.c | 9 +++------ src/login/logind-inhibit.c | 9 +++------ src/login/logind-seat.c | 9 +++------ src/login/logind-session.c | 12 ++++-------- src/machine/machine.c | 4 +--- src/machine/operation.c | 3 +-- src/network/networkd-wait-online-link.c | 3 +-- src/nspawn/nspawn-settings.c | 4 +--- src/resolve/resolved-dns-query.c | 8 ++------ src/resolve/resolved-dns-rr.c | 10 +++------- src/resolve/resolved-dns-scope.c | 4 +--- src/resolve/resolved-dns-search-domain.c | 4 +--- src/resolve/resolved-dns-server.c | 3 +-- src/resolve/resolved-dns-stream.c | 4 +--- src/resolve/resolved-dns-transaction.c | 3 +-- src/resolve/resolved-link.c | 6 ++---- src/resolve/resolved-manager.c | 4 +--- src/shared/machine-image.c | 3 +-- src/shared/ptyfwd.c | 3 +-- src/timesync/timesyncd-server.c | 7 ++----- src/udev/udev-ctrl.c | 3 +-- src/udev/udev-rules.c | 3 +-- 64 files changed, 105 insertions(+), 228 deletions(-) create mode 100644 coccinelle/mfree_return.cocci (limited to 'src/libsystemd/sd-bus') diff --git a/coccinelle/mfree_return.cocci b/coccinelle/mfree_return.cocci new file mode 100644 index 0000000000..8119fe07f2 --- /dev/null +++ b/coccinelle/mfree_return.cocci @@ -0,0 +1,6 @@ +@@ +expression p; +@@ +- free(p); +- return NULL; ++ return mfree(p); diff --git a/src/basic/bitmap.c b/src/basic/bitmap.c index f4b12fc261..f6212e6151 100644 --- a/src/basic/bitmap.c +++ b/src/basic/bitmap.c @@ -58,10 +58,8 @@ Bitmap *bitmap_copy(Bitmap *b) { return NULL; ret->bitmaps = newdup(uint64_t, b->bitmaps, b->n_bitmaps); - if (!ret->bitmaps) { - free(ret); - return NULL; - } + if (!ret->bitmaps) + return mfree(ret); ret->n_bitmaps = ret->bitmaps_allocated = b->n_bitmaps; return ret; diff --git a/src/basic/env-util.c b/src/basic/env-util.c index 7f5fddb700..b74290d6fd 100644 --- a/src/basic/env-util.c +++ b/src/basic/env-util.c @@ -544,8 +544,7 @@ char *replace_env(const char *format, char **env) { return k; fail: - free(r); - return NULL; + return mfree(r); } char **replace_env_argv(char **argv, char **env) { diff --git a/src/basic/prioq.c b/src/basic/prioq.c index d2ec516d29..4570b8e4ba 100644 --- a/src/basic/prioq.c +++ b/src/basic/prioq.c @@ -62,9 +62,7 @@ Prioq* prioq_free(Prioq *q) { return NULL; free(q->items); - free(q); - - return NULL; + return mfree(q); } int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func) { diff --git a/src/basic/replace-var.c b/src/basic/replace-var.c index 6a204b9ec3..0d21423a9c 100644 --- a/src/basic/replace-var.c +++ b/src/basic/replace-var.c @@ -107,6 +107,5 @@ char *replace_var(const char *text, char *(*lookup)(const char *variable, void*u return r; oom: - free(r); - return NULL; + return mfree(r); } diff --git a/src/basic/strbuf.c b/src/basic/strbuf.c index 4bef87d3c2..00aaf9e621 100644 --- a/src/basic/strbuf.c +++ b/src/basic/strbuf.c @@ -62,8 +62,7 @@ struct strbuf *strbuf_new(void) { err: free(str->buf); free(str->root); - free(str); - return NULL; + return mfree(str); } static void strbuf_node_cleanup(struct strbuf_node *node) { diff --git a/src/basic/string-util.c b/src/basic/string-util.c index dc7de5dab8..6b06e643c9 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -610,8 +610,7 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin return r; oom: - free(r); - return NULL; + return mfree(r); } char *strip_tab_ansi(char **ibuf, size_t *_isz) { @@ -682,8 +681,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) { if (ferror(f)) { fclose(f); - free(obuf); - return NULL; + return mfree(obuf); } fclose(f); diff --git a/src/basic/strv.c b/src/basic/strv.c index 34e464d253..0eec868eed 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -87,8 +87,7 @@ void strv_clear(char **l) { char **strv_free(char **l) { strv_clear(l); - free(l); - return NULL; + return mfree(l); } char **strv_free_erase(char **l) { @@ -426,8 +425,7 @@ char *strv_join_quoted(char **l) { return buf; oom: - free(buf); - return NULL; + return mfree(buf); } int strv_push(char ***l, char *value) { @@ -869,8 +867,7 @@ char ***strv_free_free(char ***l) { for (i = l; *i; i++) strv_free(*i); - free(l); - return NULL; + return mfree(l); } char **strv_skip(char **l, size_t n) { diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c index 1043da3eb7..e1846e1adb 100644 --- a/src/core/dynamic-user.c +++ b/src/core/dynamic-user.c @@ -42,9 +42,7 @@ static DynamicUser* dynamic_user_free(DynamicUser *d) { (void) hashmap_remove(d->manager->dynamic_users, d->name); safe_close_pair(d->storage_socket); - free(d); - - return NULL; + return mfree(d); } static int dynamic_user_add(Manager *m, const char *name, int storage_socket[2], DynamicUser **ret) { diff --git a/src/core/execute.c b/src/core/execute.c index 869522704a..59c2bd0dd2 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -3740,9 +3740,7 @@ ExecRuntime *exec_runtime_unref(ExecRuntime *r) { free(r->tmp_dir); free(r->var_tmp_dir); safe_close_pair(r->netns_storage_socket); - free(r); - - return NULL; + return mfree(r); } int exec_runtime_serialize(Unit *u, ExecRuntime *rt, FILE *f, FDSet *fds) { diff --git a/src/core/manager.c b/src/core/manager.c index 3569249788..50aae0d1ba 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1119,8 +1119,7 @@ Manager* manager_free(Manager *m) { hashmap_free(m->uid_refs); hashmap_free(m->gid_refs); - free(m); - return NULL; + return mfree(m); } void manager_enumerate(Manager *m) { diff --git a/src/core/transaction.c b/src/core/transaction.c index 8370b864fb..e22e3b30c2 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -1085,10 +1085,8 @@ Transaction *transaction_new(bool irreversible) { return NULL; tr->jobs = hashmap_new(NULL); - if (!tr->jobs) { - free(tr); - return NULL; - } + if (!tr->jobs) + return mfree(tr); tr->irreversible = irreversible; diff --git a/src/core/unit.c b/src/core/unit.c index 67668bdc48..a6b8ecdcb7 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -88,10 +88,8 @@ Unit *unit_new(Manager *m, size_t size) { return NULL; u->names = set_new(&string_hash_ops); - if (!u->names) { - free(u); - return NULL; - } + if (!u->names) + return mfree(u); u->manager = m; u->type = _UNIT_TYPE_INVALID; diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 8ac5ab730a..de0a3b6f9c 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -264,16 +264,13 @@ static crypto_device *get_crypto_device(const char *uuid) { d->keyfile = d->options = d->name = NULL; d->uuid = strdup(uuid); - if (!d->uuid) { - free(d); - return NULL; - } + if (!d->uuid) + return mfree(d); r = hashmap_put(arg_disks, d->uuid, d); if (r < 0) { free(d->uuid); - free(d); - return NULL; + return mfree(d); } } diff --git a/src/import/curl-util.c b/src/import/curl-util.c index 6990c47f48..734e1560e6 100644 --- a/src/import/curl-util.c +++ b/src/import/curl-util.c @@ -235,9 +235,7 @@ CurlGlue *curl_glue_unref(CurlGlue *g) { sd_event_source_unref(g->timer); sd_event_unref(g->event); - free(g); - - return NULL; + return mfree(g); } int curl_glue_new(CurlGlue **glue, sd_event *event) { diff --git a/src/import/export-raw.c b/src/import/export-raw.c index 6136b677dd..a3dbce1954 100644 --- a/src/import/export-raw.c +++ b/src/import/export-raw.c @@ -87,9 +87,7 @@ RawExport *raw_export_unref(RawExport *e) { free(e->buffer); free(e->path); - free(e); - - return NULL; + return mfree(e); } int raw_export_new( diff --git a/src/import/export-tar.c b/src/import/export-tar.c index d79c27f2d0..3bb6027431 100644 --- a/src/import/export-tar.c +++ b/src/import/export-tar.c @@ -91,9 +91,7 @@ TarExport *tar_export_unref(TarExport *e) { free(e->buffer); free(e->path); - free(e); - - return NULL; + return mfree(e); } int tar_export_new( diff --git a/src/import/import-raw.c b/src/import/import-raw.c index fd6b9f7703..29f3f896e5 100644 --- a/src/import/import-raw.c +++ b/src/import/import-raw.c @@ -100,9 +100,7 @@ RawImport* raw_import_unref(RawImport *i) { free(i->final_path); free(i->image_root); free(i->local); - free(i); - - return NULL; + return mfree(i); } int raw_import_new( diff --git a/src/import/import-tar.c b/src/import/import-tar.c index 8b81324fde..22f9b8c5ea 100644 --- a/src/import/import-tar.c +++ b/src/import/import-tar.c @@ -107,9 +107,7 @@ TarImport* tar_import_unref(TarImport *i) { free(i->final_path); free(i->image_root); free(i->local); - free(i); - - return NULL; + return mfree(i); } int tar_import_new( diff --git a/src/import/importd.c b/src/import/importd.c index 28b4302cb3..9d31a956a5 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -141,8 +141,7 @@ static Transfer *transfer_unref(Transfer *t) { safe_close(t->stdin_fd); safe_close(t->stdout_fd); - free(t); - return NULL; + return mfree(t); } DEFINE_TRIVIAL_CLEANUP_FUNC(Transfer*, transfer_unref); @@ -548,8 +547,7 @@ static Manager *manager_unref(Manager *m) { m->bus = sd_bus_flush_close_unref(m->bus); sd_event_unref(m->event); - free(m); - return NULL; + return mfree(m); } DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref); diff --git a/src/import/pull-job.c b/src/import/pull-job.c index 6bcf35ef4e..e550df2c57 100644 --- a/src/import/pull-job.c +++ b/src/import/pull-job.c @@ -50,9 +50,7 @@ PullJob* pull_job_unref(PullJob *j) { free(j->payload); free(j->checksum); - free(j); - - return NULL; + return mfree(j); } static void pull_job_finish(PullJob *j, int ret) { diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c index 8993402821..0cf410a5d9 100644 --- a/src/import/pull-raw.c +++ b/src/import/pull-raw.c @@ -110,9 +110,7 @@ RawPull* raw_pull_unref(RawPull *i) { free(i->settings_path); free(i->image_root); free(i->local); - free(i); - - return NULL; + return mfree(i); } int raw_pull_new( diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c index 8c61c46f73..68e2397b02 100644 --- a/src/import/pull-tar.c +++ b/src/import/pull-tar.c @@ -114,9 +114,7 @@ TarPull* tar_pull_unref(TarPull *i) { free(i->settings_path); free(i->image_root); free(i->local); - free(i); - - return NULL; + return mfree(i); } int tar_pull_new( diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c index 7bba52566e..8729372aa3 100644 --- a/src/journal-remote/journal-remote-write.c +++ b/src/journal-remote/journal-remote-write.c @@ -75,10 +75,8 @@ Writer* writer_new(RemoteServer *server) { memset(&w->metrics, 0xFF, sizeof(w->metrics)); w->mmap = mmap_cache_new(); - if (!w->mmap) { - free(w); - return NULL; - } + if (!w->mmap) + return mfree(w); w->n_ref = 1; w->server = server; @@ -103,9 +101,7 @@ Writer* writer_free(Writer *w) { if (w->mmap) mmap_cache_unref(w->mmap); - free(w); - - return NULL; + return mfree(w); } Writer* writer_unref(Writer *w) { diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 49199b269f..d3e0214731 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -394,8 +394,7 @@ JournalFile* journal_file_close(JournalFile *f) { gcry_md_close(f->hmac); #endif - free(f); - return NULL; + return mfree(f); } void journal_file_close_set(Set *s) { diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c index 293d27053a..d91247b524 100644 --- a/src/journal/mmap-cache.c +++ b/src/journal/mmap-cache.c @@ -325,10 +325,8 @@ static FileDescriptor* fd_add(MMapCache *m, int fd) { f->fd = fd; r = hashmap_put(m->fds, FD_TO_PTR(fd), f); - if (r < 0) { - free(f); - return NULL; - } + if (r < 0) + return mfree(f); return f; } diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 98c8a47afe..f2f8546086 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -387,7 +387,7 @@ _public_ int sd_journal_add_disjunction(sd_journal *j) { } static char *match_make_string(Match *m) { - char *p, *r; + char *p = NULL, *r; Match *i; bool enclose = false; @@ -397,15 +397,12 @@ static char *match_make_string(Match *m) { if (m->type == MATCH_DISCRETE) return strndup(m->data, m->size); - p = NULL; LIST_FOREACH(matches, i, m->matches) { char *t, *k; t = match_make_string(i); - if (!t) { - free(p); - return NULL; - } + if (!t) + return mfree(p); if (p) { k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t, NULL); diff --git a/src/libsystemd-network/ndisc-router.c b/src/libsystemd-network/ndisc-router.c index d9950b638c..41ff2b353a 100644 --- a/src/libsystemd-network/ndisc-router.c +++ b/src/libsystemd-network/ndisc-router.c @@ -49,8 +49,7 @@ _public_ sd_ndisc_router* sd_ndisc_router_unref(sd_ndisc_router *rt) { if (rt->n_ref > 0) return NULL; - free(rt); - return NULL; + return mfree(rt); } sd_ndisc_router *ndisc_router_new(size_t raw_size) { diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 179e5950bd..5ccb23922c 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -1873,9 +1873,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) { free(client->req_opts); free(client->hostname); free(client->vendor_class_identifier); - free(client); - - return NULL; + return mfree(client); } int sd_dhcp_client_new(sd_dhcp_client **ret) { diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index ef50ed17a1..8387b185c0 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -282,9 +282,7 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) { free(lease->static_route); free(lease->client_id); free(lease->vendor_specific); - free(lease); - - return NULL; + return mfree(lease); } static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) { diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 11ee2e252e..f16314a37f 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -178,9 +178,7 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) { hashmap_free(server->leases_by_client_id); free(server->bound_leases); - free(server); - - return NULL; + return mfree(server); } int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) { diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 463fde401c..e81215f7d7 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -1300,9 +1300,7 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) { sd_dhcp6_client_detach_event(client); free(client->req_opts); - free(client); - - return NULL; + return mfree(client); } int sd_dhcp6_client_new(sd_dhcp6_client **ret) { diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index 5c10a6326a..ab59977a3f 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -389,9 +389,7 @@ sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) { free(lease->ntp); lease->ntp_fqdn = strv_free(lease->ntp_fqdn); - free(lease); - - return NULL; + return mfree(lease); } int dhcp6_lease_new(sd_dhcp6_lease **ret) { diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c index 662885840f..4dd343c101 100644 --- a/src/libsystemd-network/sd-ipv4acd.c +++ b/src/libsystemd-network/sd-ipv4acd.c @@ -135,9 +135,7 @@ sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd) { ipv4acd_reset(acd); sd_ipv4acd_detach_event(acd); - free(acd); - - return NULL; + return mfree(acd); } int sd_ipv4acd_new(sd_ipv4acd **ret) { diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c index 5603a533a5..13209261f9 100644 --- a/src/libsystemd-network/sd-ipv4ll.c +++ b/src/libsystemd-network/sd-ipv4ll.c @@ -90,9 +90,7 @@ sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) { return NULL; sd_ipv4acd_unref(ll->acd); - free(ll); - - return NULL; + return mfree(ll); } int sd_ipv4ll_new(sd_ipv4ll **ret) { diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c index 0bd1e66aa0..0702241506 100644 --- a/src/libsystemd-network/sd-lldp.c +++ b/src/libsystemd-network/sd-lldp.c @@ -374,9 +374,7 @@ _public_ sd_lldp* sd_lldp_unref(sd_lldp *lldp) { hashmap_free(lldp->neighbor_by_id); prioq_free(lldp->neighbor_by_expiry); - free(lldp); - - return NULL; + return mfree(lldp); } _public_ int sd_lldp_new(sd_lldp **ret) { diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c index 07b0d7f704..1d3be9b862 100644 --- a/src/libsystemd-network/sd-ndisc.c +++ b/src/libsystemd-network/sd-ndisc.c @@ -148,9 +148,7 @@ _public_ sd_ndisc *sd_ndisc_unref(sd_ndisc *nd) { ndisc_reset(nd); sd_ndisc_detach_event(nd); - free(nd); - - return NULL; + return mfree(nd); } _public_ int sd_ndisc_new(sd_ndisc **ret) { diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c index 8e9074c7df..33590c31ac 100644 --- a/src/libsystemd/sd-bus/bus-slot.c +++ b/src/libsystemd/sd-bus/bus-slot.c @@ -212,9 +212,7 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) { bus_slot_disconnect(slot); free(slot->description); - free(slot); - - return NULL; + return mfree(slot); } _public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) { diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 00e93a215f..4acaf24793 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -74,9 +74,7 @@ static struct track_item* track_item_free(struct track_item *i) { sd_bus_slot_unref(i->slot); free(i->name); - free(i); - - return NULL; + return mfree(i); } DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free); @@ -206,9 +204,7 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { bus_track_remove_from_queue(track); hashmap_free(track->names); sd_bus_unref(track->bus); - free(track); - - return NULL; + return mfree(track); } static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { diff --git a/src/libudev/libudev-list.c b/src/libudev/libudev-list.c index da496ed456..0d51322a15 100644 --- a/src/libudev/libudev-list.c +++ b/src/libudev/libudev-list.c @@ -166,17 +166,16 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char * entry = new0(struct udev_list_entry, 1); if (entry == NULL) return NULL; + entry->name = strdup(name); - if (entry->name == NULL) { - free(entry); - return NULL; - } + if (entry->name == NULL) + return mfree(entry); + if (value != NULL) { entry->value = strdup(value); if (entry->value == NULL) { free(entry->name); - free(entry); - return NULL; + return mfree(entry); } } @@ -193,8 +192,7 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char * if (entries == NULL) { free(entry->name); free(entry->value); - free(entry); - return NULL; + return mfree(entry); } list->entries = entries; list->entries_max += add; diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c index 1f9d16c450..a1f2b33ad5 100644 --- a/src/libudev/libudev-monitor.c +++ b/src/libudev/libudev-monitor.c @@ -207,8 +207,7 @@ struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const c udev_monitor->sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); if (udev_monitor->sock < 0) { log_debug_errno(errno, "error getting socket: %m"); - free(udev_monitor); - return NULL; + return mfree(udev_monitor); } } else { udev_monitor->bound = true; diff --git a/src/login/logind-button.c b/src/login/logind-button.c index baa6b7113c..90fb93bbaf 100644 --- a/src/login/logind-button.c +++ b/src/login/logind-button.c @@ -43,15 +43,12 @@ Button* button_new(Manager *m, const char *name) { return NULL; b->name = strdup(name); - if (!b->name) { - free(b); - return NULL; - } + if (!b->name) + return mfree(b); if (hashmap_put(m->buttons, b->name, b) < 0) { free(b->name); - free(b); - return NULL; + return mfree(b); } b->manager = m; diff --git a/src/login/logind-device.c b/src/login/logind-device.c index eb5edd1cd5..6537fa04bf 100644 --- a/src/login/logind-device.c +++ b/src/login/logind-device.c @@ -34,15 +34,12 @@ Device* device_new(Manager *m, const char *sysfs, bool master) { return NULL; d->sysfs = strdup(sysfs); - if (!d->sysfs) { - free(d); - return NULL; - } + if (!d->sysfs) + return mfree(d); if (hashmap_put(m->devices, d->sysfs, d) < 0) { free(d->sysfs); - free(d); - return NULL; + return mfree(d); } d->manager = m; diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c index 6c78e0dddc..c93b24009b 100644 --- a/src/login/logind-inhibit.c +++ b/src/login/logind-inhibit.c @@ -45,17 +45,14 @@ Inhibitor* inhibitor_new(Manager *m, const char* id) { return NULL; i->state_file = strappend("/run/systemd/inhibit/", id); - if (!i->state_file) { - free(i); - return NULL; - } + if (!i->state_file) + return mfree(i); i->id = basename(i->state_file); if (hashmap_put(m->inhibitors, i->id, i) < 0) { free(i->state_file); - free(i); - return NULL; + return mfree(i); } i->manager = m; diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index b5192320e4..ecc7bd2e5b 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -48,18 +48,15 @@ Seat *seat_new(Manager *m, const char *id) { return NULL; s->state_file = strappend("/run/systemd/seats/", id); - if (!s->state_file) { - free(s); - return NULL; - } + if (!s->state_file) + return mfree(s); s->id = basename(s->state_file); s->manager = m; if (hashmap_put(m->seats, s->id, s) < 0) { free(s->state_file); - free(s); - return NULL; + return mfree(s); } return s; diff --git a/src/login/logind-session.c b/src/login/logind-session.c index ba1bcc2630..cbf035f706 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -62,16 +62,13 @@ Session* session_new(Manager *m, const char *id) { return NULL; s->state_file = strappend("/run/systemd/sessions/", id); - if (!s->state_file) { - free(s); - return NULL; - } + if (!s->state_file) + return mfree(s); s->devices = hashmap_new(&devt_hash_ops); if (!s->devices) { free(s->state_file); - free(s); - return NULL; + return mfree(s); } s->id = basename(s->state_file); @@ -79,8 +76,7 @@ Session* session_new(Manager *m, const char *id) { if (hashmap_put(m->sessions, s->id, s) < 0) { hashmap_free(s->devices); free(s->state_file); - free(s); - return NULL; + return mfree(s); } s->manager = m; diff --git a/src/machine/machine.c b/src/machine/machine.c index dd046d6563..a02b9d7575 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -80,9 +80,7 @@ Machine* machine_new(Manager *manager, MachineClass class, const char *name) { fail: free(m->state_file); free(m->name); - free(m); - - return NULL; + return mfree(m); } void machine_free(Machine *m) { diff --git a/src/machine/operation.c b/src/machine/operation.c index 2bf93cb493..c966d0d21c 100644 --- a/src/machine/operation.c +++ b/src/machine/operation.c @@ -147,6 +147,5 @@ Operation *operation_free(Operation *o) { if (o->machine) LIST_REMOVE(operations_by_machine, o->machine->operations, o); - free(o); - return NULL; + return mfree(o); } diff --git a/src/network/networkd-wait-online-link.c b/src/network/networkd-wait-online-link.c index 5727422e3d..e63ba07e90 100644 --- a/src/network/networkd-wait-online-link.c +++ b/src/network/networkd-wait-online-link.c @@ -77,8 +77,7 @@ Link *link_free(Link *l) { } free(l->ifname); - free(l); - return NULL; + return mfree(l); } int link_update_rtnl(Link *l, sd_netlink_message *m) { diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c index 5f1522cfb6..09c8f070ba 100644 --- a/src/nspawn/nspawn-settings.c +++ b/src/nspawn/nspawn-settings.c @@ -101,9 +101,7 @@ Settings* settings_free(Settings *s) { expose_port_free_all(s->expose_ports); custom_mount_free_all(s->custom_mounts, s->n_custom_mounts); - free(s); - - return NULL; + return mfree(s); } bool settings_private_network(Settings *s) { diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index 53be18efc6..e03db4d003 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -83,9 +83,7 @@ DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) { if (c->scope) LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c); - free(c); - - return NULL; + return mfree(c); } static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) { @@ -421,9 +419,7 @@ DnsQuery *dns_query_free(DnsQuery *q) { q->manager->n_dns_queries--; } - free(q); - - return NULL; + return mfree(q); } int dns_query_new( diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index 5687588a7d..87e4abec6e 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -73,10 +73,8 @@ DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const D return dns_resource_key_ref((DnsResourceKey*) key); k = dns_resource_key_new_consume(key->class, key->type, destination); - if (!k) { - free(destination); - return NULL; - } + if (!k) + return mfree(destination); return k; } @@ -513,9 +511,7 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) { } free(rr->to_string); - free(rr); - - return NULL; + return mfree(rr); } int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) { diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 03811ac8e7..8dbc7f623b 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -128,9 +128,7 @@ DnsScope* dns_scope_free(DnsScope *s) { dns_zone_flush(&s->zone); LIST_REMOVE(scopes, s->manager->dns_scopes, s); - free(s); - - return NULL; + return mfree(s); } DnsServer *dns_scope_get_dns_server(DnsScope *s) { diff --git a/src/resolve/resolved-dns-search-domain.c b/src/resolve/resolved-dns-search-domain.c index 732471027b..1386e6a17b 100644 --- a/src/resolve/resolved-dns-search-domain.c +++ b/src/resolve/resolved-dns-search-domain.c @@ -104,9 +104,7 @@ DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d) { return NULL; free(d->name); - free(d); - - return NULL; + return mfree(d); } void dns_search_domain_unlink(DnsSearchDomain *d) { diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 97cc8c0e09..7282848e35 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -139,8 +139,7 @@ DnsServer* dns_server_unref(DnsServer *s) { return NULL; free(s->server_string); - free(s); - return NULL; + return mfree(s); } void dns_server_unlink(DnsServer *s) { diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c index dd0e0b90e3..878bae47dc 100644 --- a/src/resolve/resolved-dns-stream.c +++ b/src/resolve/resolved-dns-stream.c @@ -343,9 +343,7 @@ DnsStream *dns_stream_unref(DnsStream *s) { dns_packet_unref(s->write_packet); dns_packet_unref(s->read_packet); - free(s); - - return NULL; + return mfree(s); } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_unref); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index d455b6b1fa..2fce44ec8b 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -134,8 +134,7 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) { dns_answer_unref(t->validated_keys); dns_resource_key_unref(t->key); - free(t); - return NULL; + return mfree(t); } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free); diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index ea4a007139..13e1f91192 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -101,8 +101,7 @@ Link *link_free(Link *l) { free(l->state_file); - free(l); - return NULL; + return mfree(l); } void link_allocate_scopes(Link *l) { @@ -698,8 +697,7 @@ LinkAddress *link_address_free(LinkAddress *a) { dns_resource_record_unref(a->llmnr_address_rr); dns_resource_record_unref(a->llmnr_ptr_rr); - free(a); - return NULL; + return mfree(a); } void link_address_add_rrs(LinkAddress *a, bool force_remove) { diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 40f08e8044..0954641c20 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -630,9 +630,7 @@ Manager *manager_free(Manager *m) { dns_trust_anchor_flush(&m->trust_anchor); manager_etc_hosts_flush(m); - free(m); - - return NULL; + return mfree(m); } int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index 529d89ee2a..060f8d50c7 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -62,8 +62,7 @@ Image *image_unref(Image *i) { free(i->name); free(i->path); - free(i); - return NULL; + return mfree(i); } static char **image_settings_path(Image *image) { diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 24055e772b..293c6673fc 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -463,8 +463,7 @@ int pty_forward_new( PTYForward *pty_forward_free(PTYForward *f) { pty_forward_disconnect(f); - free(f); - return NULL; + return mfree(f); } int pty_forward_get_last_char(PTYForward *f, char *ch) { diff --git a/src/timesync/timesyncd-server.c b/src/timesync/timesyncd-server.c index 6bda86fe6e..57a7bf2c25 100644 --- a/src/timesync/timesyncd-server.c +++ b/src/timesync/timesyncd-server.c @@ -61,8 +61,7 @@ ServerAddress* server_address_free(ServerAddress *a) { manager_set_server_address(a->name->manager, NULL); } - free(a); - return NULL; + return mfree(a); } int server_name_new( @@ -137,9 +136,7 @@ ServerName *server_name_free(ServerName *n) { log_debug("Removed server %s.", n->string); free(n->string); - free(n); - - return NULL; + return mfree(n); } void server_name_flush_addresses(ServerName *n) { diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c index f68a09d7a8..7717ac7924 100644 --- a/src/udev/udev-ctrl.c +++ b/src/udev/udev-ctrl.c @@ -211,8 +211,7 @@ struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) { err: if (conn->sock >= 0) close(conn->sock); - free(conn); - return NULL; + return mfree(conn); } struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn) { diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 26fa52cf6c..7619c8371b 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -1583,8 +1583,7 @@ struct udev_rules *udev_rules_unref(struct udev_rules *rules) { strbuf_cleanup(rules->strbuf); free(rules->uids); free(rules->gids); - free(rules); - return NULL; + return mfree(rules); } bool udev_rules_check_timestamp(struct udev_rules *rules) { -- cgit v1.2.3-54-g00ecf From 75ead2b753cb9586f3f208326446081baab70da1 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 2 Nov 2016 22:03:27 -0400 Subject: sd-bus: use PRIu64 instead of casting --- src/libsystemd/sd-bus/bus-kernel.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index 59398b841d..ad468572f3 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -848,8 +848,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { if (k->src_id == KDBUS_SRC_ID_KERNEL) bus_message_set_sender_driver(bus, m); else { - xsprintf(m->sender_buffer, ":1.%llu", - (unsigned long long)k->src_id); + xsprintf(m->sender_buffer, ":1.%"PRIu64, k->src_id); m->sender = m->creds.unique_name = m->sender_buffer; } @@ -860,8 +859,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { else if (k->dst_id == KDBUS_DST_ID_NAME) m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */ else { - xsprintf(m->destination_buffer, ":1.%llu", - (unsigned long long)k->dst_id); + xsprintf(m->destination_buffer, ":1.%"PRIu64, k->dst_id); m->destination = m->destination_buffer; } -- cgit v1.2.3-54-g00ecf From a1e2ef7ec912902d8142e7cb5830cbfb47dba86c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 3 Nov 2016 13:16:42 -0400 Subject: Revert "sd-bus: use PRIu64 instead of casting" (#4556) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 75ead2b753cb9586f3f208326446081baab70da1. Follow up for #4546: > @@ -848,8 +848,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { if (k->src_id == KDBUS_SRC_ID_KERNEL) bus_message_set_sender_driver(bus, m); else { - xsprintf(m->sender_buffer, ":1.%llu", - (unsigned long long)k->src_id); + xsprintf(m->sender_buffer, ":1.%"PRIu64, k->src_id); This produces: src/libsystemd/sd-bus/bus-kernel.c: In function ‘bus_kernel_make_message’: src/libsystemd/sd-bus/bus-kernel.c:851:44: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 4 has type ‘__u64 {aka long long unsigned int}’ [-Wformat=] xsprintf(m->sender_buffer, ":1.%"PRIu64, k->src_id); ^ --- src/libsystemd/sd-bus/bus-kernel.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/libsystemd/sd-bus') diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index ad468572f3..59398b841d 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -848,7 +848,8 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { if (k->src_id == KDBUS_SRC_ID_KERNEL) bus_message_set_sender_driver(bus, m); else { - xsprintf(m->sender_buffer, ":1.%"PRIu64, k->src_id); + xsprintf(m->sender_buffer, ":1.%llu", + (unsigned long long)k->src_id); m->sender = m->creds.unique_name = m->sender_buffer; } @@ -859,7 +860,8 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { else if (k->dst_id == KDBUS_DST_ID_NAME) m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */ else { - xsprintf(m->destination_buffer, ":1.%"PRIu64, k->dst_id); + xsprintf(m->destination_buffer, ":1.%llu", + (unsigned long long)k->dst_id); m->destination = m->destination_buffer; } -- cgit v1.2.3-54-g00ecf