diff options
author | Thomas Haller <thaller@redhat.com> | 2021-08-04 11:33:46 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2021-08-06 14:32:55 +0200 |
commit | 412b5b4fa78fd788f539c8e304faccc82d3d83a2 (patch) | |
tree | 7794ba033c5e4a0d4372dc0fdbba8c9ed951829e | |
parent | 9f0984c63b4279cb50818e7545fa45a5c7f991ce (diff) | |
download | NetworkManager-412b5b4fa78fd788f539c8e304faccc82d3d83a2.tar.gz |
dispatcher: reject new requests after releasing name
After we released the well-known name (or if we failed to ever request
it), we must exit as fast as possible, so that a new instance can
be started to serve new requests.
At that point, reject new requests because they are targeted against the
unique name, which they should not do (when talking to a D-Bus activated
service that exits on idle, it's important to talk to the well-known
name).
Also, if we receive SIGTERM, start releasing the name. We are told to
shut down, and must do so in a timely manner. Again, new requests shall
not be served by this instance.
-rw-r--r-- | src/nm-dispatcher/nm-dispatcher.c | 100 |
1 files changed, 63 insertions, 37 deletions
diff --git a/src/nm-dispatcher/nm-dispatcher.c b/src/nm-dispatcher/nm-dispatcher.c index b96cc82ea9..dba726e4e0 100644 --- a/src/nm-dispatcher/nm-dispatcher.c +++ b/src/nm-dispatcher/nm-dispatcher.c @@ -47,6 +47,8 @@ static struct { bool name_requested; + bool reject_new_requests; + bool exit_with_failure; bool shutdown_timeout; @@ -886,6 +888,13 @@ _method_call(GDBusConnection * connection, GDBusMethodInvocation *invocation, gpointer user_data) { + if (gl.reject_new_requests) { + g_dbus_method_invocation_return_error(invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_NO_SERVER, + "Server is exiting"); + return; + } if (nm_streq(interface_name, NM_DISPATCHER_DBUS_INTERFACE)) { if (nm_streq(method_name, "Action")) { _method_call_action(invocation, parameters); @@ -1060,15 +1069,61 @@ signal_handler(gpointer user_data) return G_SOURCE_CONTINUE; } +/*****************************************************************************/ + static void _bus_release_name_cb(GObject *source, GAsyncResult *result, gpointer user_data) { nm_assert(gl.num_requests_pending > 0); + gl.reject_new_requests = TRUE; gl.num_requests_pending--; g_main_context_wakeup(NULL); } static gboolean +_bus_release_name(void) +{ + int r; + + /* We already requested a name. To exit-on-idle without race, we need to dance. + * See https://lists.freedesktop.org/archives/dbus/2015-May/016671.html . */ + + if (!gl.name_requested) + return FALSE; + + gl.name_requested = FALSE; + gl.shutdown_quitting = TRUE; + + _LOG_X_T("shutdown: release-name"); + + /* we create a fake pending request. */ + gl.num_requests_pending++; + nm_clear_g_source_inst(&gl.quit_source); + + r = nm_sd_notify("STOPPING=1"); + if (r < 0) + _LOG_X_W("shutdown: sd_notifiy(STOPPING=1) failed: %s", nm_strerror_native(-r)); + else + _LOG_X_T("shutdown: sd_notifiy(STOPPING=1) succeeded"); + + g_dbus_connection_call(gl.dbus_connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "ReleaseName", + g_variant_new("(s)", NM_DISPATCHER_DBUS_SERVICE), + G_VARIANT_TYPE("(u)"), + G_DBUS_CALL_FLAGS_NONE, + 10000, + NULL, + _bus_release_name_cb, + NULL); + return TRUE; +} + +/*****************************************************************************/ + +static gboolean parse_command_line(int *p_argc, char ***p_argv, GError **error) { GOptionContext *opt_ctx; @@ -1173,49 +1228,20 @@ main(int argc, char **argv) if (!g_cancellable_is_cancelled(gl.quit_cancellable)) gl.exit_with_failure = TRUE; gl.shutdown_quitting = TRUE; + + if (!gl.name_requested) + gl.reject_new_requests = TRUE; } while (TRUE) { + if (gl.shutdown_quitting) + _bus_release_name(); + if (gl.num_requests_pending > 0) { /* while we have requests pending, we cannot stop processing them... */ } else if (gl.shutdown_timeout || gl.shutdown_quitting) { - if (gl.name_requested) { - int r; - - /* We already requested a name. To exit-on-idle without race, we need to dance. - * See https://lists.freedesktop.org/archives/dbus/2015-May/016671.html . */ - - gl.name_requested = FALSE; - gl.shutdown_quitting = TRUE; - - _LOG_X_T("shutdown: release-name"); - - /* we create a fake pending request. */ - gl.num_requests_pending++; - nm_clear_g_source_inst(&gl.quit_source); - - r = nm_sd_notify("STOPPING=1"); - if (r < 0) - _LOG_X_W("shutdown: sd_notifiy(STOPPING=1) failed: %s", nm_strerror_native(-r)); - else - _LOG_X_T("shutdown: sd_notifiy(STOPPING=1) succeeded"); - - g_dbus_connection_call(gl.dbus_connection, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS, - "ReleaseName", - g_variant_new("(s)", NM_DISPATCHER_DBUS_SERVICE), - G_VARIANT_TYPE("(u)"), - G_DBUS_CALL_FLAGS_NONE, - 10000, - NULL, - _bus_release_name_cb, - NULL); - continue; - } - - break; + if (!_bus_release_name()) + break; } g_main_context_iteration(NULL, TRUE); |