From 1a8bdd5affba07f4688c7c16224cc4ec2ec73aca Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Wed, 28 Jun 2017 15:48:28 -0700 Subject: [PATCH] [io-layer] Fix two race conditions, one on FD handle creation and one on interrupt install. mono_w32handle_new_fd: We must hold scan_mutex while initializing an unallocated handle otherwise mono_w32handle_foreach might think it's a valid handle. mono_w32handle_timedwait_signal_handle: We must increment the refcount before installing the interrupt handle as the other end can be called right after we finish installing and would trigger a failure. --- mono/metadata/w32handle.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/mono/metadata/w32handle.c b/mono/metadata/w32handle.c index f6862a9a7db..9ecec767ba0 100644 --- a/mono/metadata/w32handle.c +++ b/mono/metadata/w32handle.c @@ -451,19 +451,17 @@ gpointer mono_w32handle_new_fd (MonoW32HandleType type, int fd, fd_index = SLOT_INDEX (fd); fd_offset = SLOT_OFFSET (fd); + mono_os_mutex_lock (&scan_mutex); /* Initialize the array entries on demand */ if (!private_handles [fd_index]) { - mono_os_mutex_lock (&scan_mutex); - if (!private_handles [fd_index]) private_handles [fd_index] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT); - - mono_os_mutex_unlock (&scan_mutex); } handle_data = &private_handles [fd_index][fd_offset]; if (handle_data->type != MONO_W32HANDLE_UNUSED) { + mono_os_mutex_unlock (&scan_mutex); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle, fd is already in use", __func__, mono_w32handle_ops_typename (type)); /* FIXME: clean up this handle? We can't do anything * with the fd, cos thats the new one @@ -475,6 +473,8 @@ gpointer mono_w32handle_new_fd (MonoW32HandleType type, int fd, mono_w32handle_init_handle (handle_data, type, handle_specific); + mono_os_mutex_unlock (&scan_mutex); + return(GUINT_TO_POINTER(fd)); } @@ -1080,10 +1080,12 @@ mono_w32handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboole *alerted = FALSE; if (alerted) { + mono_w32handle_ref (handle); mono_thread_info_install_interrupt (signal_handle_and_unref, handle, alerted); - if (*alerted) + if (*alerted) { + mono_w32handle_unref (handle); return 0; - mono_w32handle_ref (handle); + } } res = mono_w32handle_timedwait_signal_naked (&handle_data->signal_cond, &handle_data->signal_mutex, timeout, poll, alerted); -- 2.25.1