diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/dbus-manager.c | 5 | ||||
-rw-r--r-- | src/core/dbus.c | 66 | ||||
-rw-r--r-- | src/core/dbus.h | 2 | ||||
-rw-r--r-- | src/core/manager.c | 13 | ||||
-rw-r--r-- | src/core/service.c | 14 | ||||
-rw-r--r-- | src/core/service.h | 1 | ||||
-rw-r--r-- | src/core/socket.c | 12 |
7 files changed, 92 insertions, 21 deletions
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 61bd0f8d5f..8a523cc8ac 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -229,7 +229,10 @@ static int property_set_log_level( if (r < 0) return r; - return log_set_max_level_from_string(t); + r = log_set_max_level_from_string(t); + if (r == 0) + log_info("Setting log level to %s.", t); + return r; } static int property_get_n_names( diff --git a/src/core/dbus.c b/src/core/dbus.c index e7ee216f0e..1d89b9e250 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -734,9 +734,11 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void return 0; } -static int bus_list_names(Manager *m, sd_bus *bus) { +int manager_sync_bus_names(Manager *m, sd_bus *bus) { _cleanup_strv_free_ char **names = NULL; - char **i; + const char *name; + Iterator i; + Unit *u; int r; assert(m); @@ -746,15 +748,55 @@ static int bus_list_names(Manager *m, sd_bus *bus) { if (r < 0) return log_error_errno(r, "Failed to get initial list of names: %m"); - /* This is a bit hacky, we say the owner of the name is the - * name itself, because we don't want the extra traffic to - * figure out the real owner. */ - STRV_FOREACH(i, names) { - Unit *u; + /* We have to synchronize the current bus names with the + * list of active services. To do this, walk the list of + * all units with bus names. */ + HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) { + Service *s = SERVICE(u); + + assert(s); - u = hashmap_get(m->watch_bus, *i); - if (u) - UNIT_VTABLE(u)->bus_name_owner_change(u, *i, NULL, *i); + if (!streq_ptr(s->bus_name, name)) { + log_unit_warning(u, "Bus name has changed from %s → %s, ignoring.", s->bus_name, name); + continue; + } + + /* Check if a service's bus name is in the list of currently + * active names */ + if (strv_contains(names, name)) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + const char *unique; + + /* If it is, determine its current owner */ + r = sd_bus_get_name_creds(bus, name, SD_BUS_CREDS_UNIQUE_NAME, &creds); + if (r < 0) { + log_error_errno(r, "Failed to get bus name owner %s: %m", name); + continue; + } + + r = sd_bus_creds_get_unique_name(creds, &unique); + if (r < 0) { + log_error_errno(r, "Failed to get unique name for %s: %m", name); + continue; + } + + /* Now, let's compare that to the previous bus owner, and + * if it's still the same, all is fine, so just don't + * bother the service. Otherwise, the name has apparently + * changed, so synthesize a name owner changed signal. */ + + if (!streq_ptr(unique, s->bus_name_owner)) + UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, unique); + } else { + /* So, the name we're watching is not on the bus. + * This either means it simply hasn't appeared yet, + * or it was lost during the daemon reload. + * Check if the service has a stored name owner, + * and synthesize a name loss signal in this case. */ + + if (s->bus_name_owner) + UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, NULL); + } } return 0; @@ -808,7 +850,9 @@ static int bus_setup_api(Manager *m, sd_bus *bus) { if (r < 0) return log_error_errno(r, "Failed to register name: %m"); - bus_list_names(m, bus); + r = manager_sync_bus_names(m, bus); + if (r < 0) + return r; log_debug("Successfully connected to API bus."); return 0; diff --git a/src/core/dbus.h b/src/core/dbus.h index 4f06ad11c4..ff761668f3 100644 --- a/src/core/dbus.h +++ b/src/core/dbus.h @@ -34,6 +34,8 @@ 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); +int manager_sync_bus_names(Manager *m, sd_bus *bus); + int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata); int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error); diff --git a/src/core/manager.c b/src/core/manager.c index 34dd715e93..ffe27be743 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1885,23 +1885,21 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t switch (sfsi.ssi_signo - SIGRTMIN) { case 20: - log_debug("Enabling showing of status."); manager_set_show_status(m, SHOW_STATUS_YES); break; case 21: - log_debug("Disabling showing of status."); manager_set_show_status(m, SHOW_STATUS_NO); break; case 22: log_set_max_level(LOG_DEBUG); - log_notice("Setting log level to debug."); + log_info("Setting log level to debug."); break; case 23: log_set_max_level(LOG_INFO); - log_notice("Setting log level to info."); + log_info("Setting log level to info."); break; case 24: @@ -2576,6 +2574,10 @@ int manager_reload(Manager *m) { /* Third, fire things up! */ manager_coldplug(m); + /* Sync current state of bus names with our set of listening units */ + if (m->api_bus) + manager_sync_bus_names(m, m->api_bus); + assert(m->n_reloading > 0); m->n_reloading--; @@ -2961,6 +2963,9 @@ void manager_set_show_status(Manager *m, ShowStatus mode) { if (m->running_as != MANAGER_SYSTEM) return; + if (m->show_status != mode) + log_debug("%s showing of status.", + mode == SHOW_STATUS_NO ? "Disabling" : "Enabling"); m->show_status = mode; if (mode > 0) diff --git a/src/core/service.c b/src/core/service.c index 41a729c421..c5b689a35c 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -323,6 +323,8 @@ static void service_done(Unit *u) { s->bus_name = mfree(s->bus_name); } + s->bus_name_owner = mfree(s->bus_name_owner); + s->bus_endpoint_fd = safe_close(s->bus_endpoint_fd); service_close_socket_fd(s); service_connection_unref(s); @@ -2122,6 +2124,7 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) { unit_serialize_item(u, f, "main-pid-known", yes_no(s->main_pid_known)); unit_serialize_item(u, f, "bus-name-good", yes_no(s->bus_name_good)); + unit_serialize_item(u, f, "bus-name-owner", s->bus_name_owner); r = unit_serialize_item_escaped(u, f, "status-text", s->status_text); if (r < 0) @@ -2249,6 +2252,10 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value, log_unit_debug(u, "Failed to parse bus-name-good value: %s", value); else s->bus_name_good = b; + } else if (streq(key, "bus-name-owner")) { + r = free_and_strdup(&s->bus_name_owner, value); + if (r < 0) + log_unit_error_errno(u, r, "Unable to deserialize current bus owner %s: %m", value); } else if (streq(key, "status-text")) { char *t; @@ -3134,6 +3141,13 @@ static void service_bus_name_owner_change( s->bus_name_good = !!new_owner; + /* Track the current owner, so we can reconstruct changes after a daemon reload */ + r = free_and_strdup(&s->bus_name_owner, new_owner); + if (r < 0) { + log_unit_error_errno(u, r, "Unable to set new bus name owner %s: %m", new_owner); + return; + } + if (s->type == SERVICE_DBUS) { /* service_enter_running() will figure out what to diff --git a/src/core/service.h b/src/core/service.h index d0faad88e0..19efbccfc7 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -172,6 +172,7 @@ struct Service { bool reset_cpu_usage:1; char *bus_name; + char *bus_name_owner; /* unique name of the current owner */ char *status_text; int status_errno; diff --git a/src/core/socket.c b/src/core/socket.c index 7beec3644e..d6b0c963e8 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -156,14 +156,16 @@ static void socket_done(Unit *u) { s->tcp_congestion = mfree(s->tcp_congestion); s->bind_to_device = mfree(s->bind_to_device); - free(s->smack); - free(s->smack_ip_in); - free(s->smack_ip_out); + s->smack = mfree(s->smack); + s->smack_ip_in = mfree(s->smack_ip_in); + s->smack_ip_out = mfree(s->smack_ip_out); strv_free(s->symlinks); - free(s->user); - free(s->group); + s->user = mfree(s->user); + s->group = mfree(s->group); + + s->fdname = mfree(s->fdname); s->timer_event_source = sd_event_source_unref(s->timer_event_source); } |