Skip to content

Commit

Permalink
Merge pull request #1139 from Unity-Technologies/unity-master-fix-rea…
Browse files Browse the repository at this point in the history
…dfile-blocking

Fix interrupting blocking file IO on Windows.
  • Loading branch information
joncham authored Feb 13, 2019
2 parents d6f42ee + dbede6d commit 5fddd4e
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 9 deletions.
18 changes: 10 additions & 8 deletions mono/metadata/w32file-win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,20 @@ 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
* 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);


Expand All @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion mono/utils/mono-threads-windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down

0 comments on commit 5fddd4e

Please sign in to comment.