diff options
-rw-r--r-- | src/NetworkManagerUtils.c | 32 | ||||
-rw-r--r-- | src/NetworkManagerUtils.h | 34 | ||||
-rw-r--r-- | src/ppp/nm-ppp-manager.c | 4 | ||||
-rw-r--r-- | src/settings/nm-secret-agent.c | 2 | ||||
-rw-r--r-- | src/settings/nm-settings.c | 6 |
5 files changed, 66 insertions, 12 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index b928b8b3b4..19e51cf198 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -946,9 +946,10 @@ nm_ip_routing_rule_to_platform (const NMIPRoutingRule *rule, struct _NMShutdownWaitObjHandle { CList lst; - GObject *watched_obj; + gpointer watched_obj; char *msg_reason; bool free_msg_reason:1; + bool is_cancellable:1; }; static CList _shutdown_waitobj_lst_head; @@ -967,7 +968,7 @@ _shutdown_waitobj_unregister (NMShutdownWaitObjHandle *handle) static void _shutdown_waitobj_cb (gpointer user_data, - GObject *where_the_object_was) + GObject *where_the_object_was) { NMShutdownWaitObjHandle *handle = user_data; @@ -980,6 +981,8 @@ _shutdown_waitobj_cb (gpointer user_data, * nm_shutdown_wait_obj_register_full: * @watched_obj: the object to watch. Takes a weak reference on the object * to be notified when it gets destroyed. + * @wait_type: whether @watched_obj is just a plain GObject or a GCancellable + * that should be cancelled. * @msg_reason: a reason message, for debugging and logging purposes. * @free_msg_reason: if %TRUE, then ownership of @msg_reason will be taken * and the string will be freed with g_free() afterwards. If %FALSE, @@ -993,21 +996,41 @@ _shutdown_waitobj_cb (gpointer user_data, * the reference-counter of @watched_obj as signal, that the object * is still used. * + * If @wait_type is %NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE, then during shutdown + * (after %NM_SHUTDOWN_TIMEOUT_MS), the cancellable will be cancelled to notify + * the source of the shutdown. Note that otherwise, in this mode also @watched_obj + * is only tracked with a weak-pointer. Especially, it does not register to the + * "cancelled" signal to automatically unregister (otherwise, you would never + * know whether the returned NMShutdownWaitObjHandle is still valid. + * * FIXME(shutdown): proper shutdown is not yet implemented, and registering * an object (currently) has no effect. * + * FIXME(shutdown): during shutdown, after %NM_SHUTDOWN_TIMEOUT_MS timeout, cancel + * all remaining %NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE instances. Also, when somebody + * enqueues a cancellable after that point, cancel it right away on an idle handler. + * * Returns: a handle to unregister the object. The caller may choose to ignore * the handle, in which case, the object will be automatically unregistered, * once it gets destroyed. + * Note that the handle is only valid as long as @watched_obj exists. If + * you plan to use it, ensure that you take care of not using it after + * destroying @watched_obj. */ NMShutdownWaitObjHandle * -nm_shutdown_wait_obj_register_full (GObject *watched_obj, +nm_shutdown_wait_obj_register_full (gpointer watched_obj, + NMShutdownWaitType wait_type, char *msg_reason, gboolean free_msg_reason) { NMShutdownWaitObjHandle *handle; - g_return_val_if_fail (G_IS_OBJECT (watched_obj), NULL); + if (wait_type == NM_SHUTDOWN_WAIT_TYPE_OBJECT) + g_return_val_if_fail (G_IS_OBJECT (watched_obj), NULL); + else if (wait_type == NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE) + g_return_val_if_fail (G_IS_CANCELLABLE (watched_obj), NULL); + else + g_return_val_if_reached (NULL); if (G_UNLIKELY (!_shutdown_waitobj_lst_head.next)) c_list_init (&_shutdown_waitobj_lst_head); @@ -1020,6 +1043,7 @@ nm_shutdown_wait_obj_register_full (GObject *watched_obj, .watched_obj = watched_obj, .msg_reason = msg_reason, .free_msg_reason = free_msg_reason, + .is_cancellable = (wait_type == NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE), }; c_list_link_tail (&_shutdown_waitobj_lst_head, &handle->lst); g_object_weak_ref (watched_obj, _shutdown_waitobj_cb, handle); diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index e957b95e29..72be1c4cf6 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -74,13 +74,43 @@ NMPlatformRoutingRule *nm_ip_routing_rule_to_platform (const NMIPRoutingRule *ru #define NM_SHUTDOWN_TIMEOUT_MS 1500 #define NM_SHUTDOWN_TIMEOUT_MS_WATCHDOG 500 +typedef enum { + /* The watched_obj argument is a GObject, and shutdown is delayed until the object + * gets destroyed (or unregistered). */ + NM_SHUTDOWN_WAIT_TYPE_OBJECT, + + /* The watched_obj argument is a GCancellable, and shutdown is delayed until the object + * gets destroyed (or unregistered). Note that after NM_SHUTDOWN_TIMEOUT_MS, the + * cancellable will be cancelled to notify listeners about the shutdown. */ + NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE, +} NMShutdownWaitType; + typedef struct _NMShutdownWaitObjHandle NMShutdownWaitObjHandle; -NMShutdownWaitObjHandle *nm_shutdown_wait_obj_register_full (GObject *watched_obj, +NMShutdownWaitObjHandle *nm_shutdown_wait_obj_register_full (gpointer watched_obj, + NMShutdownWaitType wait_type, char *msg_reason, gboolean free_msg_reason); -#define nm_shutdown_wait_obj_register(watched_obj, msg_reason) nm_shutdown_wait_obj_register_full((watched_obj), (""msg_reason""), FALSE) +static inline NMShutdownWaitObjHandle * +nm_shutdown_wait_obj_register_object_full (gpointer watched_obj, + char *msg_reason, + gboolean free_msg_reason) +{ + return nm_shutdown_wait_obj_register_full (watched_obj, NM_SHUTDOWN_WAIT_TYPE_OBJECT, msg_reason, free_msg_reason); +} + +#define nm_shutdown_wait_obj_register_object(watched_obj, msg_reason) nm_shutdown_wait_obj_register_object_full((watched_obj), (""msg_reason""), FALSE) + +static inline NMShutdownWaitObjHandle * +nm_shutdown_wait_obj_register_cancellable_full (GCancellable *watched_obj, + char *msg_reason, + gboolean free_msg_reason) +{ + return nm_shutdown_wait_obj_register_full (watched_obj, NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE, msg_reason, free_msg_reason); +} + +#define nm_shutdown_wait_obj_register_cancellable(watched_obj, msg_reason) nm_shutdown_wait_obj_register_cancellable_full((watched_obj), (""msg_reason""), FALSE) void nm_shutdown_wait_obj_unregister (NMShutdownWaitObjHandle *handle); diff --git a/src/ppp/nm-ppp-manager.c b/src/ppp/nm-ppp-manager.c index ff22dbbed2..c294942286 100644 --- a/src/ppp/nm-ppp-manager.c +++ b/src/ppp/nm-ppp-manager.c @@ -1213,7 +1213,7 @@ _ppp_manager_stop (NMPPPManager *self, /* No PID. There is nothing to kill, however, invoke the callback in * an idle handler. * - * Note that we don't register nm_shutdown_wait_obj_register(). + * Note that we don't register nm_shutdown_wait_obj_register_object(). * In order for shutdown to work properly, the caller must always * explicitly cancel the action to go down. With the idle-handler, * cancelling the handle completes the request. */ @@ -1225,7 +1225,7 @@ _ppp_manager_stop (NMPPPManager *self, * until the process terminated. We do that, by registering an object * that delays shutdown. */ handle->shutdown_waitobj = g_object_new (G_TYPE_OBJECT, NULL); - nm_shutdown_wait_obj_register (handle->shutdown_waitobj, "ppp-manager-wait-kill-pppd"); + nm_shutdown_wait_obj_register_object (handle->shutdown_waitobj, "ppp-manager-wait-kill-pppd"); nm_utils_kill_child_async (nm_steal_int (&priv->pid), SIGTERM, LOGD_PPP, "pppd", NM_SHUTDOWN_TIMEOUT_MS, diff --git a/src/settings/nm-secret-agent.c b/src/settings/nm-secret-agent.c index 1831d89bbb..88e6a77b6e 100644 --- a/src/settings/nm-secret-agent.c +++ b/src/settings/nm-secret-agent.c @@ -160,7 +160,7 @@ _call_id_new (NMSecretAgent *self, /* self has async requests (that keep self alive). As long as * we have pending requests, shutdown is blocked. */ priv->shutdown_wait_obj_registered = TRUE; - nm_shutdown_wait_obj_register (G_OBJECT (self), "secret-agent"); + nm_shutdown_wait_obj_register_object (G_OBJECT (self), "secret-agent"); } return call_id; diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index adb6636a43..f474324c20 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -3116,9 +3116,9 @@ add_plugin (NMSettings *self, priv->plugins = g_slist_append (priv->plugins, g_object_ref (plugin)); - nm_shutdown_wait_obj_register_full (G_OBJECT (plugin), - g_strdup_printf ("%s-settings-plugin", pname), - TRUE); + nm_shutdown_wait_obj_register_object_full (plugin, + g_strdup_printf ("%s-settings-plugin", pname), + TRUE); _LOGI ("Loaded settings plugin: %s (%s%s%s)", pname, |