From dbede6df2ec99debd9e6c1d551ba3c0ed1385594 Mon Sep 17 00:00:00 2001 From: Jonathan Chambers Date: Wed, 13 Feb 2019 15:44:13 -0500 Subject: [PATCH] Fix interrupting blocking file IO on Windows. Revert part of https://github.com/Unity-Technologies/mono/pull/1131 as it causes hangs in calls to CancelSynchronousIo --- mono/metadata/w32file-win32.c | 18 ++++++++++-------- mono/utils/mono-threads-windows.c | 5 ++++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/mono/metadata/w32file-win32.c b/mono/metadata/w32file-win32.c index 3ac8bf2506df..249dc5aceda9 100644 --- a/mono/metadata/w32file-win32.c +++ b/mono/metadata/w32file-win32.c @@ -95,11 +95,12 @@ mono_w32file_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 * gboolean interrupted; guint32 last_error; - gboolean res; + gboolean res = FALSE; - MonoThreadInfo *info = mono_thread_info_current (); + mono_thread_info_install_interrupt (cancel_w32_io, handle, &interrupted); + if (interrupted) + return res; - mono_win32_enter_blocking_io_call (info, (HANDLE)handle); MONO_ENTER_GC_SAFE; res = ReadFile ((HANDLE)handle, buffer, numbytes, (PDWORD)bytesread, NULL); /* need to save and restore since clients expect error code set for @@ -107,7 +108,7 @@ mono_w32file_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 * last_error = mono_w32error_get_last (); MONO_EXIT_GC_SAFE; - mono_win32_leave_blocking_io_call (info, (HANDLE)handle); + mono_thread_info_uninstall_interrupt (&interrupted); mono_w32error_set_last (last_error); @@ -119,18 +120,19 @@ mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, gui { gboolean interrupted; guint32 last_error; - gboolean res; + gboolean res = FALSE; - MonoThreadInfo *info = mono_thread_info_current (); + mono_thread_info_install_interrupt (cancel_w32_io, handle, &interrupted); + if (interrupted) + return res; - mono_win32_enter_blocking_io_call (info, (HANDLE)handle); MONO_ENTER_GC_SAFE; res = WriteFile ((HANDLE)handle, buffer, numbytes, (PDWORD)byteswritten, NULL); /* need to save and restore since clients expect error code set for * failed IO calls and mono_thread_info_uninstall_interrupt overwrites value */ last_error = mono_w32error_get_last (); MONO_EXIT_GC_SAFE; - mono_win32_leave_blocking_io_call (info, (HANDLE)handle); + mono_thread_info_uninstall_interrupt (&interrupted); mono_w32error_set_last (last_error); return res; diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c index d7a47fce1037..5194f814ac03 100644 --- a/mono/utils/mono-threads-windows.c +++ b/mono/utils/mono-threads-windows.c @@ -113,7 +113,10 @@ suspend_abort_syscall (PVOID thread_info, HANDLE native_thread_handle, DWORD tid // all outputstanding sync IO for target thread. If its not blocked on a sync IO request, below // call will just fail and nothing will be canceled. If thread is waiting on overlapped IO, // the queued APC will take care of cancel specific outstanding IO requests. - CancelSynchronousIo (native_thread_handle); + + // UNITY: Only call CancelSynchronousIo if needed. Can cause hangs if arbitrarily called + if (((MonoThreadInfo*)thread_info)->win32_apc_info_io_handle != INVALID_HANDLE_VALUE) + CancelSynchronousIo (native_thread_handle); #endif }