Use sigfastblock(2) for masking signals in libthr.
Ensure proper handshake to transfer sigfastblock(2) blocking word ownership from rtld to libthr. Unfortunately sigfastblock(2) is not enough to stop intercepting signals in libthr, because critical sections must ensure more than just signal blocking. Tested by: pho Disscussed with: cem, emaste, jilles Sponsored by: The FreeBSD Foundation Differential revision: https://reviews.freebsd.org/D12773
This commit is contained in:
parent
aef199e563
commit
fc908e5001
@ -257,6 +257,7 @@ thread_start(struct pthread *curthread)
|
||||
|
||||
if (curthread->attr.suspend == THR_CREATE_SUSPENDED)
|
||||
set = curthread->sigmask;
|
||||
_thr_signal_block_setup(curthread);
|
||||
|
||||
/*
|
||||
* This is used as a serialization point to allow parent
|
||||
|
@ -396,6 +396,9 @@ struct pthread {
|
||||
/* Signal blocked counter. */
|
||||
int sigblock;
|
||||
|
||||
/* Fast sigblock var. */
|
||||
uint32_t fsigblock;
|
||||
|
||||
/* Queue entry for list of all threads. */
|
||||
TAILQ_ENTRY(pthread) tle; /* link for all threads in process */
|
||||
|
||||
@ -813,6 +816,8 @@ void _thr_cancel_leave(struct pthread *, int) __hidden;
|
||||
void _thr_testcancel(struct pthread *) __hidden;
|
||||
void _thr_signal_block(struct pthread *) __hidden;
|
||||
void _thr_signal_unblock(struct pthread *) __hidden;
|
||||
void _thr_signal_block_check_fast(void) __hidden;
|
||||
void _thr_signal_block_setup(struct pthread *) __hidden;
|
||||
void _thr_signal_init(int) __hidden;
|
||||
void _thr_signal_deinit(void) __hidden;
|
||||
int _thr_send_sig(struct pthread *, int sig) __hidden;
|
||||
|
@ -236,6 +236,8 @@ _thr_rtld_init(void)
|
||||
_thr_signal_block(curthread);
|
||||
_rtld_thread_init(&li);
|
||||
_thr_signal_unblock(curthread);
|
||||
_thr_signal_block_check_fast();
|
||||
_thr_signal_block_setup(curthread);
|
||||
|
||||
uc_len = __getcontextx_size();
|
||||
uc = alloca(uc_len);
|
||||
|
@ -31,7 +31,8 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "namespace.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/auxv.h>
|
||||
#include <sys/elf.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <signal.h>
|
||||
@ -92,10 +93,9 @@ static const sigset_t _thr_maskset={{
|
||||
0xffffffff,
|
||||
0xffffffff}};
|
||||
|
||||
void
|
||||
_thr_signal_block(struct pthread *curthread)
|
||||
static void
|
||||
thr_signal_block_slow(struct pthread *curthread)
|
||||
{
|
||||
|
||||
if (curthread->sigblock > 0) {
|
||||
curthread->sigblock++;
|
||||
return;
|
||||
@ -104,13 +104,68 @@ _thr_signal_block(struct pthread *curthread)
|
||||
curthread->sigblock++;
|
||||
}
|
||||
|
||||
void
|
||||
_thr_signal_unblock(struct pthread *curthread)
|
||||
static void
|
||||
thr_signal_unblock_slow(struct pthread *curthread)
|
||||
{
|
||||
if (--curthread->sigblock == 0)
|
||||
__sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
thr_signal_block_fast(struct pthread *curthread)
|
||||
{
|
||||
atomic_add_32(&curthread->fsigblock, SIGFASTBLOCK_INC);
|
||||
}
|
||||
|
||||
static void
|
||||
thr_signal_unblock_fast(struct pthread *curthread)
|
||||
{
|
||||
uint32_t oldval;
|
||||
|
||||
oldval = atomic_fetchadd_32(&curthread->fsigblock, -SIGFASTBLOCK_INC);
|
||||
if (oldval == (SIGFASTBLOCK_PEND | SIGFASTBLOCK_INC))
|
||||
__sys_sigfastblock(SIGFASTBLOCK_UNBLOCK, NULL);
|
||||
}
|
||||
|
||||
static bool fast_sigblock;
|
||||
|
||||
void
|
||||
_thr_signal_block(struct pthread *curthread)
|
||||
{
|
||||
if (fast_sigblock)
|
||||
thr_signal_block_fast(curthread);
|
||||
else
|
||||
thr_signal_block_slow(curthread);
|
||||
}
|
||||
|
||||
void
|
||||
_thr_signal_unblock(struct pthread *curthread)
|
||||
{
|
||||
if (fast_sigblock)
|
||||
thr_signal_unblock_fast(curthread);
|
||||
else
|
||||
thr_signal_unblock_slow(curthread);
|
||||
}
|
||||
|
||||
void
|
||||
_thr_signal_block_check_fast(void)
|
||||
{
|
||||
int bsdflags, error;
|
||||
|
||||
error = elf_aux_info(AT_BSDFLAGS, &bsdflags, sizeof(bsdflags));
|
||||
if (error != 0)
|
||||
return;
|
||||
fast_sigblock = (bsdflags & ELF_BSDF_SIGFASTBLK) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
_thr_signal_block_setup(struct pthread *curthread)
|
||||
{
|
||||
if (!fast_sigblock)
|
||||
return;
|
||||
__sys_sigfastblock(SIGFASTBLOCK_SETPTR, &curthread->fsigblock);
|
||||
}
|
||||
|
||||
int
|
||||
_thr_send_sig(struct pthread *thread, int sig)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user