[Spice-devel] [spice-gtk PATCH v6 1/6] giopipe: don't fail on create_source
Victor Toso
victortoso at redhat.com
Wed Jun 3 02:23:01 PDT 2015
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
More information about the Spice-devel
mailing list