(gio)
authorChristian Neumair <cneumair@gnome.org>
Mon, 8 Sep 2008 12:44:07 +0000 (12:44 +0000)
committerChristian Neumair <cneumair@src.gnome.org>
Mon, 8 Sep 2008 12:44:07 +0000 (12:44 +0000)
2008-09-08  Christian Neumair  <cneumair@gnome.org>

* gunixmount.c (eject_unmount_read_error), (eject_unmount_do):
* gunixvolume.c (eject_mount_read_error), (eject_mount_do):
Use non-blocking pipe for mount helper I/O. Fixes #550647.

svn path=/trunk/; revision=7444

gio/ChangeLog
gio/gunixmount.c
gio/gunixvolume.c

index 6cc86dc..5d27bde 100644 (file)
@@ -1,3 +1,9 @@
+2008-09-08  Christian Neumair  <cneumair@gnome.org>
+
+       * gunixmount.c (eject_unmount_read_error), (eject_unmount_do):
+       * gunixvolume.c (eject_mount_read_error), (eject_mount_do):
+       Use non-blocking pipe for mount helper I/O. Fixes #550647.
+
 2008-09-06  Matthias Clasen  <mclasen@redhat.com>
 
        Bug 551149 – xdgmime mem leak
index 1ab3581..8c42246 100644 (file)
@@ -42,6 +42,8 @@
 #include "gsimpleasyncresult.h"
 #include "gioerror.h"
 #include "glibintl.h"
+/* for BUFSIZ */
+#include <stdio.h>
 
 #include "gioalias.h"
 
@@ -284,13 +286,33 @@ eject_unmount_read_error (GIOChannel *channel,
                     GIOCondition condition,
                     gpointer user_data)
 {
-  char *str;
-  gsize str_len;
   UnmountEjectOp *data = user_data;
+  char buf[BUFSIZ];
+  gsize bytes_read;
+  GError *error;
+  GIOStatus status;
+
+  error = NULL;
+read:
+  status = g_io_channel_read_chars (channel, buf, sizeof (buf), &bytes_read, &error);
+  if (status == G_IO_STATUS_NORMAL)
+   {
+     g_string_append_len (data->error_string, buf, bytes_read);
+     if (bytes_read == sizeof (buf))
+        goto read;
+   }
+  else if (status == G_IO_STATUS_EOF)
+    g_string_append_len (data->error_string, buf, bytes_read);
+  else if (status == G_IO_STATUS_ERROR)
+    {
+      if (data->error_string->len > 0)
+        g_string_append (data->error_string, "\n");
+
+      g_string_append (data->error_string, error->message);
+      g_error_free (error);
+      return FALSE;
+    }
 
-  g_io_channel_read_to_end (channel, &str, &str_len, NULL);
-  g_string_append (data->error_string, str);
-  g_free (str);
   return TRUE;
 }
 
@@ -324,6 +346,22 @@ eject_unmount_do (GMount              *mount,
                                  NULL,           /* standard_output */
                                  &(data->error_fd),
                                  &error)) {
+    g_assert (error != NULL);
+    goto handle_error;
+  }
+
+  data->error_string = g_string_new ("");
+
+  data->error_channel = g_io_channel_unix_new (data->error_fd);
+  g_io_channel_set_flags (data->error_channel, G_IO_FLAG_NONBLOCK, &error);
+  if (error != NULL)
+    goto handle_error;
+
+  data->error_channel_source_id = g_io_add_watch (data->error_channel, G_IO_IN, eject_unmount_read_error, data);
+  g_child_watch_add (child_pid, eject_unmount_cb, data);
+
+handle_error:
+  if (error != NULL) {
     GSimpleAsyncResult *simple;
     simple = g_simple_async_result_new_from_error (G_OBJECT (data->unix_mount),
                                                    data->callback,
@@ -331,14 +369,16 @@ eject_unmount_do (GMount              *mount,
                                                    error);
     g_simple_async_result_complete (simple);
     g_object_unref (simple);
+
+    if (data->error_string != NULL)
+      g_string_free (data->error_string, TRUE);
+
+    if (data->error_channel != NULL)
+      g_io_channel_unref (data->error_channel);
+
     g_error_free (error);
     g_free (data);
-    return;
   }
-  data->error_string = g_string_new ("");
-  data->error_channel = g_io_channel_unix_new (data->error_fd);
-  data->error_channel_source_id = g_io_add_watch (data->error_channel, G_IO_IN, eject_unmount_read_error, data);
-  g_child_watch_add (child_pid, eject_unmount_cb, data);
 }
 
 static void
index eb68257..16e7067 100644 (file)
@@ -39,6 +39,8 @@
 #include "gsimpleasyncresult.h"
 #include "gioerror.h"
 #include "glibintl.h"
+/* for BUFSIZ */
+#include <stdio.h>
 
 #include "gioalias.h"
 
@@ -333,13 +335,33 @@ eject_mount_read_error (GIOChannel *channel,
                   GIOCondition condition,
                   gpointer user_data)
 {
-  char *str;
-  gsize str_len;
   EjectMountOp *data = user_data;
+  char buf[BUFSIZ];
+  gsize bytes_read;
+  GError *error;
+  GIOStatus status;
+
+  error = NULL;
+read:
+  status = g_io_channel_read_chars (channel, buf, sizeof (buf), &bytes_read, &error);
+  if (status == G_IO_STATUS_NORMAL)
+   {
+     g_string_append_len (data->error_string, buf, bytes_read);
+     if (bytes_read == sizeof (buf))
+        goto read;
+   }
+  else if (status == G_IO_STATUS_EOF)
+    g_string_append_len (data->error_string, buf, bytes_read);
+  else if (status == G_IO_STATUS_ERROR)
+    {
+      if (data->error_string->len > 0)
+        g_string_append (data->error_string, "\n");
+
+      g_string_append (data->error_string, error->message);
+      g_error_free (error);
+      return FALSE;
+    }
 
-  g_io_channel_read_to_end (channel, &str, &str_len, NULL);
-  g_string_append (data->error_string, str);
-  g_free (str);
   return TRUE;
 }
 
@@ -373,6 +395,22 @@ eject_mount_do (GVolume             *volume,
                                  NULL,           /* standard_output */
                                  &(data->error_fd),
                                  &error)) {
+    g_assert (error != NULL);
+    goto handle_error;
+  }
+
+  data->error_string = g_string_new ("");
+
+  data->error_channel = g_io_channel_unix_new (data->error_fd);
+  g_io_channel_set_flags (data->error_channel, G_IO_FLAG_NONBLOCK, &error);
+  if (error != NULL)
+    goto handle_error;
+
+  data->error_channel_source_id = g_io_add_watch (data->error_channel, G_IO_IN, eject_mount_read_error, data);
+  g_child_watch_add (child_pid, eject_mount_cb, data);
+
+handle_error:
+  if (error != NULL) {
     GSimpleAsyncResult *simple;
     simple = g_simple_async_result_new_from_error (G_OBJECT (data->unix_volume),
                                                    data->callback,
@@ -380,14 +418,16 @@ eject_mount_do (GVolume             *volume,
                                                    error);
     g_simple_async_result_complete (simple);
     g_object_unref (simple);
+
+    if (data->error_string != NULL)
+      g_string_free (data->error_string, TRUE);
+
+    if (data->error_channel != NULL)
+      g_io_channel_unref (data->error_channel);
+
     g_error_free (error);
     g_free (data);
-    return;
   }
-  data->error_string = g_string_new ("");
-  data->error_channel = g_io_channel_unix_new (data->error_fd);
-  data->error_channel_source_id = g_io_add_watch (data->error_channel, G_IO_IN, eject_mount_read_error, data);
-  g_child_watch_add (child_pid, eject_mount_cb, data);
 }