/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