diff options
author | davidxu <davidxu@FreeBSD.org> | 2010-09-19 05:19:47 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2010-09-19 05:19:47 +0000 |
commit | ad24f558bd7b034d0376f20da562ae31ddfe68b1 (patch) | |
tree | 47623deb3552808a7fe4395dec19f249ad2c4c3f | |
parent | eebc7df64cafec4f2e406fa12be1388c91175299 (diff) | |
download | FreeBSD-src-ad24f558bd7b034d0376f20da562ae31ddfe68b1.zip FreeBSD-src-ad24f558bd7b034d0376f20da562ae31ddfe68b1.tar.gz |
Fix a race condition when finding stack unwinding functions.
-rw-r--r-- | lib/libthr/thread/thr_exit.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/lib/libthr/thread/thr_exit.c b/lib/libthr/thread/thr_exit.c index 2ff3953..83188c8 100644 --- a/lib/libthr/thread/thr_exit.c +++ b/lib/libthr/thread/thr_exit.c @@ -70,18 +70,31 @@ static void thread_uw_init(void) { static int inited = 0; + Dl_info dlinfo; void *handle; + void *forcedunwind, *resume, *getcfa; if (inited) - return; - inited = 1; + return; handle = RTLD_DEFAULT; - if ((uwl_forcedunwind = dlsym(handle, "_Unwind_ForcedUnwind")) == NULL|| - (uwl_resume = dlsym(handle, "_Unwind_Resume")) == NULL || - (uwl_getcfa = dlsym(handle, "_Unwind_GetCFA")) == NULL) { - uwl_forcedunwind = NULL; - return; + if ((forcedunwind = dlsym(handle, "_Unwind_ForcedUnwind")) != NULL) { + if (dladdr(forcedunwind, &dlinfo)) { + if ((handle = dlopen(dlinfo.dli_fname, RTLD_LAZY)) != NULL) { + forcedunwind = dlsym(handle, "_Unwind_ForcedUnwind"); + resume = dlsym(handle, "_Unwind_Resume"); + getcfa = dlsym(handle, "_Unwind_GetCFA"); + if (forcedunwind != NULL && resume != NULL && + getcfa != NULL) { + uwl_forcedunwind = forcedunwind; + uwl_resume = resume; + uwl_getcfa = getcfa; + } else { + dlclose(handle); + } + } + } } + inited = 1; } void |