jmp_buf overhaul fixing several issues
authorRich Felker <dalias@aerifal.cx>
Wed, 4 Jul 2012 00:07:33 +0000 (20:07 -0400)
committerRich Felker <dalias@aerifal.cx>
Wed, 4 Jul 2012 00:07:33 +0000 (20:07 -0400)
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.

arch/arm/bits/setjmp.h
arch/i386/bits/setjmp.h
arch/x86_64/bits/setjmp.h
include/setjmp.h
src/signal/siglongjmp.c
src/signal/sigsetjmp.c

index a4baec4c7b70291976b791ed5f9303ede1dc0d90..3938cb8a4f45e2df710cfbab81c3c3f28b3167c3 100644 (file)
@@ -1 +1 @@
-typedef unsigned long jmp_buf [64];
+typedef unsigned long long jmp_buf[32];
index b6595bd2add143784858df41ca3a922a64696b07..5610be9bc82baebbd3ae1b11a36ad1171856ac38 100644 (file)
@@ -1 +1 @@
-typedef unsigned long jmp_buf [7];
+typedef unsigned long jmp_buf[6];
index c5b9e4af5c5ea8a760139d4bba289efde3353d74..81d4968a1fcc5b8116a53e198bce1c094d3b48ae 100644 (file)
@@ -1 +1 @@
-typedef unsigned long jmp_buf [9];
+typedef unsigned long jmp_buf[8];
index 83ad74912304f1a8d74670e03ceff2f20cd17ec8..28ff92e402b60daa14bcde580e868219ff413caf 100644 (file)
@@ -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
index 600d560c875c48d5b070d06a2e3f188765ddea67..9b4a5398cc72add3efbb36b60f7590aa22ce51b3 100644 (file)
@@ -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);
 }
index 5c9370740e43e57c5c1997ee6a8ed34bbcec6d58..01ba0dffeddf4f7502c4db31fc251f1bdb00226a 100644 (file)
@@ -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);
 }