[gnome-video-arcade] Make reading of child process output more portable.



commit 8c1a7ba35568e915fd065b520ec8c900e77e4045
Author: Pierre Riteau <pierre riteau gmail com>
Date:   Sat Apr 11 19:09:26 2009 +0200

    Make reading of child process output more portable.
    
    The code reading the output of the SDLMAME child process was
    non-functional on OpenBSD because of differences of behavior from
    poll(2). When poll(2) monitors output from a pipe which reaches EOF,
    the revents flags returned by poll(2) differ between implementations.
    Linux only sets the POLLHUP flag, while OpenBSD sets both the POLLIN and
    the POLLHUP flags.
    Since the condition variable given as argument to process_stdout_ready
    is partially derived from the revents flags, process_stdout_ready on
    OpenBSD is called with G_IO_IN|G_IO_HUP when we hit EOF. With these
    flags, the event source is not removed, and process_stdout_ready is
    called again and again.
    
    Modify the process_read_line function to return the status reported by
    g_io_channel_read_line. This makes it possible for process_stdout_ready
    and process_stderr_ready to remove the event source when the status is
    not G_IO_STATUS_NORMAL.
---
 src/gva-process.c |   23 ++++++++++++++++-------
 1 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/src/gva-process.c b/src/gva-process.c
index 56ef754..36197bc 100644
--- a/src/gva-process.c
+++ b/src/gva-process.c
@@ -152,7 +152,7 @@ process_exited (GPid pid,
         }
 }
 
-static void
+static GIOStatus
 process_read_line (GvaProcess *process,
                    GIOChannel *channel,
                    GQueue *queue,
@@ -172,6 +172,8 @@ process_read_line (GvaProcess *process,
         }
         else
                 process_propagate_error (process, error);
+
+        return status;
 }
 
 static gboolean
@@ -179,6 +181,8 @@ process_stdout_ready (GIOChannel *channel,
                       GIOCondition condition,
                       GvaProcess *process)
 {
+        GIOStatus status;
+
         if (condition & G_IO_IN)
         {
                 /* For better performance, keep reading lines as long as
@@ -189,18 +193,20 @@ process_stdout_ready (GIOChannel *channel,
 
                 do
                 {
-                        process_read_line (
+                        status = process_read_line (
                                 process, channel,
                                 process->priv->stdout_lines,
                                 signals[STDOUT_READY]);
 
-                        /* Break immediately if we have a G_IO_HUP. */
-                        condition = (condition & G_IO_HUP) |
+                        /* Continue reading as long as data is available
+                         * in the internal buffer. */
+                        condition =
                                 g_io_channel_get_buffer_condition (channel);
                 }
                 while (condition == G_IO_IN);
 
-                return TRUE;
+                if (status == G_IO_STATUS_NORMAL)
+                        return TRUE;
         }
 
         process->priv->stdout_source_id = 0;
@@ -213,16 +219,19 @@ process_stderr_ready (GIOChannel *channel,
                       GIOCondition condition,
                       GvaProcess *process)
 {
+        GIOStatus status;
+
         if (condition & G_IO_IN)
         {
                 /* Do NOT loop here, as we do for stdout. */
 
-                process_read_line (
+                status = process_read_line (
                         process, channel,
                         process->priv->stderr_lines,
                         signals[STDERR_READY]);
 
-                return TRUE;
+                if (status == G_IO_STATUS_NORMAL)
+                        return TRUE;
         }
 
         process->priv->stderr_source_id = 0;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]