summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2015-01-16 19:00:31 +0100
committerDan Williams <dcbw@redhat.com>2015-02-24 16:15:26 -0600
commitaea6183041bd18c6926d25da967aacffcbd94001 (patch)
treea29594c6e7209d9c97a78fd386bd1ee15d1a1303
parent0eb765213903dff7ef14de8c75f1ada672d7485b (diff)
downloadNetworkManager-aea6183041bd18c6926d25da967aacffcbd94001.tar.gz
ppp-manager: new async stop() method to request stop and wait for it to complete
This method doesn't prevent the original logic in which the child process was stopped when the last reference of the PPP manager was unref-ed. (cherry picked from commit 14f732e8df6a5bfbc36d0e0adaec175d7da6f231)
-rw-r--r--src/ppp-manager/nm-ppp-manager.c111
-rw-r--r--src/ppp-manager/nm-ppp-manager.h8
2 files changed, 116 insertions, 3 deletions
diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c
index 4fac96dcd2..65993deb2a 100644
--- a/src/ppp-manager/nm-ppp-manager.c
+++ b/src/ppp-manager/nm-ppp-manager.c
@@ -68,6 +68,7 @@ static gboolean impl_ppp_manager_set_ip6_config (NMPPPManager *manager,
#include "nm-ppp-manager-glue.h"
static void _ppp_cleanup (NMPPPManager *manager);
+static void _ppp_kill (NMPPPManager *manager);
#define NM_PPPD_PLUGIN PPPD_PLUGIN_DIR "/nm-pppd-plugin.so"
#define PPP_MANAGER_SECRET_TRIES "ppp-manager-secret-tries"
@@ -139,6 +140,7 @@ dispose (GObject *object)
NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (object);
_ppp_cleanup (NM_PPP_MANAGER (object));
+ _ppp_kill (NM_PPP_MANAGER (object));
g_clear_object (&priv->act_req);
@@ -836,6 +838,7 @@ pppd_timed_out (gpointer data)
nm_log_warn (LOGD_PPP, "pppd timed out or didn't initialize our dbus module");
_ppp_cleanup (manager);
+ _ppp_kill (manager);
g_signal_emit (manager, signals[STATE_CHANGED], 0, NM_PPP_STATUS_DEAD);
@@ -1160,6 +1163,21 @@ out:
}
static void
+_ppp_kill (NMPPPManager *manager)
+{
+ NMPPPManagerPrivate *priv;
+
+ g_return_if_fail (NM_IS_PPP_MANAGER (manager));
+
+ priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+
+ if (priv->pid) {
+ nm_utils_kill_child_async (priv->pid, SIGTERM, LOGD_PPP, "pppd", 2000, NULL, NULL);
+ priv->pid = 0;
+ }
+}
+
+static void
_ppp_cleanup (NMPPPManager *manager)
{
NMPPPManagerPrivate *priv;
@@ -1191,9 +1209,96 @@ _ppp_cleanup (NMPPPManager *manager)
g_source_remove (priv->ppp_watch_id);
priv->ppp_watch_id = 0;
}
+}
- if (priv->pid) {
- nm_utils_kill_child_async (priv->pid, SIGTERM, LOGD_PPP, "pppd", 2000, NULL, NULL);
- priv->pid = 0;
+/***********************************************************/
+
+typedef struct {
+ NMPPPManager *manager;
+ GSimpleAsyncResult *result;
+ GCancellable *cancellable;
+} StopContext;
+
+static void
+stop_context_complete (StopContext *ctx)
+{
+ if (ctx->cancellable)
+ g_object_unref (ctx->cancellable);
+ g_simple_async_result_complete_in_idle (ctx->result);
+ g_object_unref (ctx->result);
+ g_object_unref (ctx->manager);
+ g_slice_free (StopContext, ctx);
+}
+
+static gboolean
+stop_context_complete_if_cancelled (StopContext *ctx)
+{
+ GError *error = NULL;
+
+ if (g_cancellable_set_error_if_cancelled (ctx->cancellable, &error)) {
+ g_simple_async_result_take_error (ctx->result, error);
+ stop_context_complete (ctx);
+ return TRUE;
}
+ return FALSE;
+}
+
+gboolean
+nm_ppp_manager_stop_finish (NMPPPManager *manager,
+ GAsyncResult *res,
+ GError **error)
+{
+ return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+}
+
+static void
+kill_child_ready (pid_t pid,
+ gboolean success,
+ int child_status,
+ StopContext *ctx)
+{
+ if (stop_context_complete_if_cancelled (ctx))
+ return;
+ stop_context_complete (ctx);
+}
+
+void
+nm_ppp_manager_stop (NMPPPManager *manager,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
+ StopContext *ctx;
+
+ ctx = g_slice_new0 (StopContext);
+ ctx->manager = g_object_ref (manager);
+ ctx->result = g_simple_async_result_new (G_OBJECT (manager),
+ callback,
+ user_data,
+ nm_ppp_manager_stop);
+
+ /* Setup cancellable */
+ ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+ if (stop_context_complete_if_cancelled (ctx))
+ return;
+
+ /* Cleanup internals */
+ _ppp_cleanup (manager);
+
+ /* If no pppd running, we're done */
+ if (!priv->pid) {
+ stop_context_complete (ctx);
+ return;
+ }
+
+ /* No cancellable operation, so just wait until it returns always */
+ nm_utils_kill_child_async (priv->pid,
+ SIGTERM,
+ LOGD_PPP,
+ "pppd",
+ 2000,
+ (NMUtilsKillChildAsyncCb) kill_child_ready,
+ ctx);
+ priv->pid = 0;
}
diff --git a/src/ppp-manager/nm-ppp-manager.h b/src/ppp-manager/nm-ppp-manager.h
index 84be76d044..f8cbda1365 100644
--- a/src/ppp-manager/nm-ppp-manager.h
+++ b/src/ppp-manager/nm-ppp-manager.h
@@ -24,6 +24,7 @@
#include <glib.h>
#include <glib-object.h>
+#include <gio/gio.h>
#include "nm-ppp-status.h"
#include "nm-activation-request.h"
@@ -69,5 +70,12 @@ gboolean nm_ppp_manager_start (NMPPPManager *manager,
guint32 timeout_secs,
GError **err);
+void nm_ppp_manager_stop (NMPPPManager *manager,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean nm_ppp_manager_stop_finish (NMPPPManager *manager,
+ GAsyncResult *res,
+ GError **error);
#endif /* __NETWORKMANAGER_PPP_MANAGER_H__ */