From 225553f93e1e1dfa10114f3b5dc7cbd187ea64bd Mon Sep 17 00:00:00 2001 From: Dafydd Harries Date: Fri, 30 Mar 2018 10:57:18 -0400 Subject: [PATCH] fix timeout path for starting ssh-agent Previously, GkdSsshAgentProcess would busy-loop waiting for the agent to time out. If the agent never produced any output, it would busy-loop forever. (This seems like it was because it would call g_main_context_iterate with may_block=FALSE, preventing the timeout source from firing.) Instead, have GkdSsshAgentProcess create a GMainLoop that's run until the agent starts or a timeout is reached. --- daemon/ssh-agent/gkd-ssh-agent-process.c | 38 +++++++++++++++++++++++++------- daemon/ssh-agent/gkd-ssh-agent-service.c | 5 ++++- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/daemon/ssh-agent/gkd-ssh-agent-process.c b/daemon/ssh-agent/gkd-ssh-agent-process.c index d3bb3a7e..edf97630 100644 --- a/daemon/ssh-agent/gkd-ssh-agent-process.c +++ b/daemon/ssh-agent/gkd-ssh-agent-process.c @@ -53,6 +53,7 @@ struct _GkdSshAgentProcess guint output_id; guint child_id; gboolean ready; + GMainLoop *ready_loop; }; G_DEFINE_TYPE (GkdSshAgentProcess, gkd_ssh_agent_process, G_TYPE_OBJECT); @@ -160,6 +161,10 @@ on_output_watch (gint fd, if (condition & G_IO_IN) { self->ready = TRUE; + if (self->ready_loop) { + g_main_loop_quit (self->ready_loop); + } + len = read (fd, buf, sizeof (buf)); if (len < 0) { if (errno != EAGAIN && errno != EINTR) @@ -179,6 +184,7 @@ agent_start_inlock (GkdSshAgentProcess *self, GError **error) { const gchar *argv[] = { SSH_AGENT, "-D", "-a", self->path, NULL }; + GPid pid; if (!g_spawn_async_with_pipes ("/", (gchar **)argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, @@ -199,19 +205,38 @@ agent_start_inlock (GkdSshAgentProcess *self, static gboolean on_timeout (gpointer user_data) { - gboolean *timedout = user_data; - *timedout = TRUE; + GkdSshAgentProcess *self = user_data; + + if (self->ready_loop) { + g_main_loop_quit (self->ready_loop); + } + return TRUE; } +static void +wait_for_agent (GkdSshAgentProcess *self) +{ + guint source; + + if (self->ready_loop) { + g_main_loop_run (self->ready_loop); + } else { + self->ready_loop = g_main_loop_new (NULL, FALSE); + source = g_timeout_add_seconds (3, on_timeout, self); + g_main_loop_run (self->ready_loop); + g_source_remove (source); + g_main_loop_unref (self->ready_loop); + self->ready_loop = NULL; + } +} + GSocketConnection * gkd_ssh_agent_process_connect (GkdSshAgentProcess *self, GCancellable *cancellable, GError **error) { gboolean started = FALSE; - gboolean timedout = FALSE; - guint source; GSocketClient *client; GSocketAddress *address; GSocketConnection *connection; @@ -227,10 +252,7 @@ gkd_ssh_agent_process_connect (GkdSshAgentProcess *self, } if (started && !self->ready) { - source = g_timeout_add_seconds (5, on_timeout, &timedout); - while (!self->ready && !timedout) - g_main_context_iteration (NULL, FALSE); - g_source_remove (source); + wait_for_agent (self); } if (!self->ready) { diff --git a/daemon/ssh-agent/gkd-ssh-agent-service.c b/daemon/ssh-agent/gkd-ssh-agent-service.c index a9f74ab3..1ebbe381 100644 --- a/daemon/ssh-agent/gkd-ssh-agent-service.c +++ b/daemon/ssh-agent/gkd-ssh-agent-service.c @@ -348,7 +348,10 @@ on_run (GThreadedSocketService *service, egg_buffer_uninit (&req); egg_buffer_uninit (&resp); - g_object_unref (agent_connection); + if (agent_connection) { + g_object_unref (agent_connection); + } + g_object_unref (self); return TRUE; -- 2.16.3