diff --git a/libc/include/bits/setjmp-types.h b/libc/include/bits/setjmp-types.h index 439f7a38..386fb876 100644 --- a/libc/include/bits/setjmp-types.h +++ b/libc/include/bits/setjmp-types.h @@ -5,6 +5,7 @@ #include #include +#include #ifndef _SETJMP_H #error "Never use bits/setjmp-types.h directly; include setjmp.h instead." @@ -12,7 +13,13 @@ #ifdef __libc_arch_x86_64 typedef __u64_t jmp_buf[8]; -typedef __u64_t sigjmp_buf[8]; +typedef struct +{ + jmp_buf buf; + sigset_t set; + int saved; +} __sigjmp_buf_tag; +typedef __sigjmp_buf_tag sigjmp_buf[1]; #else #error "Unsupported architecture." #endif diff --git a/libc/include/setjmp.h b/libc/include/setjmp.h index 9538c94f..c1fe3584 100644 --- a/libc/include/setjmp.h +++ b/libc/include/setjmp.h @@ -14,13 +14,13 @@ extern "C" /* Saves the current execution state in env. */ int setjmp(jmp_buf env); - /* Right now, does the exact same thing as setjmp() (savesigs is ignored), since signals are not implemented. */ + /* Saves the current execution state (and optionally, the current signal mask) in env. */ int sigsetjmp(sigjmp_buf env, int savesigs); /* Restores the execution state saved in env by a setjmp() call. */ __noreturn void longjmp(jmp_buf env, int val); - /* Right now, does the exact same as longjmp(), since signals are not implemented. */ + /* Restores the execution state saved in env by a sigsetjmp() call. */ __noreturn void siglongjmp(sigjmp_buf env, int val); #ifdef __cplusplus diff --git a/libc/src/setjmp.cpp b/libc/src/setjmp.cpp index 2d2bf673..932a0694 100644 --- a/libc/src/setjmp.cpp +++ b/libc/src/setjmp.cpp @@ -1,14 +1,17 @@ #include +#include extern "C" { - int sigsetjmp(sigjmp_buf env, int) + int sigsetjmp(sigjmp_buf env, int savesigs) { - return setjmp(env); + if (savesigs) env->saved = 1, sigprocmask(0, nullptr, &env->set); + return setjmp(env->buf); } __noreturn void siglongjmp(sigjmp_buf env, int val) { - longjmp(env, val); + if (env->saved) sigprocmask(SIG_SETMASK, &env->set, nullptr); + longjmp(env->buf, val); } }