/pidgin/main: 21cffc3446a0: purple-gio: Add purple-gio.[ch] cont...

Mike Ruprecht <[email protected]> Sun, 28 Aug 2016 23:58:01 -0400
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: 21cffc3446a0aad1399efa0feb7adf10e35ffa4c
Author:	 Mike Ruprecht <[email protected]>
Date:	 2016-08-27 01:28 -0500
Branch:	 default
URL: https://hg.pidgin.im/pidgin/main/rev/21cffc3446a0

Description:

purple-gio: Add purple-gio.[ch] containing purple_gio_graceful_close()

In order to gracefully close Gio connections, there can't be pending
operations with input nor output stream. Having a synchronous close
function for PurpleConnection causes just calling g_io_stream_close()
in the close function to be a potential race condition.

This patch adds a function which takes a GIOStream and optionally any
wrapping GInputStream or GOutputStream, waits for pending operations
to complete asynchronously if any, and then gracefully closes the
connection. If no operations are pending, it closes them synchronously.

diffstat:

 libpurple/Makefile.am  |    2 +
 libpurple/purple-gio.c |  107 +++++++++++++++++++++++++++++++++++++++++++++++++
 libpurple/purple-gio.h |   59 +++++++++++++++++++++++++++
 3 files changed, 168 insertions(+), 0 deletions(-)

diffs (195 lines):

diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am
--- a/libpurple/Makefile.am
+++ b/libpurple/Makefile.am
@@ -93,6 +93,7 @@ purple_coresources = \
 	proxy.c \
 	protocol.c \
 	protocols.c \
+	purple-gio.c \
 	purple-socket.c \
 	queuedoutputstream.c \
 	request.c \
@@ -173,6 +174,7 @@ purple_coreheaders = \
 	proxy.h \
 	protocol.h \
 	protocols.h \
+	purple-gio.h \
 	purple-socket.h \
 	queuedoutputstream.h \
 	request.h \
diff --git a/libpurple/purple-gio.c b/libpurple/purple-gio.c
new file mode 100644
--- /dev/null
+++ b/libpurple/purple-gio.c
@@ -0,0 +1,107 @@
+/*
+ *
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include "internal.h"
+#include "purple-gio.h"
+
+typedef struct {
+	GIOStream *stream;
+	GInputStream *input;
+	GOutputStream *output;
+} GracefulCloseData;
+
+static gboolean
+graceful_close_cb(gpointer user_data)
+{
+	GracefulCloseData *data = user_data;
+	GError *error = NULL;
+
+	if (g_input_stream_has_pending(data->input) ||
+			g_output_stream_has_pending(data->output)) {
+		/* Has pending operations. Not ready to close yet.
+		 * Try again later.
+		 */
+		return G_SOURCE_CONTINUE;
+	}
+
+	/* Finally can gracefully close */
+
+	/* Close wrapper input stream, if any */
+	if (data->input != NULL &&
+			!g_input_stream_close(data->input, NULL, &error)) {
+		purple_debug_warning("gio",
+				"Error closing input stream: %s",
+				error->message);
+		g_clear_error(&error);
+	}
+
+	g_clear_object(&data->input);
+
+	/* Close wrapper output stream, if any */
+	if (data->output != NULL &&
+			!g_output_stream_close(data->output, NULL, &error)) {
+		purple_debug_warning("gio",
+				"Error closing output stream: %s",
+				error->message);
+		g_clear_error(&error);
+	}
+
+	g_clear_object(&data->output);
+
+	/* Close io stream */
+	if (!g_io_stream_close(data->stream, NULL, &error)) {
+		purple_debug_warning("gio",
+				"Error closing stream: %s",
+				error->message);
+		g_clear_error(&error);
+	}
+
+	g_clear_object(&data->stream);
+
+	/* Clean up */
+	g_free(data);
+	return G_SOURCE_REMOVE;
+}
+
+void
+purple_gio_graceful_close(GIOStream *stream,
+		GInputStream *input, GOutputStream *output)
+{
+	GracefulCloseData *data;
+
+	g_return_if_fail(G_IS_IO_STREAM(stream));
+	g_return_if_fail(input == NULL || G_IS_INPUT_STREAM(input));
+	g_return_if_fail(output == NULL || G_IS_OUTPUT_STREAM(output));
+
+	data = g_new(GracefulCloseData, 1);
+	data->stream = g_object_ref(stream);
+	data->input = g_object_ref(input);
+	data->output = g_object_ref(output);
+
+	/* Try gracefully closing the stream synchronously */
+	if (graceful_close_cb(data) == G_SOURCE_CONTINUE) {
+		/* Has pending operations. Do so asynchronously */
+		g_idle_add(graceful_close_cb, data);
+	}
+}
+
diff --git a/libpurple/purple-gio.h b/libpurple/purple-gio.h
new file mode 100644
--- /dev/null
+++ b/libpurple/purple-gio.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#ifndef _PURPLE_GIO_H
+#define _PURPLE_GIO_H
+/**
+ * SECTION:purple-gio
+ * @section_id: libpurple-purple-gio
+ * @short_description: Gio helper functions
+ * @title: Purple Gio API
+ *
+ * The Purple Gio API provides helper functions for Gio operations which
+ * are commonly used within libpurple and its consumers. These contain
+ * such functions as setting up connections and shutting them down
+ * gracefully.
+ */
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+/**
+ * purple_gio_graceful_close:
+ * @stream: A #GIOStream to close
+ * @input: (optional): A #GInputStream which wraps @stream's input stream
+ * @output: (optional): A #GOutputStream which wraps @stream's output stream
+ *
+ * Closes @input, @output, @stream. If there are pending operations, it
+ * asynchronously waits for the operations to finish before closing the
+ * arguments. Ensure the Gio callbacks can safely handle this being done
+ * asynchronously.
+ */
+void
+purple_gio_graceful_close(GIOStream *stream,
+		GInputStream *input, GOutputStream *output);
+
+G_END_DECLS
+
+#endif /* _PURPLE_GIO_H */

_______________________________________________
Commits mailing list
[email protected]
https://pidgin.im/cgi-bin/mailman/listinfo/commits