diff options
author | Timur Iskhodzhanov <timurrrr@google.com> | 2015-03-11 17:47:10 +0000 |
---|---|---|
committer | Timur Iskhodzhanov <timurrrr@google.com> | 2015-03-11 17:47:10 +0000 |
commit | 4779d3501762b1c89b54dd852787e410d1dc3e5e (patch) | |
tree | a7938b2dbd3ec5e3f10b3931c904c55313df2b7b /lib | |
parent | c832cef78d250afa8265d018c2472678f7d2e63e (diff) |
[ASan/Win] Fix a CHECK failure when an exception is thrown from a callback passed to QueueUserWorkItem
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@231947 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/asan/asan_interceptors.cc | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc index df5769692..2e08d99da 100644 --- a/lib/asan/asan_interceptors.cc +++ b/lib/asan/asan_interceptors.cc @@ -832,9 +832,55 @@ INTERCEPTOR_WINAPI(DWORD, CreateThread, asan_thread_start, t, thr_flags, tid); } +struct UserWorkItemInfo { + DWORD (__stdcall *function)(void *arg); + void *arg; + u32 parent_tid; +}; + +static BlockingMutex mu_for_thread_tracking(LINKER_INITIALIZED); + +// QueueUserWorkItem may silently create a thread we should keep track of. +// We achieve this by wrapping the user-supplied work items with our function. +static DWORD __stdcall QueueUserWorkItemWrapper(void *arg) { + UserWorkItemInfo *item = (UserWorkItemInfo *)arg; + + { + // FIXME: GetCurrentThread relies on TSD, which might not play well with + // system thread pools. We might want to use something like reference + // counting to zero out GetCurrentThread() underlying storage when the last + // work item finishes? Or can we disable reclaiming of threads in the pool? + BlockingMutexLock l(&mu_for_thread_tracking); + AsanThread *t = GetCurrentThread(); + if (!t) { + GET_STACK_TRACE_THREAD; + t = AsanThread::Create(/* start_routine */ nullptr, /* arg */ nullptr, + item->parent_tid, &stack, /* detached */ true); + t->Init(); + asanThreadRegistry().StartThread(t->tid(), 0, 0); + SetCurrentThread(t); + } + } + + DWORD ret = item->function(item->arg); + delete item; + return ret; +} + +INTERCEPTOR_WINAPI(DWORD, QueueUserWorkItem, DWORD(__stdcall *function)(void *), + void *arg, DWORD flags) { + UserWorkItemInfo *work_item_info = new UserWorkItemInfo; + work_item_info->function = function; + work_item_info->arg = arg; + work_item_info->parent_tid = GetCurrentTidOrInvalid(); + return REAL(QueueUserWorkItem)(QueueUserWorkItemWrapper, work_item_info, + flags); +} + namespace __asan { void InitializeWindowsInterceptors() { ASAN_INTERCEPT_FUNC(CreateThread); + ASAN_INTERCEPT_FUNC(QueueUserWorkItem); ASAN_INTERCEPT_FUNC(RaiseException); ASAN_INTERCEPT_FUNC(_except_handler3); ASAN_INTERCEPT_FUNC(_except_handler4); |