aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Polstra <jdp@FreeBSD.org>1999-12-28 04:38:17 +0000
committerJohn Polstra <jdp@FreeBSD.org>1999-12-28 04:38:17 +0000
commit3600eb76c6005988b386d04cfdb5963b38a18eee (patch)
tree87a46a42824ad2fcf6b934cf07a8d0e56a4a34b7
parent427db879c9c39266493f3a7f772d0acc584547b4 (diff)
downloadsrc-3600eb76c6005988b386d04cfdb5963b38a18eee.tar.gz
src-3600eb76c6005988b386d04cfdb5963b38a18eee.zip
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.
Notes
Notes: svn path=/head/; revision=55165
-rw-r--r--include/dlfcn.h1
-rw-r--r--lib/libc/gen/dllockinit.34
-rw-r--r--libexec/rtld-elf/alpha/lockdflt.c12
-rw-r--r--libexec/rtld-elf/amd64/lockdflt.c12
-rw-r--r--libexec/rtld-elf/i386/lockdflt.c12
-rw-r--r--libexec/rtld-elf/lockdflt.c12
6 files changed, 37 insertions, 16 deletions
diff --git a/include/dlfcn.h b/include/dlfcn.h
index 09edf2dde31b..16cc41754cef 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -66,6 +66,7 @@ __BEGIN_DECLS
int dladdr __P((const void *, Dl_info *));
int dlclose __P((void *));
const char *dlerror __P((void));
+/* XXX dllockinit() interface is likely to change. */
void dllockinit __P((void *_context,
void *(*_lock_create)(void *_context),
void (*_rlock_acquire)(void *_lock),
diff --git a/lib/libc/gen/dllockinit.3 b/lib/libc/gen/dllockinit.3
index facb18ba0353..7bc32b3ebb6a 100644
--- a/lib/libc/gen/dllockinit.3
+++ b/lib/libc/gen/dllockinit.3
@@ -39,6 +39,10 @@
"void (*lock_release)(void *lock)" "void (*lock_destroy)(void *lock)" \
"void (*context_destroy)(void *context)"
.Sh DESCRIPTION
+.Bf Sy
+This interface is subject to change and should not be used yet.
+.Ef
+.Pp
Threads packages can call
.Nm
at initialization time to register locking functions for the dynamic
diff --git a/libexec/rtld-elf/alpha/lockdflt.c b/libexec/rtld-elf/alpha/lockdflt.c
index 6f278c3ab284..c92695001bd7 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 6f278c3ab284..c92695001bd7 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 6f278c3ab284..c92695001bd7 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 6f278c3ab284..c92695001bd7 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