diff options
author | Rich Felker <dalias@aerifal.cx> | 2012-07-03 20:07:33 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2012-07-03 20:07:33 -0400 |
commit | d6c0efe106b1016108207fb6872820c06dcef4f8 (patch) | |
tree | 700300d0b4ff576121241befdcf865678cde4e5c | |
parent | e6129e6d836e5f4725d9b14ba7457b32e24adc61 (diff) | |
download | musl-d6c0efe106b1016108207fb6872820c06dcef4f8.tar.gz musl-d6c0efe106b1016108207fb6872820c06dcef4f8.tar.bz2 musl-d6c0efe106b1016108207fb6872820c06dcef4f8.tar.xz musl-d6c0efe106b1016108207fb6872820c06dcef4f8.zip |
jmp_buf overhaul fixing several issues
on arm, the location of the saved-signal-mask flag and mask were off
by one between sigsetjmp and siglongjmp, causing incorrect behavior
restoring the signal mask. this is because the siglongjmp code assumed
an extra slot was in the non-sig jmp_buf for the flag, but arm did not
have this. now, the extra slot is removed for all archs since it was
useless.
also, arm eabi requires jmp_buf to have 8-byte alignment. we achieve
that using long long as the type rather than with non-portable gcc
attribute tags.
-rw-r--r-- | arch/arm/bits/setjmp.h | 2 | ||||
-rw-r--r-- | arch/i386/bits/setjmp.h | 2 | ||||
-rw-r--r-- | arch/x86_64/bits/setjmp.h | 2 | ||||
-rw-r--r-- | include/setjmp.h | 6 | ||||
-rw-r--r-- | src/signal/siglongjmp.c | 9 | ||||
-rw-r--r-- | src/signal/sigsetjmp.c | 8 |
6 files changed, 15 insertions, 14 deletions
diff --git a/arch/arm/bits/setjmp.h b/arch/arm/bits/setjmp.h index a4baec4c..3938cb8a 100644 --- a/arch/arm/bits/setjmp.h +++ b/arch/arm/bits/setjmp.h @@ -1 +1 @@ -typedef unsigned long jmp_buf [64]; +typedef unsigned long long jmp_buf[32]; diff --git a/arch/i386/bits/setjmp.h b/arch/i386/bits/setjmp.h index b6595bd2..5610be9b 100644 --- a/arch/i386/bits/setjmp.h +++ b/arch/i386/bits/setjmp.h @@ -1 +1 @@ -typedef unsigned long jmp_buf [7]; +typedef unsigned long jmp_buf[6]; diff --git a/arch/x86_64/bits/setjmp.h b/arch/x86_64/bits/setjmp.h index c5b9e4af..81d4968a 100644 --- a/arch/x86_64/bits/setjmp.h +++ b/arch/x86_64/bits/setjmp.h @@ -1 +1 @@ -typedef unsigned long jmp_buf [9]; +typedef unsigned long jmp_buf[8]; diff --git a/include/setjmp.h b/include/setjmp.h index 83ad7491..28ff92e4 100644 --- a/include/setjmp.h +++ b/include/setjmp.h @@ -11,7 +11,11 @@ extern "C" { #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ || defined(_BSD_SOURCE) -typedef unsigned long sigjmp_buf[(128+sizeof(jmp_buf))/sizeof(long)]; +typedef struct { + jmp_buf __jb; + unsigned long __fl; + unsigned long __ss[128]; +} sigjmp_buf[1]; int sigsetjmp (sigjmp_buf, int); void siglongjmp (sigjmp_buf, int); #endif diff --git a/src/signal/siglongjmp.c b/src/signal/siglongjmp.c index 600d560c..9b4a5398 100644 --- a/src/signal/siglongjmp.c +++ b/src/signal/siglongjmp.c @@ -1,12 +1,11 @@ #include <setjmp.h> #include <signal.h> #include <stdlib.h> +#include "syscall.h" void siglongjmp(sigjmp_buf buf, int ret) { - unsigned long *flag = buf + sizeof(jmp_buf)/sizeof(long) - 1; - sigset_t *mask = (void *)(flag + 1); - if (*flag) - sigprocmask (SIG_SETMASK, mask, NULL); - longjmp((void *)buf, ret); + if (buf->__fl) + __syscall(SYS_rt_sigprocmask, SIG_SETMASK, buf->__ss, 0, 8); + longjmp(buf->__jb, ret); } diff --git a/src/signal/sigsetjmp.c b/src/signal/sigsetjmp.c index 5c937074..01ba0dff 100644 --- a/src/signal/sigsetjmp.c +++ b/src/signal/sigsetjmp.c @@ -9,9 +9,7 @@ int sigsetjmp(sigjmp_buf buf, int save) { - unsigned long *flag = buf + sizeof(jmp_buf)/sizeof(long); - sigset_t *mask = (void *)(flag + 1); - if ((*flag = save)) - sigprocmask (SIG_SETMASK, NULL, mask); - return setjmp((void *)buf); + if ((buf->__fl = save)) + pthread_sigmask(SIG_SETMASK, 0, (sigset_t *)buf->__ss); + return setjmp(buf->__jb); } |