Skip to content

Commit 5fddd4e

Browse files
authored
Merge pull request #1139 from Unity-Technologies/unity-master-fix-readfile-blocking
Fix interrupting blocking file IO on Windows.
2 parents d6f42ee + dbede6d commit 5fddd4e

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-9
lines changed

mono/metadata/w32file-win32.c

+10-8
Original file line numberDiff line numberDiff line change
@@ -95,19 +95,20 @@ mono_w32file_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *
9595

9696
gboolean interrupted;
9797
guint32 last_error;
98-
gboolean res;
98+
gboolean res = FALSE;
9999

100-
MonoThreadInfo *info = mono_thread_info_current ();
100+
mono_thread_info_install_interrupt (cancel_w32_io, handle, &interrupted);
101+
if (interrupted)
102+
return res;
101103

102-
mono_win32_enter_blocking_io_call (info, (HANDLE)handle);
103104
MONO_ENTER_GC_SAFE;
104105
res = ReadFile ((HANDLE)handle, buffer, numbytes, (PDWORD)bytesread, NULL);
105106
/* need to save and restore since clients expect error code set for
106107
* failed IO calls and mono_thread_info_uninstall_interrupt overwrites value */
107108
last_error = mono_w32error_get_last ();
108109

109110
MONO_EXIT_GC_SAFE;
110-
mono_win32_leave_blocking_io_call (info, (HANDLE)handle);
111+
mono_thread_info_uninstall_interrupt (&interrupted);
111112
mono_w32error_set_last (last_error);
112113

113114

@@ -119,18 +120,19 @@ mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, gui
119120
{
120121
gboolean interrupted;
121122
guint32 last_error;
122-
gboolean res;
123+
gboolean res = FALSE;
123124

124-
MonoThreadInfo *info = mono_thread_info_current ();
125+
mono_thread_info_install_interrupt (cancel_w32_io, handle, &interrupted);
126+
if (interrupted)
127+
return res;
125128

126-
mono_win32_enter_blocking_io_call (info, (HANDLE)handle);
127129
MONO_ENTER_GC_SAFE;
128130
res = WriteFile ((HANDLE)handle, buffer, numbytes, (PDWORD)byteswritten, NULL);
129131
/* need to save and restore since clients expect error code set for
130132
* failed IO calls and mono_thread_info_uninstall_interrupt overwrites value */
131133
last_error = mono_w32error_get_last ();
132134
MONO_EXIT_GC_SAFE;
133-
mono_win32_leave_blocking_io_call (info, (HANDLE)handle);
135+
mono_thread_info_uninstall_interrupt (&interrupted);
134136
mono_w32error_set_last (last_error);
135137

136138
return res;

mono/utils/mono-threads-windows.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@ suspend_abort_syscall (PVOID thread_info, HANDLE native_thread_handle, DWORD tid
113113
// all outputstanding sync IO for target thread. If its not blocked on a sync IO request, below
114114
// call will just fail and nothing will be canceled. If thread is waiting on overlapped IO,
115115
// the queued APC will take care of cancel specific outstanding IO requests.
116-
CancelSynchronousIo (native_thread_handle);
116+
117+
// UNITY: Only call CancelSynchronousIo if needed. Can cause hangs if arbitrarily called
118+
if (((MonoThreadInfo*)thread_info)->win32_apc_info_io_handle != INVALID_HANDLE_VALUE)
119+
CancelSynchronousIo (native_thread_handle);
117120
#endif
118121
}
119122

0 commit comments

Comments
 (0)