summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2008-05-06 09:27:41 +0000
committerkib <kib@FreeBSD.org>2008-05-06 09:27:41 +0000
commit60e5d7d0529be9f877e67cf34013ac32320062f0 (patch)
tree0d4b4b84b2ad5fa15e5d4e4caee3794dae371904 /libexec
parentfc58e99cef77a3982048f6b39d87180dd8b28ad9 (diff)
downloadFreeBSD-src-60e5d7d0529be9f877e67cf34013ac32320062f0.zip
FreeBSD-src-60e5d7d0529be9f877e67cf34013ac32320062f0.tar.gz
Fix the problem with the C++ exception handling for the multithreaded
programs. From the PR description: The gcc runtime's _Unwind_Find_FDE function, invoked during exception handling's stack unwinding, is not safe to execute from within multiple threads. FreeBSD' s dl_iterate_phdr() however permits multiple threads to pass through it though. The result is surprisingly reliable infinite looping of one or more threads if they just happen to be unwinding at the same time. Introduce the new lock that is write locked around the dl_iterate_pdr, thus providing required exclusion for the stack unwinders. PR: threads/123062 Submitted by: Andy Newman <an at atrn org> Reviewed by: kan MFC after: 2 weeks
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/rtld.c8
-rw-r--r--libexec/rtld-elf/rtld_lock.c3
-rw-r--r--libexec/rtld-elf/rtld_lock.h1
3 files changed, 8 insertions, 4 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index ad27632..ec68eea 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -2129,9 +2129,10 @@ dl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param)
{
struct dl_phdr_info phdr_info;
const Obj_Entry *obj;
- int error, lockstate;
+ int error, bind_lockstate, phdr_lockstate;
- lockstate = rlock_acquire(rtld_bind_lock);
+ phdr_lockstate = wlock_acquire(rtld_phdr_lock);
+ bind_lockstate = rlock_acquire(rtld_bind_lock);
error = 0;
@@ -2150,7 +2151,8 @@ dl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param)
break;
}
- rlock_release(rtld_bind_lock, lockstate);
+ rlock_release(rtld_bind_lock, bind_lockstate);
+ wlock_release(rtld_phdr_lock, phdr_lockstate);
return (error);
}
diff --git a/libexec/rtld-elf/rtld_lock.c b/libexec/rtld-elf/rtld_lock.c
index 1d77fe1..c67f5fb 100644
--- a/libexec/rtld-elf/rtld_lock.c
+++ b/libexec/rtld-elf/rtld_lock.c
@@ -171,7 +171,7 @@ thread_mask_clear(int mask)
lockinfo.thread_clr_flag(mask);
}
-#define RTLD_LOCK_CNT 2
+#define RTLD_LOCK_CNT 3
struct rtld_lock {
void *handle;
int mask;
@@ -179,6 +179,7 @@ struct rtld_lock {
rtld_lock_t rtld_bind_lock = &rtld_locks[0];
rtld_lock_t rtld_libc_lock = &rtld_locks[1];
+rtld_lock_t rtld_phdr_lock = &rtld_locks[2];
int
rlock_acquire(rtld_lock_t lock)
diff --git a/libexec/rtld-elf/rtld_lock.h b/libexec/rtld-elf/rtld_lock.h
index cca4f18..2e3f954 100644
--- a/libexec/rtld-elf/rtld_lock.h
+++ b/libexec/rtld-elf/rtld_lock.h
@@ -52,6 +52,7 @@ typedef struct rtld_lock *rtld_lock_t;
extern rtld_lock_t rtld_bind_lock;
extern rtld_lock_t rtld_libc_lock;
+extern rtld_lock_t rtld_phdr_lock;
int rlock_acquire(rtld_lock_t);
int wlock_acquire(rtld_lock_t);
OpenPOWER on IntegriCloud