X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mono.git;a=blobdiff_plain;f=mono%2Fmetadata%2Fthreads.c;h=34f3be0d4887eb48835f6381a8e12e1598e16a6f;hp=d53f160758820a990d96a8906650537544365912;hb=6b139f4c98eb90bfb7e1285933fc682dae541cad;hpb=6277ba55de75c3a760ba030e112485a623c02d89 diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index d53f1607588..34f3be0d488 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -9,6 +9,7 @@ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) * Copyright 2004-2009 Novell, Inc (http://www.novell.com) * Copyright 2011 Xamarin, Inc (http://www.xamarin.com) + * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ #include @@ -453,7 +454,9 @@ 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); if (thread == mono_thread_internal_current ()) { /* @@ -615,23 +618,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 *); @@ -680,7 +685,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 @@ -724,6 +730,7 @@ static guint32 WINAPI start_wrapper_internal(void *data) if (internal->name && (internal->flags & MONO_THREAD_FLAG_NAME_SET)) { char *tname = g_utf16_to_utf8 (internal->name, internal->name_len, NULL, NULL, NULL); mono_profiler_thread_name (internal->tid, tname); + mono_thread_info_set_name (MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid), tname); g_free (tname); } /* start_func is set only for unmanaged start functions */ @@ -786,7 +793,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; @@ -798,6 +805,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); @@ -833,15 +842,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)); @@ -909,19 +915,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); @@ -930,9 +937,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 @@ -946,7 +952,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 * @@ -1018,7 +1032,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); @@ -1035,8 +1051,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; } @@ -1122,6 +1140,7 @@ HANDLE ves_icall_System_Threading_Thread_Thread_internal (MonoThread *this_obj, MonoObject *start) { + MonoError error; StartInfo *start_info; MonoInternalThread *internal; gboolean res; @@ -1152,8 +1171,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; } @@ -1344,14 +1364,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 managed, MonoError *error) { LOCK_THREAD (this_obj); + mono_error_init (error); + if ((this_obj->flags & MONO_THREAD_FLAG_NAME_SET) && !this_obj->threadpool_thread) { 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) { @@ -1382,7 +1404,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); } /* @@ -1424,17 +1448,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; } @@ -1442,13 +1467,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 * @@ -1582,8 +1613,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; @@ -1616,11 +1646,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; @@ -1663,12 +1693,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 (); @@ -1687,11 +1717,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 (); @@ -1709,7 +1740,8 @@ ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (HANDLE toSignal, H 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) @@ -2252,8 +2284,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) @@ -2266,12 +2299,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; } @@ -3508,8 +3543,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]; @@ -3528,7 +3567,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) {