mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 07:29:23 +00:00
Fix backtraces on cancellation points
This commit is contained in:
parent
022536cab6
commit
0d7c265392
4 changed files with 22 additions and 13 deletions
|
@ -948,9 +948,9 @@ static dontdiscard __asan_die_f *__asan_report_memory_fault(
|
|||
static void *__asan_morgue_add(void *p) {
|
||||
return atomic_exchange_explicit(
|
||||
__asan_morgue.p + (atomic_fetch_add_explicit(&__asan_morgue.i, 1,
|
||||
memory_order_acquire) &
|
||||
memory_order_acq_rel) &
|
||||
(ARRAYLEN(__asan_morgue.p) - 1)),
|
||||
p, memory_order_release);
|
||||
p, memory_order_acq_rel);
|
||||
}
|
||||
|
||||
static void __asan_morgue_flush(void) {
|
||||
|
|
|
@ -53,7 +53,6 @@ static ssize_t GetDevRandom(char *p, size_t n) {
|
|||
pthread_cleanup_push((void *)sys_close, (void *)(intptr_t)fd);
|
||||
rc = sys_read(fd, p, n);
|
||||
pthread_cleanup_pop(1);
|
||||
close(fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,9 @@ __pid: .quad 0
|
|||
.endobj __pid,globl,hidden
|
||||
.previous
|
||||
|
||||
systemfive_cp:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
systemfive_cancellable: # our pthread_cancel() miracle code
|
||||
cmpb $0,__tls_enabled(%rip) # inspired by the musl libc design!
|
||||
je 1f # we handle linux and bsd together!
|
||||
|
@ -118,12 +121,12 @@ systemfive_cancellable: # our pthread_cancel() miracle code
|
|||
testb $PT_NOCANCEL,0x00(%r10) # PosixThread::flags
|
||||
jnz 1f # canceler no cancelling
|
||||
cmp $0,0x04(%r10) # PosixThread::cancelled
|
||||
jne _pthread_cancel_sys # tail call for masked mode
|
||||
.weak _pthread_cancel_sys # must be linked if we're cancelled
|
||||
jne systemfive_cancel # tail call for masked mode
|
||||
1: mov %rcx,%r10 # move the fourth argument
|
||||
clc # no cancellable system calls exist
|
||||
syscall # that have 7+ args on the bsd OSes
|
||||
systemfive_cancellable_end: # i/o calls park here for long time
|
||||
pop %rbp
|
||||
jc systemfive_errno
|
||||
jmp 0f
|
||||
jc 3f # we're now out of the limbo state!
|
||||
|
@ -143,10 +146,15 @@ systemfive_cancellable_end: # i/o calls park here for long time
|
|||
jnz systemfive_errno # cancellation is disabled
|
||||
cmp $0,0x04(%rcx) # PosixThread::cancelled
|
||||
je systemfive_errno # we aren't actually cancelled
|
||||
jmp _pthread_cancel_sys # now we are in fact cancelled
|
||||
.endfn systemfive_cancellable,globl,hidden
|
||||
jmp 1f # now we are in fact cancelled
|
||||
systemfive_cancel:
|
||||
pop %rbp
|
||||
1: jmp _pthread_cancel_sys # must be linked if we're cancelled
|
||||
.weak _pthread_cancel_sys
|
||||
.globl systemfive_cancellable_end
|
||||
.hidden systemfive_cancellable_end
|
||||
.globl systemfive_cancellable
|
||||
.globl systemfive_cancel
|
||||
.endfn systemfive_cp
|
||||
|
||||
.Lanchorpoint:
|
||||
#if SupportsLinux() || SupportsMetal()
|
||||
|
@ -155,7 +163,7 @@ systemfive_linux:
|
|||
cmp $0xfff,%eax # checks if unsupported by platform
|
||||
je systemfive_enosys # never taken branches cost nothing
|
||||
btr $11,%eax # 0x800 means a call is cancellable
|
||||
jc systemfive_cancellable # it is handled by the holiest code
|
||||
jc systemfive_cp # it is handled by the holiest code
|
||||
mov %rcx,%r10 # syscall instruction clobbers %rcx
|
||||
push %rbp # linux never reads args from stack
|
||||
mov %rsp,%rbp # having frame will help backtraces
|
||||
|
@ -210,7 +218,7 @@ systemfive_bsd:
|
|||
cmp $0xfff,%ax
|
||||
je systemfive_enosys
|
||||
btr $11,%eax # checks/reset the 800 cancellable bit
|
||||
jc systemfive_cancellable
|
||||
jc systemfive_cp
|
||||
mov %rcx,%r10
|
||||
syscall # bsd will need arg on stack sometimes
|
||||
jc systemfive_errno # bsd sets carry flag if %rax is errno
|
||||
|
|
|
@ -34,8 +34,10 @@
|
|||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
extern const char systemfive_cancellable[] hidden;
|
||||
extern const char systemfive_cancellable_end[] hidden;
|
||||
int systemfive_cancel(void);
|
||||
|
||||
extern const char systemfive_cancellable[];
|
||||
extern const char systemfive_cancellable_end[];
|
||||
|
||||
int _pthread_cancel_sys(void) {
|
||||
struct PosixThread *pt;
|
||||
|
@ -57,7 +59,7 @@ static void OnSigCancel(int sig, siginfo_t *si, void *ctx) {
|
|||
if ((pt->flags & PT_ASYNC) ||
|
||||
(systemfive_cancellable <= (char *)uc->uc_mcontext.rip &&
|
||||
(char *)uc->uc_mcontext.rip < systemfive_cancellable_end)) {
|
||||
uc->uc_mcontext.rip = (intptr_t)_pthread_cancel_sys;
|
||||
uc->uc_mcontext.rip = (intptr_t)systemfive_cancel;
|
||||
} else {
|
||||
tkill(atomic_load_explicit(&tib->tib_tid, memory_order_relaxed), sig);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue