Merge pull request #2998 from lateralusX/jlorenss/win-x64-full-aot-support
[mono.git] / mono / metadata / threads.c
index 5884d0270e58ee9ce7dd577fc37d3d16a8a4fced..8acb6f5efafa01e91926c3b54cdc1dd87f3849a9 100644 (file)
@@ -257,8 +257,14 @@ mono_thread_get_tls_key (void)
 gint32
 mono_thread_get_tls_offset (void)
 {
-       int offset;
+       int offset = -1;
+
+#ifdef HOST_WIN32
+       if (current_object_key)
+               offset = current_object_key;
+#else
        MONO_THREAD_VAR_OFFSET (tls_current_object,offset);
+#endif
        return offset;
 }
 
@@ -454,7 +460,11 @@ static void thread_cleanup (MonoInternalThread *thread)
        }
        mono_release_type_locks (thread);
 
-       mono_profiler_thread_end (thread->tid);
+       /* Can happen when we attach the profiler helper thread in order to heapshot. */
+       if (!mono_thread_info_lookup (MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid))->tools_thread)
+               mono_profiler_thread_end (thread->tid);
+
+       mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
 
        if (thread == mono_thread_internal_current ()) {
                /*
@@ -616,23 +626,25 @@ create_internal_thread (MonoError *error)
        return thread;
 }
 
-static void
-init_root_domain_thread (MonoInternalThread *thread, MonoThread *candidate)
+static gboolean
+init_root_domain_thread (MonoInternalThread *thread, MonoThread *candidate, MonoError *error)
 {
-       MonoError error;
        MonoDomain *domain = mono_get_root_domain ();
 
+       mono_error_init (error);
        if (!candidate || candidate->obj.vtable->domain != domain) {
-               candidate = new_thread_with_internal (domain, thread, &error);
-               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               candidate = new_thread_with_internal (domain, thread, error);
+               return_val_if_nok (error, FALSE);
        }
        set_current_thread_for_domain (domain, thread, candidate);
        g_assert (!thread->root_domain_thread);
        MONO_OBJECT_SETREF (thread, root_domain_thread, candidate);
+       return TRUE;
 }
 
 static guint32 WINAPI start_wrapper_internal(void *data)
 {
+       MonoError error;
        MonoThreadInfo *info;
        StartInfo *start_info = (StartInfo *)data;
        guint32 (*start_func)(void *);
@@ -681,7 +693,8 @@ static guint32 WINAPI start_wrapper_internal(void *data)
        /* We have to do this here because mono_thread_new_init()
           requires that root_domain_thread is set up. */
        thread_adjust_static_data (internal);
-       init_root_domain_thread (internal, start_info->obj);
+       init_root_domain_thread (internal, start_info->obj, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
 
        /* This MUST be called before any managed code can be
         * executed, as it calls the callback function that (for the
@@ -722,11 +735,13 @@ static guint32 WINAPI start_wrapper_internal(void *data)
        mono_profiler_thread_start (tid);
 
        /* if the name was set before starting, we didn't invoke the profiler callback */
-       if (internal->name && (internal->flags & MONO_THREAD_FLAG_NAME_SET)) {
+       if (internal->name) {
                char *tname = g_utf16_to_utf8 (internal->name, internal->name_len, NULL, NULL, NULL);
                mono_profiler_thread_name (internal->tid, tname);
+               mono_native_thread_set_name (MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid), tname);
                g_free (tname);
        }
+
        /* start_func is set only for unmanaged start functions */
        if (start_func) {
                start_func (start_arg);
@@ -735,7 +750,8 @@ static guint32 WINAPI start_wrapper_internal(void *data)
                g_assert (start_delegate != NULL);
                args [0] = start_arg;
                /* we may want to handle the exception here. See comment below on unhandled exceptions */
-               mono_runtime_delegate_invoke (start_delegate, args, NULL);
+               mono_runtime_delegate_invoke_checked (start_delegate, args, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
        }
 
        /* If the thread calls ExitThread at all, this remaining code
@@ -787,7 +803,7 @@ static guint32 WINAPI start_wrapper(void *data)
  */
 static gboolean
 create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *start_info, gboolean threadpool_thread, guint32 stack_size,
-                          gboolean throw_on_failure)
+                          MonoError *error)
 {
        HANDLE thread_handle;
        MonoNativeThreadId tid;
@@ -799,6 +815,8 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *star
         */
        mono_threads_join_threads ();
 
+       mono_error_init (error);
+
        mono_threads_lock ();
        if (shutting_down) {
                g_free (start_info);
@@ -834,15 +852,12 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *star
                                                                                                stack_size, create_flags, &tid);
 
        if (thread_handle == NULL) {
-               /* The thread couldn't be created, so throw an exception */
+               /* The thread couldn't be created, so set an exception */
                mono_threads_lock ();
                mono_g_hash_table_remove (threads_starting_up, thread);
                mono_threads_unlock ();
                g_free (start_info);
-               if (throw_on_failure)
-                       mono_raise_exception (mono_get_exception_execution_engine ("Couldn't create thread"));
-               else
-                       g_warning ("%s: CreateThread error 0x%x", __func__, GetLastError ());
+               mono_error_set_execution_engine (error, "Couldn't create thread. Error 0x%x", GetLastError());
                return FALSE;
        }
        THREAD_DEBUG (g_message ("%s: Started thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread_handle));
@@ -874,9 +889,9 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *star
                 */
                THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for thread %p (%"G_GSIZE_FORMAT") to start", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
 
-               MONO_PREPARE_BLOCKING;
+               MONO_ENTER_GC_SAFE;
                WaitForSingleObjectEx (internal->start_notify, INFINITE, FALSE);
-               MONO_FINISH_BLOCKING;
+               MONO_EXIT_GC_SAFE;
 
                CloseHandle (internal->start_notify);
                internal->start_notify = NULL;
@@ -910,19 +925,20 @@ guint32 mono_threads_get_default_stacksize (void)
  *   ARG should not be a GC reference.
  */
 MonoInternalThread*
-mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread, guint32 stack_size)
+mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread, guint32 stack_size, MonoError *error)
 {
-       MonoError error;
        MonoThread *thread;
        MonoInternalThread *internal;
        StartInfo *start_info;
        gboolean res;
 
-       thread = create_thread_object (domain, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       mono_error_init (error);
 
-       internal = create_internal_thread (&error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+       thread = create_thread_object (domain, error);
+       return_val_if_nok (error, NULL);
+
+       internal = create_internal_thread (error);
+       return_val_if_nok (error, NULL);
 
        MONO_OBJECT_SETREF (thread, internal_thread, internal);
 
@@ -931,9 +947,8 @@ mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gb
        start_info->obj = thread;
        start_info->start_arg = arg;
 
-       res = create_thread (thread, internal, start_info, threadpool_thread, stack_size, TRUE);
-       if (!res)
-               return NULL;
+       res = create_thread (thread, internal, start_info, threadpool_thread, stack_size, error);
+       return_val_if_nok (error, NULL);
 
        /* Check that the managed and unmanaged layout of MonoInternalThread matches */
 #ifndef MONO_CROSS_COMPILE
@@ -947,7 +962,15 @@ mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gb
 void
 mono_thread_create (MonoDomain *domain, gpointer func, gpointer arg)
 {
-       mono_thread_create_internal (domain, func, arg, FALSE, 0);
+       MonoError error;
+       if (!mono_thread_create_checked (domain, func, arg, &error))
+               mono_error_cleanup (&error);
+}
+
+gboolean
+mono_thread_create_checked (MonoDomain *domain, gpointer func, gpointer arg, MonoError *error)
+{
+       return (NULL != mono_thread_create_internal (domain, func, arg, FALSE, 0, error));
 }
 
 MonoThread *
@@ -1019,7 +1042,9 @@ mono_thread_attach_full (MonoDomain *domain, gboolean force_attach, MonoError *e
 
        thread_adjust_static_data (thread);
 
-       init_root_domain_thread (thread, current_thread);
+       init_root_domain_thread (thread, current_thread, error);
+       return_val_if_nok (error, NULL);
+
        if (domain != mono_get_root_domain ())
                set_current_thread_for_domain (domain, thread, current_thread);
 
@@ -1036,8 +1061,10 @@ mono_thread_attach_full (MonoDomain *domain, gboolean force_attach, MonoError *e
                        mono_thread_attach_cb (MONO_NATIVE_THREAD_ID_TO_UINT (tid), staddr + stsize);
        }
 
-       // FIXME: Need a separate callback
-       mono_profiler_thread_start (MONO_NATIVE_THREAD_ID_TO_UINT (tid));
+       /* Can happen when we attach the profiler helper thread in order to heapshot. */
+       if (!info->tools_thread)
+               // FIXME: Need a separate callback
+               mono_profiler_thread_start (MONO_NATIVE_THREAD_ID_TO_UINT (tid));
 
        return current_thread;
 }
@@ -1123,6 +1150,7 @@ HANDLE
 ves_icall_System_Threading_Thread_Thread_internal (MonoThread *this_obj,
                                                                                                   MonoObject *start)
 {
+       MonoError error;
        StartInfo *start_info;
        MonoInternalThread *internal;
        gboolean res;
@@ -1153,8 +1181,9 @@ ves_icall_System_Threading_Thread_Thread_internal (MonoThread *this_obj,
        start_info->obj = this_obj;
        g_assert (this_obj->obj.vtable->domain == mono_domain_get ());
 
-       res = create_thread (this_obj, internal, start_info, FALSE, 0, FALSE);
+       res = create_thread (this_obj, internal, start_info, FALSE, 0, &error);
        if (!res) {
+               mono_error_cleanup (&error);
                UNLOCK_THREAD (internal);
                return NULL;
        }
@@ -1345,14 +1374,16 @@ ves_icall_System_Threading_Thread_GetName_internal (MonoInternalThread *this_obj
 }
 
 void 
-mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, gboolean managed)
+mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, gboolean permanent, MonoError *error)
 {
        LOCK_THREAD (this_obj);
 
-       if ((this_obj->flags & MONO_THREAD_FLAG_NAME_SET) && !this_obj->threadpool_thread) {
+       mono_error_init (error);
+
+       if ((this_obj->flags & MONO_THREAD_FLAG_NAME_SET)) {
                UNLOCK_THREAD (this_obj);
                
-               mono_raise_exception (mono_get_exception_invalid_operation ("Thread.Name can only be set once."));
+               mono_error_set_invalid_operation (error, "Thread.Name can only be set once.");
                return;
        }
        if (this_obj->name) {
@@ -1363,19 +1394,20 @@ mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, g
                this_obj->name = g_new (gunichar2, mono_string_length (name));
                memcpy (this_obj->name, mono_string_chars (name), mono_string_length (name) * 2);
                this_obj->name_len = mono_string_length (name);
+
+               if (permanent)
+                       this_obj->flags |= MONO_THREAD_FLAG_NAME_SET;
        }
        else
                this_obj->name = NULL;
 
-       if (managed)
-               this_obj->flags |= MONO_THREAD_FLAG_NAME_SET;
        
        UNLOCK_THREAD (this_obj);
 
        if (this_obj->name && this_obj->tid) {
                char *tname = mono_string_to_utf8 (name);
                mono_profiler_thread_name (this_obj->tid, tname);
-               mono_thread_info_set_name (thread_get_tid (this_obj), tname);
+               mono_native_thread_set_name (thread_get_tid (this_obj), tname);
                mono_free (tname);
        }
 }
@@ -1383,7 +1415,9 @@ mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, g
 void 
 ves_icall_System_Threading_Thread_SetName_internal (MonoInternalThread *this_obj, MonoString *name)
 {
-       mono_thread_set_name_internal (this_obj, name, TRUE);
+       MonoError error;
+       mono_thread_set_name_internal (this_obj, name, TRUE, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 /*
@@ -1425,17 +1459,18 @@ ves_icall_System_Threading_Thread_SetPriority (MonoThread *this_obj, int priorit
 /* If the array is already in the requested domain, we just return it,
    otherwise we return a copy in that domain. */
 static MonoArray*
-byte_array_to_domain (MonoArray *arr, MonoDomain *domain)
+byte_array_to_domain (MonoArray *arr, MonoDomain *domain, MonoError *error)
 {
        MonoArray *copy;
 
+       mono_error_init (error);
        if (!arr)
                return NULL;
 
        if (mono_object_domain (arr) == domain)
                return arr;
 
-       copy = mono_array_new (domain, mono_defaults.byte_class, arr->max_length);
+       copy = mono_array_new_checked (domain, mono_defaults.byte_class, arr->max_length, error);
        memmove (mono_array_addr (copy, guint8, 0), mono_array_addr (arr, guint8, 0), arr->max_length);
        return copy;
 }
@@ -1443,13 +1478,19 @@ byte_array_to_domain (MonoArray *arr, MonoDomain *domain)
 MonoArray*
 ves_icall_System_Threading_Thread_ByteArrayToRootDomain (MonoArray *arr)
 {
-       return byte_array_to_domain (arr, mono_get_root_domain ());
+       MonoError error;
+       MonoArray *result = byte_array_to_domain (arr, mono_get_root_domain (), &error);
+       mono_error_set_pending_exception (&error);
+       return result;
 }
 
 MonoArray*
 ves_icall_System_Threading_Thread_ByteArrayToCurrentDomain (MonoArray *arr)
 {
-       return byte_array_to_domain (arr, mono_domain_get ());
+       MonoError error;
+       MonoArray *result = byte_array_to_domain (arr, mono_domain_get (), &error);
+       mono_error_set_pending_exception (&error);
+       return result;
 }
 
 MonoThread *
@@ -1526,9 +1567,9 @@ ves_icall_System_Threading_Thread_Join_internal(MonoThread *this_obj, int ms)
        
        mono_thread_set_state (cur_thread, ThreadState_WaitSleepJoin);
 
-       MONO_PREPARE_BLOCKING;
+       MONO_ENTER_GC_SAFE;
        ret=WaitForSingleObjectEx (handle, ms, TRUE);
-       MONO_FINISH_BLOCKING;
+       MONO_EXIT_GC_SAFE;
 
        mono_thread_clr_state (cur_thread, ThreadState_WaitSleepJoin);
        
@@ -1554,12 +1595,12 @@ mono_wait_uninterrupted (MonoInternalThread *thread, gboolean multiple, guint32
 
        start = (ms == -1) ? 0 : mono_100ns_ticks ();
        do {
-               MONO_PREPARE_BLOCKING;
+               MONO_ENTER_GC_SAFE;
                        if (multiple)
                        ret = WaitForMultipleObjectsEx (numhandles, handles, waitall, wait, alertable);
                else
                        ret = WaitForSingleObjectEx (handles [0], ms, alertable);
-               MONO_FINISH_BLOCKING;
+               MONO_EXIT_GC_SAFE;
 
                if (ret != WAIT_IO_COMPLETION)
                        break;
@@ -1583,8 +1624,7 @@ mono_wait_uninterrupted (MonoInternalThread *thread, gboolean multiple, guint32
        return ret;
 }
 
-/* FIXME: exitContext isnt documented */
-gint32 ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_handles, gint32 ms, gboolean exitContext)
+gint32 ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_handles, gint32 ms)
 {
        HANDLE *handles;
        guint32 numhandles;
@@ -1617,11 +1657,11 @@ gint32 ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_ha
 
        g_free(handles);
 
-       return ret;
+       /* WAIT_FAILED in waithandle.cs is different from WAIT_FAILED in Win32 API */
+       return ret == WAIT_FAILED ? 0x7fffffff : ret;
 }
 
-/* FIXME: exitContext isnt documented */
-gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_handles, gint32 ms, gboolean exitContext)
+gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_handles, gint32 ms)
 {
        HANDLE handles [MAXIMUM_WAIT_OBJECTS];
        uintptr_t numhandles;
@@ -1664,12 +1704,12 @@ gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_ha
                return ret - WAIT_ABANDONED_0;
        }
        else {
-               return ret;
+               /* WAIT_FAILED in waithandle.cs is different from WAIT_FAILED in Win32 API */
+               return ret == WAIT_FAILED ? 0x7fffffff : ret;
        }
 }
 
-/* FIXME: exitContext isnt documented */
-gint32 ves_icall_System_Threading_WaitHandle_WaitOne_internal(HANDLE handle, gint32 ms, gboolean exitContext)
+gint32 ves_icall_System_Threading_WaitHandle_WaitOne_internal(HANDLE handle, gint32 ms)
 {
        guint32 ret;
        MonoInternalThread *thread = mono_thread_internal_current ();
@@ -1688,11 +1728,12 @@ gint32 ves_icall_System_Threading_WaitHandle_WaitOne_internal(HANDLE handle, gin
        
        mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
        
-       return ret;
+       /* WAIT_FAILED in waithandle.cs is different from WAIT_FAILED in Win32 API */
+       return ret == WAIT_FAILED ? 0x7fffffff : ret;
 }
 
 gint32
-ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (HANDLE toSignal, HANDLE toWait, gint32 ms, gboolean exitContext)
+ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (HANDLE toSignal, HANDLE toWait, gint32 ms)
 {
        guint32 ret;
        MonoInternalThread *thread = mono_thread_internal_current ();
@@ -1704,13 +1745,14 @@ ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (HANDLE toSignal, H
 
        mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
        
-       MONO_PREPARE_BLOCKING;
+       MONO_ENTER_GC_SAFE;
        ret = SignalObjectAndWait (toSignal, toWait, ms, TRUE);
-       MONO_FINISH_BLOCKING;
+       MONO_EXIT_GC_SAFE;
        
        mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
 
-       return ret;
+       /* WAIT_FAILED in waithandle.cs is different from WAIT_FAILED in Win32 API */
+       return ret == WAIT_FAILED ? 0x7fffffff : ret;
 }
 
 HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created)
@@ -2253,8 +2295,9 @@ mono_thread_internal_reset_abort (MonoInternalThread *thread)
 MonoObject*
 ves_icall_System_Threading_Thread_GetAbortExceptionState (MonoThread *this_obj)
 {
+       MonoError error;
        MonoInternalThread *thread = this_obj->internal_thread;
-       MonoObject *state, *deserialized = NULL, *exc;
+       MonoObject *state, *deserialized = NULL;
        MonoDomain *domain;
 
        if (!thread->abort_state_handle)
@@ -2267,12 +2310,14 @@ ves_icall_System_Threading_Thread_GetAbortExceptionState (MonoThread *this_obj)
        if (mono_object_domain (state) == domain)
                return state;
 
-       deserialized = mono_object_xdomain_representation (state, domain, &exc);
+       deserialized = mono_object_xdomain_representation (state, domain, &error);
 
        if (!deserialized) {
                MonoException *invalid_op_exc = mono_get_exception_invalid_operation ("Thread.ExceptionState cannot access an ExceptionState from a different AppDomain");
-               if (exc)
+               if (!is_ok (&error)) {
+                       MonoObject *exc = (MonoObject*)mono_error_convert_to_exception (&error);
                        MONO_OBJECT_SETREF (invalid_op_exc, inner_ex, exc);
+               }
                mono_set_pending_exception (invalid_op_exc);
                return NULL;
        }
@@ -2871,9 +2916,9 @@ static void wait_for_tids (struct wait_data *wait, guint32 timeout)
        
        THREAD_DEBUG (g_message("%s: %d threads to wait for in this batch", __func__, wait->num));
 
-       MONO_PREPARE_BLOCKING;
+       MONO_ENTER_GC_SAFE;
        ret=WaitForMultipleObjectsEx(wait->num, wait->handles, TRUE, timeout, TRUE);
-       MONO_FINISH_BLOCKING;
+       MONO_EXIT_GC_SAFE;
 
        if(ret==WAIT_FAILED) {
                /* See the comment in build_wait_tids() */
@@ -2934,9 +2979,9 @@ static void wait_for_tids_or_state_change (struct wait_data *wait, guint32 timeo
                count++;
        }
 
-       MONO_PREPARE_BLOCKING;
+       MONO_ENTER_GC_SAFE;
        ret=WaitForMultipleObjectsEx (count, wait->handles, FALSE, timeout, TRUE);
-       MONO_FINISH_BLOCKING;
+       MONO_EXIT_GC_SAFE;
 
        if(ret==WAIT_FAILED) {
                /* See the comment in build_wait_tids() */
@@ -3043,9 +3088,8 @@ remove_and_abort_threads (gpointer key, gpointer value, gpointer user)
                if (handle == NULL)
                        return FALSE;
 
-               /* printf ("A: %d\n", wait->num); */
-               wait->handles[wait->num]=thread->handle;
-               wait->threads[wait->num]=thread;
+               wait->handles[wait->num] = handle;
+               wait->threads[wait->num] = thread;
                wait->num++;
 
                THREAD_DEBUG (g_print ("%s: Aborting id: %"G_GSIZE_FORMAT"\n", __func__, (gsize)thread->tid));
@@ -3509,8 +3553,12 @@ mono_threads_get_thread_dump (MonoArray **out_threads, MonoArray **out_stack_fra
        ud.frames = g_new0 (MonoStackFrameInfo, 256);
        ud.max_frames = 256;
 
-       *out_threads = mono_array_new (domain, mono_defaults.thread_class, nthreads);
-       *out_stack_frames = mono_array_new (domain, mono_defaults.array_class, nthreads);
+       *out_threads = mono_array_new_checked (domain, mono_defaults.thread_class, nthreads, &error);
+       if (!is_ok (&error))
+               goto leave;
+       *out_stack_frames = mono_array_new_checked (domain, mono_defaults.array_class, nthreads, &error);
+       if (!is_ok (&error))
+               goto leave;
 
        for (tindex = 0; tindex < nthreads; ++tindex) {
                MonoInternalThread *thread = thread_array [tindex];
@@ -3529,7 +3577,9 @@ mono_threads_get_thread_dump (MonoArray **out_threads, MonoArray **out_stack_fra
 
                mono_array_setref_fast (*out_threads, tindex, mono_thread_current_for_thread (thread));
 
-               thread_frames = mono_array_new (domain, mono_defaults.stack_frame_class, ud.nframes);
+               thread_frames = mono_array_new_checked (domain, mono_defaults.stack_frame_class, ud.nframes, &error);
+               if (!is_ok (&error))
+                       goto leave;
                mono_array_setref_fast (*out_stack_frames, tindex, thread_frames);
 
                for (i = 0; i < ud.nframes; ++i) {
@@ -3750,7 +3800,7 @@ mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout)
 #endif
 
        abort_appdomain_data user_data;
-       guint32 start_time;
+       gint64 start_time;
        int orig_timeout = timeout;
        int i;
 
@@ -4330,8 +4380,18 @@ mono_thread_execute_interruption (void)
                mono_thread_info_clear_self_interrupt ();
        }
 
-       if ((thread->state & ThreadState_AbortRequested) != 0) {
+       /* If there's a pending exception and an AbortRequested, the pending exception takes precedence */
+       if (sys_thread->pending_exception) {
+               MonoException *exc;
+
+               exc = sys_thread->pending_exception;
+               sys_thread->pending_exception = NULL;
+
+               UNLOCK_THREAD (thread);
+               return exc;
+       } else if ((thread->state & ThreadState_AbortRequested) != 0) {
                UNLOCK_THREAD (thread);
+               g_assert (sys_thread->pending_exception == NULL);
                if (thread->abort_exc == NULL) {
                        /* 
                         * This might be racy, but it has to be called outside the lock
@@ -4353,14 +4413,6 @@ mono_thread_execute_interruption (void)
                
                mono_thread_exit ();
                return NULL;
-       } else if (sys_thread->pending_exception) {
-               MonoException *exc;
-
-               exc = sys_thread->pending_exception;
-               sys_thread->pending_exception = NULL;
-
-        UNLOCK_THREAD (thread);
-        return exc;
        } else if (thread->thread_interrupt_requested) {
 
                thread->thread_interrupt_requested = FALSE;
@@ -4500,35 +4552,6 @@ mono_thread_force_interruption_checkpoint_noraise (void)
        return mono_thread_interruption_checkpoint_request (TRUE);
 }
 
-/*
- * mono_thread_get_and_clear_pending_exception:
- *
- *   Return any pending exceptions for the current thread and clear it as a side effect.
- */
-MonoException*
-mono_thread_get_and_clear_pending_exception (void)
-{
-       MonoInternalThread *thread = mono_thread_internal_current ();
-       MonoThread *sys_thread = mono_thread_current ();
-
-       /* The thread may already be stopping */
-       if (thread == NULL)
-               return NULL;
-
-       if (thread->interruption_requested && !is_running_protected_wrapper ()) {
-               return mono_thread_execute_interruption ();
-       }
-       
-       if (sys_thread->pending_exception) {
-               MonoException *exc = sys_thread->pending_exception;
-
-               sys_thread->pending_exception = NULL;
-               return exc;
-       }
-
-       return NULL;
-}
-
 /*
  * mono_set_pending_exception:
  *