MINOR: tools: protect dladdr() against reentrant calls from the debug handler
If a thread is currently resolving a symbol while another thread triggers a thread dump, the current thread may enter the debug handler and call resolve_sym_addr() again, possibly deadlocking if the underlying libc uses locking. Let's postpone the debug signal delivery in this area during the call. This will slow the resolution a little bit but we don't care, it's not supposed to happen often and it must remain rock-solid.
This commit is contained in:
parent
8d0c633677
commit
2dfb63313b
22
src/tools.c
22
src/tools.c
@ -35,6 +35,7 @@ extern void *__elf_aux_vector;
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -5562,6 +5563,7 @@ const void *resolve_sym_name(struct buffer *buf, const char *pfx, const void *ad
|
||||
static Dl_info dli_main;
|
||||
static int dli_main_done; // 0 = not resolved, 1 = resolve in progress, 2 = done
|
||||
__decl_thread_var(static HA_SPINLOCK_T dladdr_lock);
|
||||
sigset_t new_mask, old_mask;
|
||||
int isolated;
|
||||
Dl_info dli;
|
||||
size_t size = 0;
|
||||
@ -5610,9 +5612,26 @@ const void *resolve_sym_name(struct buffer *buf, const char *pfx, const void *ad
|
||||
HA_SPIN_TRYLOCK(OTHER_LOCK, &dladdr_lock) != 0)
|
||||
goto use_array;
|
||||
|
||||
/* make sure we don't re-enter from wdt nor debug coming from other
|
||||
* threads as dladdr() is not re-entrant. We'll block these sensitive
|
||||
* signals while possibly dumping a backtrace.
|
||||
*/
|
||||
sigemptyset(&new_mask);
|
||||
#ifdef WDTSIG
|
||||
sigaddset(&new_mask, WDTSIG);
|
||||
#endif
|
||||
#ifdef DEBUGSIG
|
||||
sigaddset(&new_mask, DEBUGSIG);
|
||||
#endif
|
||||
ha_sigmask(SIG_BLOCK, &new_mask, &old_mask);
|
||||
|
||||
/* now resolve the symbol */
|
||||
i = dladdr_and_size(addr, &dli, &size);
|
||||
|
||||
if (!i) {
|
||||
/* unblock temporarily blocked signals */
|
||||
ha_sigmask(SIG_SETMASK, &old_mask, NULL);
|
||||
|
||||
if (!isolated)
|
||||
HA_SPIN_UNLOCK(OTHER_LOCK, &dladdr_lock);
|
||||
goto use_array;
|
||||
@ -5638,6 +5657,9 @@ const void *resolve_sym_name(struct buffer *buf, const char *pfx, const void *ad
|
||||
ha_thread_relax();
|
||||
}
|
||||
|
||||
/* unblock temporarily blocked signals */
|
||||
ha_sigmask(SIG_SETMASK, &old_mask, NULL);
|
||||
|
||||
if (!isolated)
|
||||
HA_SPIN_UNLOCK(OTHER_LOCK, &dladdr_lock);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user