typedef struct {
MonoNativeThreadId tid;
guint32 recursion;
+ gboolean abandoned;
} MonoW32HandleMutex;
struct MonoW32HandleNamedMutex {
};
static gboolean
-mutex_handle_own (gpointer handle, MonoW32HandleType type)
+mutex_handle_own (gpointer handle, MonoW32HandleType type, guint32 *statuscode)
{
MonoW32HandleMutex *mutex_handle;
+ *statuscode = WAIT_OBJECT_0;
+
if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
return FALSE;
mutex_handle->tid = pthread_self ();
mutex_handle->recursion++;
+ if (mutex_handle->abandoned) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: mutex handle %p was abandoned", __func__, handle);
+ mutex_handle->abandoned = FALSE;
+ *statuscode = WAIT_ABANDONED_0;
+ }
mono_w32handle_set_signal_state (handle, FALSE, FALSE);
ves_icall_System_Threading_Mutex_ReleaseMutex_internal (handle);
}
-static gboolean mutex_own (gpointer handle)
+static gboolean mutex_own (gpointer handle, guint32 *statuscode)
{
- return mutex_handle_own (handle, MONO_W32HANDLE_MUTEX);
+ return mutex_handle_own (handle, MONO_W32HANDLE_MUTEX, statuscode);
}
static gboolean mutex_is_owned (gpointer handle)
}
/* NB, always called with the shared handle lock held */
-static gboolean namedmutex_own (gpointer handle)
+static gboolean namedmutex_own (gpointer handle, guint32 *statuscode)
{
- return mutex_handle_own (handle, MONO_W32HANDLE_NAMEDMUTEX);
+ return mutex_handle_own (handle, MONO_W32HANDLE_NAMEDMUTEX, statuscode);
}
static gboolean namedmutex_is_owned (gpointer handle)
{
gpointer handle;
int thr_ret;
+ guint32 statuscode;
mutex_handle->tid = 0;
mutex_handle->recursion = 0;
+ mutex_handle->abandoned = FALSE;
handle = mono_w32handle_new (type, mutex_handle);
if (handle == INVALID_HANDLE_VALUE) {
g_assert (thr_ret == 0);
if (owned)
- mutex_handle_own (handle, type);
+ mutex_handle_own (handle, type, &statuscode);
else
mono_w32handle_set_signal_state (handle, TRUE, FALSE);
tid = pthread_self ();
- if (!pthread_equal (mutex_handle->tid, tid)) {
+ if (mutex_handle->abandoned) {
+ // The Win32 ReleaseMutex() function returns TRUE for abandoned mutexes
+ ret = TRUE;
+ } else if (!pthread_equal (mutex_handle->tid, tid)) {
ret = FALSE;
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: we don't own %s handle %p (owned by %ld, me %ld)",
if (pthread_equal (mutex_handle->tid, tid)) {
mutex_handle->recursion = 0;
mutex_handle->tid = 0;
+ mutex_handle->abandoned = TRUE;
mono_w32handle_set_signal_state (handle, TRUE, FALSE);