diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2016-06-16 16:37:20 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2016-06-21 10:18:16 +0200 |
commit | 0189a973fac5a97b13ff83b0f8a1d5044faee82c (patch) | |
tree | 94f3104b206a60f4921f9875bb3f7dc2d63dea42 | |
parent | 170905e720919bde662015d24b3e70ff46e20290 (diff) | |
download | network-manager-applet-0189a973fac5a97b13ff83b0f8a1d5044faee82c.tar.gz |
vpn-request: don't kill the auth-dialog upon request destroy
When the secrets request is destroyed, we unreferenced the
AppletVpnRequest object and also killed any pending authentication
dialog.
Instead, send a CANCEL message to the dialog to notify it about the
cancellation of the request and wait for its termination before
destroying the AppletVpnRequest.
-rw-r--r-- | src/applet-vpn-request.c | 70 |
1 files changed, 46 insertions, 24 deletions
diff --git a/src/applet-vpn-request.c b/src/applet-vpn-request.c index 69f72a7e..292eb38a 100644 --- a/src/applet-vpn-request.c +++ b/src/applet-vpn-request.c @@ -41,6 +41,9 @@ #define APPLET_IS_VPN_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), APPLET_TYPE_VPN_REQUEST)) #define APPLET_VPN_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), APPLET_TYPE_VPN_REQUEST, AppletVpnRequestClass)) +#define MSG_QUIT "QUIT\n\n" +#define MSG_CANCEL "CANCEL %u %s\n\n" + typedef struct { GObject parent; } AppletVpnRequest; @@ -132,6 +135,7 @@ child_finished_cb (GPid pid, gint status, gpointer user_data) if (settings) g_variant_unref (settings); g_clear_error (&error); + g_object_unref (self); } static gboolean @@ -140,7 +144,6 @@ child_stdout_data_cb (GIOChannel *source, GIOCondition condition, gpointer user_ VpnSecretsInfo *info = user_data; AppletVpnRequest *self = info->vpn; AppletVpnRequestPrivate *priv = APPLET_VPN_REQUEST_GET_PRIVATE (self); - const char *buf = "QUIT\n\n"; char *str; int len; @@ -155,7 +158,7 @@ child_stdout_data_cb (GIOChannel *source, GIOCondition condition, gpointer user_ /* on second line with a newline newline */ if (++priv->num_newlines == 2) { /* terminate the child */ - if (write (priv->child_stdin, buf, strlen (buf)) == -1) + if (write (priv->child_stdin, MSG_QUIT, NM_STRLEN (MSG_QUIT)) == -1) return TRUE; } } else if (len > 0) { @@ -191,14 +194,52 @@ find_auth_dialog_binary (const char *service, *out_hints_supported = nm_vpn_plugin_info_supports_hints (plugin); return g_strdup (auth_dialog); } +static const char * +cancel_reason_to_str (NMSecretAgentCancelReason reason) +{ + switch (reason) { + case NM_SECRET_AGENT_CANCEL_REASON_CANCELED: + return _("the request was canceled"); + case NM_SECRET_AGENT_CANCEL_REASON_TIMED_OUT: + return _("timeout reached"); + case NM_SECRET_AGENT_CANCEL_REASON_UNKNOWN: + default: + return _("reason unknown"); + } +} + +static void +child_finished_cb2 (GPid pid, gint status, gpointer user_data) +{ + g_object_unref (user_data); +} static void free_vpn_secrets_info (SecretsRequest *req) { VpnSecretsInfo *info = (VpnSecretsInfo *) req; + gs_free char *msg_free = NULL; + char *msg; + + if (info->vpn) { + AppletVpnRequestPrivate *priv = APPLET_VPN_REQUEST_GET_PRIVATE (info->vpn); + + nm_clear_g_source (&priv->watch_id); + + if (priv->pid) { + if (req->canceled) { + msg_free = msg = g_strdup_printf (MSG_CANCEL, + req->cancel_reason, + cancel_reason_to_str (req->cancel_reason)); + } else + msg = MSG_QUIT; + + write (priv->child_stdin, msg, strlen (msg)); + priv->watch_id = g_child_watch_add (priv->pid, child_finished_cb2, info->vpn); + } - if (info->vpn) g_object_unref (info->vpn); + } } size_t @@ -381,6 +422,7 @@ applet_vpn_request_get_secrets (SecretsRequest *req, GError **error) /* catch when child is reaped */ priv->watch_id = g_child_watch_add (priv->pid, child_finished_cb, info); + g_object_ref (info->vpn); /* listen to what child has to say */ priv->channel = g_io_channel_unix_new (priv->child_stdout); @@ -401,18 +443,6 @@ applet_vpn_request_init (AppletVpnRequest *self) { } -static gboolean -ensure_killed (gpointer data) -{ - pid_t pid = GPOINTER_TO_INT (data); - - if (kill (pid, 0) == 0) - kill (pid, SIGKILL); - /* ensure the child is reaped */ - waitpid (pid, NULL, 0); - return FALSE; -} - static void dispose (GObject *object) { @@ -436,16 +466,8 @@ dispose (GObject *object) if (priv->channel) g_io_channel_unref (priv->channel); - if (priv->pid) { + if (priv->pid) g_spawn_close_pid (priv->pid); - if (kill (priv->pid, SIGTERM) == 0) - g_timeout_add_seconds (2, ensure_killed, GINT_TO_POINTER (priv->pid)); - else { - kill (priv->pid, SIGKILL); - /* ensure the child is reaped */ - waitpid (priv->pid, NULL, 0); - } - } g_slist_foreach (priv->lines, (GFunc) g_free, NULL); g_slist_free (priv->lines); |