about summary refs log tree commit diff
path: root/src/signal
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2013-04-26 19:48:01 -0400
committerRich Felker <dalias@aerifal.cx>2013-04-26 19:48:01 -0400
commit2c074b0d6cb2b28c5d1c0ccb2809965f4676efeb (patch)
tree9c56db36bf3ae26450e8374bb38f181b787ae707 /src/signal
parentd53c92c972dab717f8f8e521eb0e9c4404cef4bd (diff)
downloadmusl-2c074b0d6cb2b28c5d1c0ccb2809965f4676efeb.tar.gz
musl-2c074b0d6cb2b28c5d1c0ccb2809965f4676efeb.tar.xz
musl-2c074b0d6cb2b28c5d1c0ccb2809965f4676efeb.zip
transition to using functions for internal signal blocking/restoring
there are several reasons for this change. one is getting rid of the
repetition of the syscall signature all over the place. another is
sharing the constant masks without costly GOT accesses in PIC.

the main motivation, however, is accurately representing whether we
want to block signals that might be handled by the application, or all
signals.
Diffstat (limited to 'src/signal')
-rw-r--r--src/signal/block.c44
-rw-r--r--src/signal/raise.c4
-rw-r--r--src/signal/siglongjmp.c4
3 files changed, 48 insertions, 4 deletions
diff --git a/src/signal/block.c b/src/signal/block.c
new file mode 100644
index 00000000..d7f61001
--- /dev/null
+++ b/src/signal/block.c
@@ -0,0 +1,44 @@
+#include "pthread_impl.h"
+#include "syscall.h"
+#include <signal.h>
+
+static const unsigned long all_mask[] = {
+#if ULONG_MAX == 0xffffffff && _NSIG == 129
+	-1UL, -1UL, -1UL, -1UL
+#elif ULONG_MAX == 0xffffffff
+	-1UL, -1UL
+#else
+	-1UL
+#endif
+};
+
+static const unsigned long app_mask[] = {
+#if ULONG_MAX == 0xffffffff
+#if _NSIG == 65
+	0x7fffffff, 0xfffffffc
+#else
+	0x7fffffff, 0xfffffffc, -1UL, -1UL
+#endif
+#else
+#if _NSIG == 65
+	0xfffffffc7fffffff
+#else
+	0xfffffffc7fffffff, -1UL
+#endif
+#endif
+};
+
+void __block_all_sigs(void *set)
+{
+	__syscall(SYS_rt_sigprocmask, SIG_BLOCK, &all_mask, set, _NSIG/8);
+}
+
+void __block_app_sigs(void *set)
+{
+	__syscall(SYS_rt_sigprocmask, SIG_BLOCK, &app_mask, set, _NSIG/8);
+}
+
+void __restore_sigs(void *set)
+{
+	__syscall(SYS_rt_sigprocmask, SIG_SETMASK, set, 0, _NSIG/8);
+}
diff --git a/src/signal/raise.c b/src/signal/raise.c
index b24dc741..6fa43bef 100644
--- a/src/signal/raise.c
+++ b/src/signal/raise.c
@@ -8,10 +8,10 @@ int raise(int sig)
 {
 	int pid, tid, ret;
 	sigset_t set;
-	__syscall(SYS_rt_sigprocmask, SIG_BLOCK, SIGALL_SET, &set, _NSIG/8);
+	__block_app_sigs(&set);
 	tid = __syscall(SYS_gettid);
 	pid = __syscall(SYS_getpid);
 	ret = syscall(SYS_tgkill, pid, tid, sig);
-	__syscall(SYS_rt_sigprocmask, SIG_SETMASK, &set, 0, _NSIG/8);
+	__restore_sigs(&set);
 	return ret;
 }
diff --git a/src/signal/siglongjmp.c b/src/signal/siglongjmp.c
index bbdde796..a7bcca24 100644
--- a/src/signal/siglongjmp.c
+++ b/src/signal/siglongjmp.c
@@ -2,10 +2,10 @@
 #include <signal.h>
 #include <stdlib.h>
 #include "syscall.h"
+#include "pthread_impl.h"
 
 _Noreturn void siglongjmp(sigjmp_buf buf, int ret)
 {
-	if (buf->__fl) __syscall(SYS_rt_sigprocmask, SIG_SETMASK,
-		buf->__ss, 0, _NSIG/8);
+	if (buf->__fl) __restore_sigs(buf->__ss);
 	longjmp(buf->__jb, ret);
 }