PipeInputStream and PipeOutputStream should not fail when creating GPollableStream source as this currently does not work with default write_all and read_all functions; In order to avoid creating zombie GSource in create_source of both PipeInputStream and PipeOutputStream, we track all created GSources and set them to be dispatched when data is available to read/write. It is worth to mention that concurrent write/read is not possible with current giopipe and only the last created GSource will read the data as it is dispatched first. --- gtk/giopipe.c | 69 +++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/gtk/giopipe.c b/gtk/giopipe.c index 50edb5b..0e654ce 100644 --- a/gtk/giopipe.c +++ b/gtk/giopipe.c @@ -44,7 +44,7 @@ struct _PipeInputStream * closing. */ gboolean peer_closed; - GSource *source; + GList *sources; }; struct _PipeInputStreamClass @@ -69,7 +69,7 @@ struct _PipeOutputStream const gchar *buffer; gsize count; gboolean peer_closed; - GSource *source; + GList *sources; }; struct _PipeOutputStreamClass @@ -120,12 +120,35 @@ pipe_input_stream_read (GInputStream *stream, return count; } +static GList * +set_all_sources_ready (GList *sources) +{ + GList *it = sources; + while (it != NULL) { + GSource *s = it->data; + GList *next = it->next; + + if (s == NULL || g_source_is_destroyed(s)) { + /* remove */ + sources = g_list_delete_link(sources, it); + g_clear_pointer(&s, g_source_unref); + } else { + /* dispatch */ + g_source_set_ready_time(s, 0); + } + it = next; + } + return sources; +} + static void pipe_input_stream_check_source (PipeInputStream *self) { - if (self->source && !g_source_is_destroyed(self->source) && - g_pollable_input_stream_is_readable(G_POLLABLE_INPUT_STREAM(self))) - g_source_set_ready_time(self->source, 0); + if (self->sources == NULL) + return; + + if (g_pollable_input_stream_is_readable(G_POLLABLE_INPUT_STREAM(self))) + self->sources = set_all_sources_ready(self->sources); } static gboolean @@ -193,10 +216,8 @@ pipe_input_stream_dispose(GObject *object) self->peer = NULL; } - if (self->source) { - g_source_unref(self->source); - self->source = NULL; - } + g_list_free_full (self->sources, (GDestroyNotify) g_source_unref); + self->sources = NULL; G_OBJECT_CLASS(pipe_input_stream_parent_class)->dispose (object); } @@ -234,14 +255,8 @@ pipe_input_stream_create_source (GPollableInputStream *stream, PipeInputStream *self = PIPE_INPUT_STREAM(stream); GSource *pollable_source; - g_return_val_if_fail (self->source == NULL || - g_source_is_destroyed (self->source), NULL); - - if (self->source && g_source_is_destroyed (self->source)) - g_source_unref (self->source); - pollable_source = g_pollable_source_new_full (self, NULL, cancellable); - self->source = g_source_ref (pollable_source); + self->sources = g_list_prepend (self->sources, g_source_ref (pollable_source)); return pollable_source; } @@ -319,10 +334,8 @@ pipe_output_stream_dispose(GObject *object) self->peer = NULL; } - if (self->source) { - g_source_unref(self->source); - self->source = NULL; - } + g_list_free_full (self->sources, (GDestroyNotify) g_source_unref); + self->sources = NULL; G_OBJECT_CLASS(pipe_output_stream_parent_class)->dispose (object); } @@ -330,9 +343,11 @@ pipe_output_stream_dispose(GObject *object) static void pipe_output_stream_check_source (PipeOutputStream *self) { - if (self->source && !g_source_is_destroyed(self->source) && - g_pollable_output_stream_is_writable(G_POLLABLE_OUTPUT_STREAM(self))) - g_source_set_ready_time(self->source, 0); + if (self->sources == NULL) + return; + + if (g_pollable_output_stream_is_writable(G_POLLABLE_OUTPUT_STREAM(self))) + self->sources = set_all_sources_ready(self->sources); } static gboolean @@ -416,14 +431,8 @@ pipe_output_stream_create_source (GPollableOutputStream *stream, PipeOutputStream *self = PIPE_OUTPUT_STREAM(stream); GSource *pollable_source; - g_return_val_if_fail (self->source == NULL || - g_source_is_destroyed (self->source), NULL); - - if (self->source && g_source_is_destroyed (self->source)) - g_source_unref (self->source); - pollable_source = g_pollable_source_new_full (self, NULL, cancellable); - self->source = g_source_ref (pollable_source); + self->sources = g_list_prepend (self->sources, g_source_ref (pollable_source)); return pollable_source; } -- 2.4.2 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel