From b9c69790a81a8390bda9ae02faeba0e06d3430ca Mon Sep 17 00:00:00 2001 From: Christian Neumair Date: Mon, 8 Sep 2008 12:44:07 +0000 Subject: [PATCH] (gio) 2008-09-08 Christian Neumair * 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 | 6 ++++++ gio/gunixmount.c | 60 +++++++++++++++++++++++++++++++++++++++++++++---------- gio/gunixvolume.c | 60 +++++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 106 insertions(+), 20 deletions(-) diff --git a/gio/ChangeLog b/gio/ChangeLog index 6cc86dc..5d27bde 100644 --- a/gio/ChangeLog +++ b/gio/ChangeLog @@ -1,3 +1,9 @@ +2008-09-08 Christian Neumair + + * 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 Bug 551149 – xdgmime mem leak diff --git a/gio/gunixmount.c b/gio/gunixmount.c index 1ab3581..8c42246 100644 --- a/gio/gunixmount.c +++ b/gio/gunixmount.c @@ -42,6 +42,8 @@ #include "gsimpleasyncresult.h" #include "gioerror.h" #include "glibintl.h" +/* for BUFSIZ */ +#include #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 diff --git a/gio/gunixvolume.c b/gio/gunixvolume.c index eb68257..16e7067 100644 --- a/gio/gunixvolume.c +++ b/gio/gunixvolume.c @@ -39,6 +39,8 @@ #include "gsimpleasyncresult.h" #include "gioerror.h" #include "glibintl.h" +/* for BUFSIZ */ +#include #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); } -- 2.7.4