summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/NetworkManagerUtils.c32
-rw-r--r--src/NetworkManagerUtils.h34
-rw-r--r--src/ppp/nm-ppp-manager.c4
-rw-r--r--src/settings/nm-secret-agent.c2
-rw-r--r--src/settings/nm-settings.c6
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,