diff options
author | jdp <jdp@FreeBSD.org> | 1999-12-28 04:38:17 +0000 |
---|---|---|
committer | jdp <jdp@FreeBSD.org> | 1999-12-28 04:38:17 +0000 |
commit | 363b7bd53715dfc3c4b8bc6809fed0a241c34a9a (patch) | |
tree | 69b2660c2be6f033a411c7b6f07eb8728f078b9d /libexec/rtld-elf | |
parent | c96f8e891fe73a35ab2082f6403dd88a66ac0222 (diff) | |
download | FreeBSD-src-363b7bd53715dfc3c4b8bc6809fed0a241c34a9a.zip FreeBSD-src-363b7bd53715dfc3c4b8bc6809fed0a241c34a9a.tar.gz |
Work around an assert failure in the dynamic linker's default thread
locking functions. If an application loads a shared object with
dlopen() and the shared object has an init function which requires
lazy binding, then _rtld_bind is called when the thread is already
inside the dynamic linker. This leads to a recursive acquisition
of the lock, which I was not expecting -- hence the assert failure.
This work-around makes the default locking functions handle recursive
locking. It is NOT the correct fix -- that should be implemented
at the generic locking level rather than in the default locking
functions. I will implement the correct fix in a future commit.
Since the dllockinit() interface will likely need to change, warn
about that in both the man page and the header file.
Diffstat (limited to 'libexec/rtld-elf')
-rw-r--r-- | libexec/rtld-elf/alpha/lockdflt.c | 12 | ||||
-rw-r--r-- | libexec/rtld-elf/amd64/lockdflt.c | 12 | ||||
-rw-r--r-- | libexec/rtld-elf/i386/lockdflt.c | 12 | ||||
-rw-r--r-- | libexec/rtld-elf/lockdflt.c | 12 |
4 files changed, 32 insertions, 16 deletions
diff --git a/libexec/rtld-elf/alpha/lockdflt.c b/libexec/rtld-elf/alpha/lockdflt.c index 6f278c3..c926950 100644 --- a/libexec/rtld-elf/alpha/lockdflt.c +++ b/libexec/rtld-elf/alpha/lockdflt.c @@ -51,8 +51,11 @@ void lockdflt_acquire(void *lock) { LockDflt *l = (LockDflt *)lock; - sigprocmask(SIG_BLOCK, &l->lock_mask, &l->old_mask); - assert(l->depth == 0); + sigset_t old_mask; + + sigprocmask(SIG_BLOCK, &l->lock_mask, &old_mask); + if (l->depth == 0) + l->old_mask = old_mask; l->depth++; } @@ -81,9 +84,10 @@ void lockdflt_release(void *lock) { LockDflt *l = (LockDflt *)lock; - assert(l->depth == 1); l->depth--; - sigprocmask(SIG_SETMASK, &l->old_mask, NULL); + assert(l->depth >= 0); + if (l->depth == 0) + sigprocmask(SIG_SETMASK, &l->old_mask, NULL); } void diff --git a/libexec/rtld-elf/amd64/lockdflt.c b/libexec/rtld-elf/amd64/lockdflt.c index 6f278c3..c926950 100644 --- a/libexec/rtld-elf/amd64/lockdflt.c +++ b/libexec/rtld-elf/amd64/lockdflt.c @@ -51,8 +51,11 @@ void lockdflt_acquire(void *lock) { LockDflt *l = (LockDflt *)lock; - sigprocmask(SIG_BLOCK, &l->lock_mask, &l->old_mask); - assert(l->depth == 0); + sigset_t old_mask; + + sigprocmask(SIG_BLOCK, &l->lock_mask, &old_mask); + if (l->depth == 0) + l->old_mask = old_mask; l->depth++; } @@ -81,9 +84,10 @@ void lockdflt_release(void *lock) { LockDflt *l = (LockDflt *)lock; - assert(l->depth == 1); l->depth--; - sigprocmask(SIG_SETMASK, &l->old_mask, NULL); + assert(l->depth >= 0); + if (l->depth == 0) + sigprocmask(SIG_SETMASK, &l->old_mask, NULL); } void diff --git a/libexec/rtld-elf/i386/lockdflt.c b/libexec/rtld-elf/i386/lockdflt.c index 6f278c3..c926950 100644 --- a/libexec/rtld-elf/i386/lockdflt.c +++ b/libexec/rtld-elf/i386/lockdflt.c @@ -51,8 +51,11 @@ void lockdflt_acquire(void *lock) { LockDflt *l = (LockDflt *)lock; - sigprocmask(SIG_BLOCK, &l->lock_mask, &l->old_mask); - assert(l->depth == 0); + sigset_t old_mask; + + sigprocmask(SIG_BLOCK, &l->lock_mask, &old_mask); + if (l->depth == 0) + l->old_mask = old_mask; l->depth++; } @@ -81,9 +84,10 @@ void lockdflt_release(void *lock) { LockDflt *l = (LockDflt *)lock; - assert(l->depth == 1); l->depth--; - sigprocmask(SIG_SETMASK, &l->old_mask, NULL); + assert(l->depth >= 0); + if (l->depth == 0) + sigprocmask(SIG_SETMASK, &l->old_mask, NULL); } void diff --git a/libexec/rtld-elf/lockdflt.c b/libexec/rtld-elf/lockdflt.c index 6f278c3..c926950 100644 --- a/libexec/rtld-elf/lockdflt.c +++ b/libexec/rtld-elf/lockdflt.c @@ -51,8 +51,11 @@ void lockdflt_acquire(void *lock) { LockDflt *l = (LockDflt *)lock; - sigprocmask(SIG_BLOCK, &l->lock_mask, &l->old_mask); - assert(l->depth == 0); + sigset_t old_mask; + + sigprocmask(SIG_BLOCK, &l->lock_mask, &old_mask); + if (l->depth == 0) + l->old_mask = old_mask; l->depth++; } @@ -81,9 +84,10 @@ void lockdflt_release(void *lock) { LockDflt *l = (LockDflt *)lock; - assert(l->depth == 1); l->depth--; - sigprocmask(SIG_SETMASK, &l->old_mask, NULL); + assert(l->depth >= 0); + if (l->depth == 0) + sigprocmask(SIG_SETMASK, &l->old_mask, NULL); } void |