|
|
7bcd4f |
From 7650ad1e08ab13bdb461783c4995d186d9392840 Mon Sep 17 00:00:00 2001
|
|
|
7bcd4f |
From: Rui Matos <tiagomatos@gmail.com>
|
|
|
7bcd4f |
Date: Thu, 6 Feb 2014 18:41:18 +0100
|
|
|
7bcd4f |
Subject: [PATCH] PolkitAgentSession: fix race between child and io watches
|
|
|
7bcd4f |
|
|
|
7bcd4f |
The helper flushes and fdatasyncs stdout and stderr before terminating
|
|
|
7bcd4f |
but this doesn't guarantee that our io watch is called before our
|
|
|
7bcd4f |
child watch. This means that we can end up with a successful return
|
|
|
7bcd4f |
from the helper which we still report as a failure.
|
|
|
7bcd4f |
|
|
|
7bcd4f |
If we add G_IO_HUP and G_IO_ERR to the conditions we look for in the
|
|
|
7bcd4f |
io watch and the child terminates we still run the io watch handler
|
|
|
7bcd4f |
which will complete the session.
|
|
|
7bcd4f |
|
|
|
7bcd4f |
This means that the child watch is in fact needless and we can remove
|
|
|
7bcd4f |
it.
|
|
|
7bcd4f |
|
|
|
7bcd4f |
https://bugs.freedesktop.org/show_bug.cgi?id=60847
|
|
|
7bcd4f |
---
|
|
|
7bcd4f |
src/polkitagent/polkitagentsession.c | 47 +++++++++---------------------------
|
|
|
7bcd4f |
1 file changed, 11 insertions(+), 36 deletions(-)
|
|
|
7bcd4f |
|
|
|
7bcd4f |
diff --git a/src/polkitagent/polkitagentsession.c b/src/polkitagent/polkitagentsession.c
|
|
|
7bcd4f |
index 1c7a2dc..f014773 100644
|
|
|
7bcd4f |
--- a/src/polkitagent/polkitagentsession.c
|
|
|
7bcd4f |
+++ b/src/polkitagent/polkitagentsession.c
|
|
|
7bcd4f |
@@ -92,7 +92,6 @@ struct _PolkitAgentSession
|
|
|
7bcd4f |
int child_stdout;
|
|
|
7bcd4f |
GPid child_pid;
|
|
|
7bcd4f |
|
|
|
7bcd4f |
- GSource *child_watch_source;
|
|
|
7bcd4f |
GSource *child_stdout_watch_source;
|
|
|
7bcd4f |
GIOChannel *child_stdout_channel;
|
|
|
7bcd4f |
|
|
|
7bcd4f |
@@ -377,13 +376,6 @@ kill_helper (PolkitAgentSession *session)
|
|
|
7bcd4f |
session->child_pid = 0;
|
|
|
7bcd4f |
}
|
|
|
7bcd4f |
|
|
|
7bcd4f |
- if (session->child_watch_source != NULL)
|
|
|
7bcd4f |
- {
|
|
|
7bcd4f |
- g_source_destroy (session->child_watch_source);
|
|
|
7bcd4f |
- g_source_unref (session->child_watch_source);
|
|
|
7bcd4f |
- session->child_watch_source = NULL;
|
|
|
7bcd4f |
- }
|
|
|
7bcd4f |
-
|
|
|
7bcd4f |
if (session->child_stdout_watch_source != NULL)
|
|
|
7bcd4f |
{
|
|
|
7bcd4f |
g_source_destroy (session->child_stdout_watch_source);
|
|
|
7bcd4f |
@@ -429,26 +421,6 @@ complete_session (PolkitAgentSession *session,
|
|
|
7bcd4f |
}
|
|
|
7bcd4f |
}
|
|
|
7bcd4f |
|
|
|
7bcd4f |
-static void
|
|
|
7bcd4f |
-child_watch_func (GPid pid,
|
|
|
7bcd4f |
- gint status,
|
|
|
7bcd4f |
- gpointer user_data)
|
|
|
7bcd4f |
-{
|
|
|
7bcd4f |
- PolkitAgentSession *session = POLKIT_AGENT_SESSION (user_data);
|
|
|
7bcd4f |
-
|
|
|
7bcd4f |
- if (G_UNLIKELY (_show_debug ()))
|
|
|
7bcd4f |
- {
|
|
|
7bcd4f |
- g_print ("PolkitAgentSession: in child_watch_func for pid %d (WIFEXITED=%d WEXITSTATUS=%d)\n",
|
|
|
7bcd4f |
- (gint) pid,
|
|
|
7bcd4f |
- WIFEXITED(status),
|
|
|
7bcd4f |
- WEXITSTATUS(status));
|
|
|
7bcd4f |
- }
|
|
|
7bcd4f |
-
|
|
|
7bcd4f |
- /* kill all the watches we have set up, except for the child since it has exited already */
|
|
|
7bcd4f |
- session->child_pid = 0;
|
|
|
7bcd4f |
- complete_session (session, FALSE);
|
|
|
7bcd4f |
-}
|
|
|
7bcd4f |
-
|
|
|
7bcd4f |
static gboolean
|
|
|
7bcd4f |
io_watch_have_data (GIOChannel *channel,
|
|
|
7bcd4f |
GIOCondition condition,
|
|
|
7bcd4f |
@@ -475,10 +447,13 @@ io_watch_have_data (GIOChannel *channel,
|
|
|
7bcd4f |
NULL,
|
|
|
7bcd4f |
NULL,
|
|
|
7bcd4f |
&error);
|
|
|
7bcd4f |
- if (error != NULL)
|
|
|
7bcd4f |
+ if (error != NULL || line == NULL)
|
|
|
7bcd4f |
{
|
|
|
7bcd4f |
- g_warning ("Error reading line from helper: %s", error->message);
|
|
|
7bcd4f |
- g_error_free (error);
|
|
|
7bcd4f |
+ /* In case we get just G_IO_HUP, line is NULL but error is
|
|
|
7bcd4f |
+ unset.*/
|
|
|
7bcd4f |
+ g_warning ("Error reading line from helper: %s",
|
|
|
7bcd4f |
+ error ? error->message : "nothing to read");
|
|
|
7bcd4f |
+ g_clear_error (&error);
|
|
|
7bcd4f |
|
|
|
7bcd4f |
complete_session (session, FALSE);
|
|
|
7bcd4f |
goto out;
|
|
|
7bcd4f |
@@ -540,6 +515,9 @@ io_watch_have_data (GIOChannel *channel,
|
|
|
7bcd4f |
g_free (line);
|
|
|
7bcd4f |
g_free (unescaped);
|
|
|
7bcd4f |
|
|
|
7bcd4f |
+ if (condition & (G_IO_ERR | G_IO_HUP))
|
|
|
7bcd4f |
+ complete_session (session, FALSE);
|
|
|
7bcd4f |
+
|
|
|
7bcd4f |
/* keep the IOChannel around */
|
|
|
7bcd4f |
return TRUE;
|
|
|
7bcd4f |
}
|
|
|
7bcd4f |
@@ -650,12 +628,9 @@ polkit_agent_session_initiate (PolkitAgentSession *session)
|
|
|
7bcd4f |
if (G_UNLIKELY (_show_debug ()))
|
|
|
7bcd4f |
g_print ("PolkitAgentSession: spawned helper with pid %d\n", (gint) session->child_pid);
|
|
|
7bcd4f |
|
|
|
7bcd4f |
- session->child_watch_source = g_child_watch_source_new (session->child_pid);
|
|
|
7bcd4f |
- g_source_set_callback (session->child_watch_source, (GSourceFunc) child_watch_func, session, NULL);
|
|
|
7bcd4f |
- g_source_attach (session->child_watch_source, g_main_context_get_thread_default ());
|
|
|
7bcd4f |
-
|
|
|
7bcd4f |
session->child_stdout_channel = g_io_channel_unix_new (session->child_stdout);
|
|
|
7bcd4f |
- session->child_stdout_watch_source = g_io_create_watch (session->child_stdout_channel, G_IO_IN);
|
|
|
7bcd4f |
+ session->child_stdout_watch_source = g_io_create_watch (session->child_stdout_channel,
|
|
|
7bcd4f |
+ G_IO_IN | G_IO_ERR | G_IO_HUP);
|
|
|
7bcd4f |
g_source_set_callback (session->child_stdout_watch_source, (GSourceFunc) io_watch_have_data, session, NULL);
|
|
|
7bcd4f |
g_source_attach (session->child_stdout_watch_source, g_main_context_get_thread_default ());
|
|
|
7bcd4f |
|
|
|
7bcd4f |
--
|
|
|
7bcd4f |
1.8.3.1
|
|
|
7bcd4f |
|