From 4f6b3f30f048632a763bbd552b3c0c4dbc7af7e0 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 30 Mar 2020 08:36:22 -0400 Subject: [PATCH] [wasm] Throw an exception in some blocking operations in non-threaded mode. (#19363) * [wasm] Throw an exception from Monitor.Wait () in non-threaded mode. * [wasm] Throw an exception when waiting for unsignalled events in non-threaded mode. --- mono/metadata/monitor.c | 7 +++++++ mono/metadata/threads.c | 16 ++++++++++++++++ mono/metadata/w32handle.c | 28 ++++++++++++++++++++++++++++ mono/metadata/w32handle.h | 6 ++++++ 4 files changed, 57 insertions(+) diff --git a/mono/metadata/monitor.c b/mono/metadata/monitor.c index 643af9ba177..72e51bd56c5 100644 --- a/mono/metadata/monitor.c +++ b/mono/metadata/monitor.c @@ -1409,6 +1409,13 @@ mono_monitor_wait (MonoObjectHandle obj_handle, guint32 ms, MonoBoolean allow_in mono_error_set_pending_exception (error); return FALSE; } + +#ifdef DISABLE_THREADS + if (ms == MONO_INFINITE_WAIT) { + mono_error_set_synchronization_lock (error, "Cannot wait on monitors on this runtime."); + return FALSE; + } +#endif LOCK_DEBUG (g_message ("%s: (%d) queuing handle %p", __func__, id, event)); diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index f28e0bdc8e9..684aa2e7919 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -2314,6 +2314,22 @@ ves_icall_System_Threading_WaitHandle_Wait_internal (gpointer *handles, gint32 n MonoW32HandleWaitRet ret; +#ifdef DISABLE_THREADS + if (numhandles == 1 && timeout == MONO_INFINITE_WAIT) { + gboolean signalled = FALSE; + for (int i = 0; i < numhandles; ++i) { + if (mono_w32handle_handle_is_owned (handles [i]) || mono_w32handle_handle_is_signalled (handles [i])) { + signalled = TRUE; + break; + } + } + if (!signalled) { + mono_error_set_synchronization_lock (error, "Cannot wait on events on this runtime."); + return 0; + } + } +#endif + HANDLE_LOOP_PREPARE; for (;;) { diff --git a/mono/metadata/w32handle.c b/mono/metadata/w32handle.c index 5f064b5aa52..17a4b9d68dd 100644 --- a/mono/metadata/w32handle.c +++ b/mono/metadata/w32handle.c @@ -815,6 +815,34 @@ own_if_owned (MonoW32Handle *handle_data, gboolean *abandoned) return TRUE; } +gboolean +mono_w32handle_handle_is_signalled (gpointer handle) +{ + MonoW32Handle *handle_data; + gboolean res; + + if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) + return FALSE; + + res = mono_w32handle_issignalled (handle_data); + mono_w32handle_unref (handle_data); + return res; +} + +gboolean +mono_w32handle_handle_is_owned (gpointer handle) +{ + MonoW32Handle *handle_data; + gboolean res; + + if (!mono_w32handle_lookup_and_ref (handle, &handle_data)) + return FALSE; + + res = mono_w32handle_ops_isowned (handle_data); + mono_w32handle_unref (handle_data); + return res; +} + #ifdef HOST_WIN32 MonoW32HandleWaitRet mono_w32handle_wait_one (gpointer handle, guint32 timeout, gboolean alertable) diff --git a/mono/metadata/w32handle.h b/mono/metadata/w32handle.h index 215606314f3..d0c50a9357b 100644 --- a/mono/metadata/w32handle.h +++ b/mono/metadata/w32handle.h @@ -154,6 +154,12 @@ mono_w32handle_trylock (MonoW32Handle *handle_data); void mono_w32handle_unlock (MonoW32Handle *handle_data); +gboolean +mono_w32handle_handle_is_signalled (gpointer handle); + +gboolean +mono_w32handle_handle_is_owned (gpointer handle); + MonoW32HandleWaitRet mono_w32handle_wait_one (gpointer handle, guint32 timeout, gboolean alertable); -- 2.11.4.GIT