mirror of
https://github.com/fluencelabs/musl
synced 2025-06-22 19:21:58 +00:00
fix issue with longjmp out of signal handlers and cancellation
stale state information indicating that a thread was possibly blocked at a cancellation point could get left behind if longjmp was used to exit a signal handler that interrupted a cancellation point. to fix the issue, we throw away the state information entirely and simply compare the saved instruction pointer to a range of code addresses in the __syscall_cp_asm function. all the ugly PIC work (which becomes minimal anyway with this approach) is defered to cancellation time instead of happening at every syscall, which should improve performance too. this commit also fixes cancellation on arm, which was mildly broken (race condition, not checking cancellation flag once inside the cancellation point zone). apparently i forgot to implement that. the new arm code is untested, but appears correct; i'll test and fix it later if there are problems.
This commit is contained in:
@ -3,20 +3,18 @@
|
|||||||
__syscall_cp_asm:
|
__syscall_cp_asm:
|
||||||
mov ip,sp
|
mov ip,sp
|
||||||
stmfd sp!,{r4,r5,r6,r7,lr}
|
stmfd sp!,{r4,r5,r6,r7,lr}
|
||||||
stmfd sp!,{r0}
|
.global __cp_begin
|
||||||
bl 1f
|
__cp_begin:
|
||||||
1: mov r4,#(1f-.)
|
ld r0,[r0]
|
||||||
add r4,r4,lr
|
cmp r0,#0
|
||||||
str r4,[r0,#4]
|
blne __cancel
|
||||||
str sp,[r0]
|
|
||||||
mov r7,r1
|
mov r7,r1
|
||||||
mov r0,r2
|
mov r0,r2
|
||||||
mov r1,r3
|
mov r1,r3
|
||||||
ldmfd ip,{r2,r3,r4,r5,r6}
|
ldmfd ip,{r2,r3,r4,r5,r6}
|
||||||
1: svc 0
|
svc 0
|
||||||
ldmfd sp!,{r1}
|
.global __cp_end
|
||||||
mov r2,#0
|
__cp_end:
|
||||||
str r2,[r1]
|
|
||||||
ldmfd sp!,{r4,r5,r6,r7,lr}
|
ldmfd sp!,{r4,r5,r6,r7,lr}
|
||||||
tst lr,#1
|
tst lr,#1
|
||||||
moveq pc,lr
|
moveq pc,lr
|
||||||
|
@ -14,19 +14,12 @@ long __syscall_cp_asm(volatile void *, long, long, long, long, long, long, long)
|
|||||||
long (__syscall_cp)(long nr, long u, long v, long w, long x, long y, long z)
|
long (__syscall_cp)(long nr, long u, long v, long w, long x, long y, long z)
|
||||||
{
|
{
|
||||||
pthread_t self;
|
pthread_t self;
|
||||||
uintptr_t old_sp, old_ip;
|
|
||||||
long r;
|
long r;
|
||||||
|
|
||||||
if (!libc.main_thread || (self = __pthread_self())->canceldisable)
|
if (!libc.main_thread || (self = __pthread_self())->canceldisable)
|
||||||
return __syscall(nr, u, v, w, x, y, z);
|
return __syscall(nr, u, v, w, x, y, z);
|
||||||
|
|
||||||
old_sp = self->cp_sp;
|
r = __syscall_cp_asm(&self->cancel, nr, u, v, w, x, y, z);
|
||||||
old_ip = self->cp_ip;
|
|
||||||
self->cp_sp = 0;
|
|
||||||
self->cp_ip = 0;
|
|
||||||
r = __syscall_cp_asm(&self->cp_sp, nr, u, v, w, x, y, z);
|
|
||||||
self->cp_ip = old_ip;
|
|
||||||
self->cp_sp = old_sp;
|
|
||||||
if (r==-EINTR && nr!=SYS_close && self->cancel && !self->canceldisable)
|
if (r==-EINTR && nr!=SYS_close && self->cancel && !self->canceldisable)
|
||||||
__cancel();
|
__cancel();
|
||||||
return r;
|
return r;
|
||||||
@ -42,14 +35,14 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
|
|||||||
{
|
{
|
||||||
pthread_t self = __pthread_self();
|
pthread_t self = __pthread_self();
|
||||||
ucontext_t *uc = ctx;
|
ucontext_t *uc = ctx;
|
||||||
uintptr_t sp = ((uintptr_t *)&uc->uc_mcontext)[CANCEL_REG_SP];
|
const char *ip = ((char **)&uc->uc_mcontext)[CANCEL_REG_IP];
|
||||||
uintptr_t ip = ((uintptr_t *)&uc->uc_mcontext)[CANCEL_REG_IP];
|
extern const char __cp_begin[1], __cp_end[1];
|
||||||
|
|
||||||
if (!self->cancel || self->canceldisable) return;
|
if (!self->cancel || self->canceldisable) return;
|
||||||
|
|
||||||
_sigaddset(&uc->uc_sigmask, SIGCANCEL);
|
_sigaddset(&uc->uc_sigmask, SIGCANCEL);
|
||||||
|
|
||||||
if (self->cancelasync || sp == self->cp_sp && ip <= self->cp_ip) {
|
if (self->cancelasync || ip >= __cp_begin && ip < __cp_end) {
|
||||||
self->canceldisable = 1;
|
self->canceldisable = 1;
|
||||||
pthread_sigmask(SIG_SETMASK, &uc->uc_sigmask, 0);
|
pthread_sigmask(SIG_SETMASK, &uc->uc_sigmask, 0);
|
||||||
__cancel();
|
__cancel();
|
||||||
|
@ -2,34 +2,28 @@
|
|||||||
.global __syscall_cp_asm
|
.global __syscall_cp_asm
|
||||||
.type __syscall_cp_asm,@function
|
.type __syscall_cp_asm,@function
|
||||||
__syscall_cp_asm:
|
__syscall_cp_asm:
|
||||||
|
mov 4(%esp),%ecx
|
||||||
pushl %ebx
|
pushl %ebx
|
||||||
pushl %esi
|
pushl %esi
|
||||||
pushl %edi
|
pushl %edi
|
||||||
pushl %ebp
|
pushl %ebp
|
||||||
leal 20(%esp),%ebp
|
.global __cp_begin
|
||||||
call 1f
|
__cp_begin:
|
||||||
1: popl %eax
|
movl (%ecx),%eax
|
||||||
movl (%ebp),%ecx
|
|
||||||
addl $[1f-1b],%eax
|
|
||||||
movl %eax,4(%ecx)
|
|
||||||
movl %esp,(%ecx)
|
|
||||||
movl 8(%ecx),%eax
|
|
||||||
testl %eax,%eax
|
testl %eax,%eax
|
||||||
jnz 2f
|
jnz __cancel
|
||||||
movl 4(%ebp),%eax
|
movl 24(%esp),%eax
|
||||||
movl 8(%ebp),%ebx
|
movl 28(%esp),%ebx
|
||||||
movl 12(%ebp),%ecx
|
movl 32(%esp),%ecx
|
||||||
movl 16(%ebp),%edx
|
movl 36(%esp),%edx
|
||||||
movl 20(%ebp),%esi
|
movl 40(%esp),%esi
|
||||||
movl 24(%ebp),%edi
|
movl 44(%esp),%edi
|
||||||
movl 28(%ebp),%ebp
|
movl 48(%esp),%ebp
|
||||||
1: int $128
|
int $128
|
||||||
|
.global __cp_end
|
||||||
|
__cp_end:
|
||||||
popl %ebp
|
popl %ebp
|
||||||
popl %edi
|
popl %edi
|
||||||
popl %esi
|
popl %esi
|
||||||
popl %ebx
|
popl %ebx
|
||||||
xorl %edx,%edx
|
|
||||||
movl 4(%esp),%ecx
|
|
||||||
movl %edx,(%ecx)
|
|
||||||
ret
|
ret
|
||||||
2: call __cancel
|
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
.global __syscall_cp_asm
|
.global __syscall_cp_asm
|
||||||
.type __syscall_cp_asm,@function
|
.type __syscall_cp_asm,@function
|
||||||
__syscall_cp_asm:
|
__syscall_cp_asm:
|
||||||
lea 1f(%rip),%rax
|
|
||||||
mov %rax,8(%rdi)
|
.global __cp_begin
|
||||||
mov %rsp,(%rdi)
|
__cp_begin:
|
||||||
mov 16(%rdi),%eax
|
mov (%rdi),%eax
|
||||||
test %eax,%eax
|
test %eax,%eax
|
||||||
jnz 2f
|
jnz __cancel
|
||||||
mov %rdi,%r11
|
mov %rdi,%r11
|
||||||
mov %rsi,%rax
|
mov %rsi,%rax
|
||||||
mov %rdx,%rdi
|
mov %rdx,%rdi
|
||||||
@ -17,9 +17,7 @@ __syscall_cp_asm:
|
|||||||
mov 8(%rsp),%r8
|
mov 8(%rsp),%r8
|
||||||
mov 16(%rsp),%r9
|
mov 16(%rsp),%r9
|
||||||
mov %r11,8(%rsp)
|
mov %r11,8(%rsp)
|
||||||
1: syscall
|
syscall
|
||||||
xor %ecx,%ecx
|
.global __cp_end
|
||||||
mov 8(%rsp),%rdi
|
__cp_end:
|
||||||
mov %rcx,(%rdi)
|
|
||||||
ret
|
ret
|
||||||
2: call __cancel
|
|
||||||
|
Reference in New Issue
Block a user