From b9d7b80897d79cb43c4a795c7d9d3d9a24e140cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 6 Jul 2012 00:46:32 +0200 Subject: [PATCH] win32: make gio stream cancellable v2: - fix cancellation of concurrent readers - replace g_assert() usage with g_warn_if_fail() v3: - fix indentation - fix loop code to not leak (silly me) https://bugzilla.gnome.org/show_bug.cgi?id=679288 --- gio/gasynchelper.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/gio/gasynchelper.c b/gio/gasynchelper.c index fa6c8162b..ab8bd2c1d 100644 --- a/gio/gasynchelper.c +++ b/gio/gasynchelper.c @@ -174,9 +174,9 @@ gboolean _g_win32_overlap_wait_result (HANDLE hfile, OVERLAPPED *overlap, DWORD *transferred, - GCancellable *cancellable G_GNUC_UNUSED) + GCancellable *cancellable) { - GPollFD pollfd[1] = { 0, }; + GPollFD pollfd[2]; gboolean result = FALSE; gint num, npoll; @@ -184,15 +184,36 @@ _g_win32_overlap_wait_result (HANDLE hfile, pollfd[0].events = G_IO_IN; num = 1; + if (g_cancellable_make_pollfd (cancellable, &pollfd[1])) + num++; + +loop: npoll = g_poll (pollfd, num, -1); if (npoll <= 0) /* error out, should never happen */ goto end; - /* either cancelled or IO completed, either way get the result */ - result = GetOverlappedResult (overlap->hEvent, overlap, transferred, TRUE); + if (g_cancellable_is_cancelled (cancellable)) + { + /* CancelIO only cancels pending operations issued by the + * current thread and since we're doing only sync operations, + * this is safe.... */ + /* CancelIoEx is only Vista+. Since we have only one overlap + * operaton on this thread, we can just use: */ + result = CancelIo (hfile); + g_warn_if_fail (result); + } + + result = GetOverlappedResult (overlap->hEvent, overlap, transferred, FALSE); + if (result == FALSE && + GetLastError () == ERROR_IO_INCOMPLETE && + !g_cancellable_is_cancelled (cancellable)) + goto loop; end: + if (num > 1) + g_cancellable_release_fd (cancellable); + return result; } #endif