diff --git a/docs/32-bit-abi.md b/docs/32-bit-abi.md index 21f9b7137..0ea94d48c 100644 --- a/docs/32-bit-abi.md +++ b/docs/32-bit-abi.md @@ -59,6 +59,9 @@ to double check: In the 64-bit ABI, `off_t` is always 64-bit. +For source compatibility, the names containing `64` are also available +in the 64-bit ABI even though they're identical to the non-`64` names. + ## `sigset_t` is too small for real-time signals @@ -68,8 +71,15 @@ code. Android P (API level 28) adds `sigset64_t` and a corresponding function for every function that takes a `sigset_t` (so `sigprocmask64` takes a `sigset64_t` where `sigprocmask` takes a `sigset_t`). +On 32-bit Android, `struct sigaction` is also too small because it contains +a `sigset_t`. We also offer a `struct sigaction64` and `sigaction64` function +to work around this. + In the 64-bit ABI, `sigset_t` is the correct size for every architecture. +For source compatibility, the names containing `64` are also available +in the 64-bit ABI even though they're identical to the non-`64` names. + ## `time_t` is 32-bit diff --git a/docs/status.md b/docs/status.md index 8cef5b7d3..2666e58b4 100644 --- a/docs/status.md +++ b/docs/status.md @@ -49,11 +49,12 @@ New libc functions in P: * `iconv`/`iconv_close`/`iconv_open` (adding ) * `pthread_attr_getinheritsched`/`pthread_attr_setinheritsched`/`pthread_setschedprio` * `pthread_mutexattr_getprotocol`/`pthread_mutexattr_setprotocol` (mutex priority inheritance) + * support for `sigaction64_t` and `sigset64_t` allowing LP32 access to real-time signals * * `swab` * `syncfs` - * `%C` and `%S` support in the printf family (previously only the wprintf family supported these). - * `%mc`/`%ms`/`%m[` support in the scanf family. + * `%C` and `%S` support in the printf family (previously only the wprintf family supported these) + * `%mc`/`%ms`/`%m[` support in the scanf family New libc functions in O: * `sendto` FORTIFY support diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp index ec26a50c4..d2c99a5ca 100644 --- a/libc/bionic/abort.cpp +++ b/libc/bionic/abort.cpp @@ -67,13 +67,10 @@ void abort() { sigprocmask64(SIG_SETMASK, &mask, nullptr); inline_tgkill(pid, tid, SIGABRT); - // If SIGABRT ignored, or caught and the handler returns, + // If SIGABRT is ignored or it's caught and the handler returns, // remove the SIGABRT signal handler and raise SIGABRT again. - struct sigaction sa; - sa.sa_handler = SIG_DFL; - sa.sa_flags = SA_RESTART; - sigemptyset(&sa.sa_mask); - sigaction(SIGABRT, &sa, &sa); + struct sigaction64 sa = { .sa_handler = SIG_DFL, .sa_flags = SA_RESTART }; + sigaction64(SIGABRT, &sa, nullptr); sigprocmask64(SIG_SETMASK, &mask, nullptr); inline_tgkill(pid, tid, SIGABRT); diff --git a/libc/bionic/sigaction.cpp b/libc/bionic/sigaction.cpp index 0633748bf..e5a7d5f2c 100644 --- a/libc/bionic/sigaction.cpp +++ b/libc/bionic/sigaction.cpp @@ -27,6 +27,7 @@ */ #include +#include extern "C" void __restore_rt(void); extern "C" void __restore(void); @@ -75,28 +76,49 @@ int sigaction(int signal, const struct sigaction* bionic_new_action, struct siga return result; } +__strong_alias(sigaction64, sigaction); + #else +extern "C" int __rt_sigaction(int, const struct sigaction64*, struct sigaction64*, size_t); extern "C" int __sigaction(int, const struct sigaction*, struct sigaction*); -int sigaction(int signal, const struct sigaction* bionic_new_action, struct sigaction* bionic_old_action) { +int sigaction(int signal, const struct sigaction* bionic_new, struct sigaction* bionic_old) { // The 32-bit ABI is broken. struct sigaction includes a too-small sigset_t, - // so we have to use sigaction(2) rather than rt_sigaction(2). - struct sigaction kernel_new_action; - if (bionic_new_action != NULL) { - kernel_new_action.sa_flags = bionic_new_action->sa_flags; - kernel_new_action.sa_handler = bionic_new_action->sa_handler; - kernel_new_action.sa_mask = bionic_new_action->sa_mask; -#if defined(SA_RESTORER) - kernel_new_action.sa_restorer = bionic_new_action->sa_restorer; - - if (!(kernel_new_action.sa_flags & SA_RESTORER)) { - kernel_new_action.sa_flags |= SA_RESTORER; - kernel_new_action.sa_restorer = (kernel_new_action.sa_flags & SA_SIGINFO) ? &__restore_rt : &__restore; - } -#endif + // so we have to translate to struct sigaction64 first. + struct sigaction64 kernel_new; + if (bionic_new) { + kernel_new = {}; + kernel_new.sa_flags = bionic_new->sa_flags; + kernel_new.sa_handler = bionic_new->sa_handler; + memcpy(&kernel_new.sa_mask, &bionic_new->sa_mask, sizeof(bionic_new->sa_mask)); } - return __sigaction(signal, (bionic_new_action != NULL) ? &kernel_new_action : NULL, bionic_old_action); + + struct sigaction64 kernel_old; + int result = sigaction64(signal, bionic_new ? &kernel_new : nullptr, &kernel_old); + if (bionic_old) { + *bionic_old = {}; + bionic_old->sa_flags = kernel_old.sa_flags; + bionic_old->sa_handler = kernel_old.sa_handler; + memcpy(&bionic_old->sa_mask, &kernel_old.sa_mask, sizeof(bionic_old->sa_mask)); + } + return result; +} + +int sigaction64(int signal, const struct sigaction64* bionic_new, struct sigaction64* bionic_old) { + struct sigaction64 kernel_new; + if (bionic_new) { + kernel_new = *bionic_new; + if (!(kernel_new.sa_flags & SA_RESTORER)) { + kernel_new.sa_flags |= SA_RESTORER; + kernel_new.sa_restorer = (kernel_new.sa_flags & SA_SIGINFO) ? &__restore_rt : &__restore; + } + } + + return __rt_sigaction(signal, + bionic_new ? &kernel_new : nullptr, + bionic_old, + sizeof(kernel_new.sa_mask)); } #endif diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp index 099944ad8..fbfe0ce24 100644 --- a/libc/bionic/signal.cpp +++ b/libc/bionic/signal.cpp @@ -147,22 +147,19 @@ int sighold(int sig) { } int sigignore(int sig) { - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - if (sigemptyset(&sa.sa_mask) == -1) return -1; - sa.sa_handler = SIG_IGN; - return sigaction(sig, &sa, nullptr); + struct sigaction64 sa = { .sa_handler = SIG_IGN }; + return sigaction64(sig, &sa, nullptr); } int siginterrupt(int sig, int flag) { - struct sigaction act; - sigaction(sig, nullptr, &act); + struct sigaction64 act; + sigaction64(sig, nullptr, &act); if (flag) { act.sa_flags &= ~SA_RESTART; } else { act.sa_flags |= SA_RESTART; } - return sigaction(sig, &act, nullptr); + return sigaction64(sig, &act, nullptr); } template @@ -185,16 +182,8 @@ int sigismember64(const sigset64_t* set, int sig) { } __LIBC_HIDDEN__ sighandler_t _signal(int sig, sighandler_t handler, int flags) { - struct sigaction sa; - sigemptyset(&sa.sa_mask); - sa.sa_handler = handler; - sa.sa_flags = flags; - - if (sigaction(sig, &sa, &sa) == -1) { - return SIG_ERR; - } - - return sa.sa_handler; + struct sigaction64 sa = { .sa_handler = handler, .sa_flags = flags }; + return (sigaction64(sig, &sa, &sa) == -1) ? SIG_ERR : sa.sa_handler; } sighandler_t signal(int sig, sighandler_t handler) { @@ -262,15 +251,11 @@ int sigrelse(int sig) { } sighandler_t sigset(int sig, sighandler_t disp) { - struct sigaction new_sa; - if (disp != SIG_HOLD) { - memset(&new_sa, 0, sizeof(new_sa)); - new_sa.sa_handler = disp; - sigemptyset(&new_sa.sa_mask); - } + struct sigaction64 new_sa; + if (disp != SIG_HOLD) new_sa = { .sa_handler = disp }; - struct sigaction old_sa; - if (sigaction(sig, (disp == SIG_HOLD) ? nullptr : &new_sa, &old_sa) == -1) { + struct sigaction64 old_sa; + if (sigaction64(sig, (disp == SIG_HOLD) ? nullptr : &new_sa, &old_sa) == -1) { return SIG_ERR; } diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp index 7422a0bb4..fde102cb7 100644 --- a/libc/bionic/spawn.cpp +++ b/libc/bionic/spawn.cpp @@ -98,17 +98,17 @@ static void ApplyAttrs(short flags, const posix_spawnattr_t* attr) { // POSIX: "Signals set to be caught by the calling process shall be // set to the default action in the child process." bool use_sigdefault = ((flags & POSIX_SPAWN_SETSIGDEF) != 0); - const struct sigaction default_sa = { .sa_handler = SIG_DFL }; + const struct sigaction64 default_sa = { .sa_handler = SIG_DFL }; for (int s = 1; s < _NSIG; ++s) { bool reset = false; if (use_sigdefault && sigismember64(&(*attr)->sigdefault.sigset64, s)) { reset = true; } else { - struct sigaction current; - if (sigaction(s, nullptr, ¤t) == -1) _exit(127); + struct sigaction64 current; + if (sigaction64(s, nullptr, ¤t) == -1) _exit(127); reset = (current.sa_handler != SIG_IGN && current.sa_handler != SIG_DFL); } - if (reset && sigaction(s, &default_sa, nullptr) == -1) _exit(127); + if (reset && sigaction64(s, &default_sa, nullptr) == -1) _exit(127); } if ((flags & POSIX_SPAWN_SETPGROUP) != 0 && setpgid(0, (*attr)->pgroup) == -1) _exit(127); diff --git a/libc/include/signal.h b/libc/include/signal.h index 61bb395fa..2027d70cb 100644 --- a/libc/include/signal.h +++ b/libc/include/signal.h @@ -40,7 +40,8 @@ /* For 64-bit (and mips), the kernel's struct sigaction doesn't match the * POSIX one, so we need to expose our own and translate behind the scenes. * For 32-bit, we're stuck with the definitions we already shipped, - * even though they contain a sigset_t that's too small. */ + * even though they contain a sigset_t that's too small. See sigaction64. + */ #define sigaction __kernel_sigaction #include #undef sigaction @@ -89,43 +90,65 @@ typedef struct { unsigned long __bits[_KERNEL__NSIG/LONG_BIT]; } sigset64_t; #if defined(__LP64__) +#define __SIGACTION_BODY \ + int sa_flags; \ + union { \ + sighandler_t sa_handler; \ + void (*sa_sigaction)(int, struct siginfo*, void*); \ + }; \ + sigset_t sa_mask; \ + void (*sa_restorer)(void); \ + +struct sigaction { __SIGACTION_BODY }; +struct sigaction64 { __SIGACTION_BODY }; + +#undef __SIGACTION_BODY + +#elif defined(__mips__) + +#define __SIGACTION_BODY \ + int sa_flags; \ + union { \ + sighandler_t sa_handler; \ + void (*sa_sigaction)(int, struct siginfo*, void*); \ + }; \ + sigset_t sa_mask; \ + +struct sigaction { __SIGACTION_BODY }; +struct sigaction64 { __SIGACTION_BODY }; + +#undef __SIGACTION_BODY + +#else + +#undef sa_handler +#undef sa_sigaction + struct sigaction { - int sa_flags; union { sighandler_t sa_handler; void (*sa_sigaction)(int, struct siginfo*, void*); }; sigset_t sa_mask; + int sa_flags; void (*sa_restorer)(void); }; -#elif defined(__mips__) - -struct sigaction { - int sa_flags; +/* This matches the kernel's internal structure. */ +struct sigaction64 { union { sighandler_t sa_handler; - void (*sa_sigaction) (int, struct siginfo*, void*); + void (*sa_sigaction)(int, struct siginfo*, void*); }; - sigset_t sa_mask; -}; - -#else - -struct sigaction { - union { - sighandler_t _sa_handler; - void (*_sa_sigaction)(int, struct siginfo*, void*); - } _u; - sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); + sigset64_t sa_mask; }; #endif -// TODO: sigaction contains a sigset_t that's too small on LP32. int sigaction(int __signal, const struct sigaction* __new_action, struct sigaction* __old_action); +int sigaction64(int __signal, const struct sigaction64* __new_action, struct sigaction64* __old_action) __INTRODUCED_IN(28); int siginterrupt(int __signal, int __flag); @@ -191,4 +214,4 @@ __END_DECLS #include -#endif /* _SIGNAL_H_ */ +#endif diff --git a/libc/libc.arm.map b/libc/libc.arm.map index c345ba636..839c40651 100644 --- a/libc/libc.arm.map +++ b/libc/libc.arm.map @@ -1386,6 +1386,7 @@ LIBC_P { # introduced=P sethostent; setnetent; setprotoent; + sigaction64; sigaddset64; sigdelset64; sigemptyset64; diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map index 3af0d423b..a39a2334a 100644 --- a/libc/libc.arm64.map +++ b/libc/libc.arm64.map @@ -1306,6 +1306,7 @@ LIBC_P { # introduced=P sethostent; setnetent; setprotoent; + sigaction64; sigaddset64; sigdelset64; sigemptyset64; diff --git a/libc/libc.map.txt b/libc/libc.map.txt index 5c54ba105..b3bfa8a8f 100644 --- a/libc/libc.map.txt +++ b/libc/libc.map.txt @@ -1411,6 +1411,7 @@ LIBC_P { # introduced=P sethostent; setnetent; setprotoent; + sigaction64; sigaddset64; sigdelset64; sigemptyset64; diff --git a/libc/libc.mips.map b/libc/libc.mips.map index c3646085d..2a9313228 100644 --- a/libc/libc.mips.map +++ b/libc/libc.mips.map @@ -1370,6 +1370,7 @@ LIBC_P { # introduced=P sethostent; setnetent; setprotoent; + sigaction64; sigaddset64; sigdelset64; sigemptyset64; diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map index 3af0d423b..a39a2334a 100644 --- a/libc/libc.mips64.map +++ b/libc/libc.mips64.map @@ -1306,6 +1306,7 @@ LIBC_P { # introduced=P sethostent; setnetent; setprotoent; + sigaction64; sigaddset64; sigdelset64; sigemptyset64; diff --git a/libc/libc.x86.map b/libc/libc.x86.map index eec2c19cb..d2e73995e 100644 --- a/libc/libc.x86.map +++ b/libc/libc.x86.map @@ -1368,6 +1368,7 @@ LIBC_P { # introduced=P sethostent; setnetent; setprotoent; + sigaction64; sigaddset64; sigdelset64; sigemptyset64; diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map index 3af0d423b..a39a2334a 100644 --- a/libc/libc.x86_64.map +++ b/libc/libc.x86_64.map @@ -1306,6 +1306,7 @@ LIBC_P { # introduced=P sethostent; setnetent; setprotoent; + sigaction64; sigaddset64; sigdelset64; sigemptyset64; diff --git a/libc/malloc_debug/BacktraceData.cpp b/libc/malloc_debug/BacktraceData.cpp index d59728040..57d8f2afe 100644 --- a/libc/malloc_debug/BacktraceData.cpp +++ b/libc/malloc_debug/BacktraceData.cpp @@ -59,13 +59,10 @@ BacktraceData::BacktraceData(DebugData* debug_data, const Config& config, size_t bool BacktraceData::Initialize(const Config& config) { enabled_ = config.backtrace_enabled(); if (config.backtrace_enable_on_signal()) { - struct sigaction enable_act; - memset(&enable_act, 0, sizeof(enable_act)); - + struct sigaction64 enable_act = {}; enable_act.sa_sigaction = ToggleBacktraceEnable; enable_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; - sigemptyset(&enable_act.sa_mask); - if (sigaction(config.backtrace_signal(), &enable_act, nullptr) != 0) { + if (sigaction64(config.backtrace_signal(), &enable_act, nullptr) != 0) { error_log("Unable to set up backtrace signal enable function: %s", strerror(errno)); return false; } @@ -73,13 +70,10 @@ bool BacktraceData::Initialize(const Config& config) { config.backtrace_signal(), getpid()); } - struct sigaction act; - memset(&act, 0, sizeof(act)); - + struct sigaction64 act = {}; act.sa_sigaction = EnableDump; act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; - sigemptyset(&act.sa_mask); - if (sigaction(config.backtrace_dump_signal(), &act, nullptr) != 0) { + if (sigaction64(config.backtrace_dump_signal(), &act, nullptr) != 0) { error_log("Unable to set up backtrace dump signal function: %s", strerror(errno)); return false; } diff --git a/libc/malloc_debug/RecordData.cpp b/libc/malloc_debug/RecordData.cpp index 5a68deb10..55d99438d 100644 --- a/libc/malloc_debug/RecordData.cpp +++ b/libc/malloc_debug/RecordData.cpp @@ -179,13 +179,10 @@ RecordData::RecordData() { } bool RecordData::Initialize(const Config& config) { - struct sigaction dump_act; - memset(&dump_act, 0, sizeof(dump_act)); - + struct sigaction64 dump_act = {}; dump_act.sa_sigaction = RecordDump; dump_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; - sigemptyset(&dump_act.sa_mask); - if (sigaction(config.record_allocs_signal(), &dump_act, nullptr) != 0) { + if (sigaction64(config.record_allocs_signal(), &dump_act, nullptr) != 0) { error_log("Unable to set up record dump signal function: %s", strerror(errno)); return false; } diff --git a/tests/BionicDeathTest.h b/tests/BionicDeathTest.h index 3e8d7b231..6826ab72c 100644 --- a/tests/BionicDeathTest.h +++ b/tests/BionicDeathTest.h @@ -21,25 +21,28 @@ #include +#if !defined(__BIONIC__) +#define sigaction64 sigaction +#endif + class BionicDeathTest : public testing::Test { protected: virtual void SetUp() { // Suppress debuggerd stack traces. Too slow. for (int signo : { SIGABRT, SIGBUS, SIGSEGV, SIGSYS }) { - struct sigaction action = {}; - action.sa_handler = SIG_DFL; - sigaction(signo, &action, &previous_); + struct sigaction64 action = { .sa_handler = SIG_DFL }; + sigaction64(signo, &action, &previous_); } } virtual void TearDown() { for (int signo : { SIGABRT, SIGBUS, SIGSEGV, SIGSYS }) { - sigaction(signo, &previous_, nullptr); + sigaction64(signo, &previous_, nullptr); } } private: - struct sigaction previous_; + struct sigaction64 previous_; }; #endif // BIONIC_TESTS_BIONIC_DEATH_TEST_H_ diff --git a/tests/ScopedSignalHandler.h b/tests/ScopedSignalHandler.h index 85c41a87c..36bbf1077 100644 --- a/tests/ScopedSignalHandler.h +++ b/tests/ScopedSignalHandler.h @@ -26,6 +26,7 @@ #define posix_spawnattr_setsigdefault64 posix_spawnattr_setsigdefault #define posix_spawnattr_setsigmask64 posix_spawnattr_setsigmask #define pthread_sigmask64 pthread_sigmask +#define sigaction64 sigaction #define sigaddset64 sigaddset #define sigdelset64 sigdelset #define sigemptyset64 sigemptyset @@ -47,7 +48,7 @@ class ScopedSignalHandler { memset(&action_, 0, sizeof(action_)); action_.sa_flags = sa_flags; action_.sa_handler = handler; - sigaction(signal_number_, &action_, &old_action_); + sigaction64(signal_number_, &action_, &old_action_); } ScopedSignalHandler(int signal_number, void (*action)(int, siginfo_t*, void*), @@ -56,20 +57,20 @@ class ScopedSignalHandler { memset(&action_, 0, sizeof(action_)); action_.sa_flags = sa_flags; action_.sa_sigaction = action; - sigaction(signal_number_, &action_, &old_action_); + sigaction64(signal_number_, &action_, &old_action_); } ScopedSignalHandler(int signal_number) : signal_number_(signal_number) { - sigaction(signal_number, nullptr, &old_action_); + sigaction64(signal_number, nullptr, &old_action_); } ~ScopedSignalHandler() { - sigaction(signal_number_, &old_action_, NULL); + sigaction64(signal_number_, &old_action_, NULL); } private: - struct sigaction action_; - struct sigaction old_action_; + struct sigaction64 action_; + struct sigaction64 old_action_; const int signal_number_; }; diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp index ebc079e1d..87a918f4f 100644 --- a/tests/signal_test.cpp +++ b/tests/signal_test.cpp @@ -269,55 +269,63 @@ TEST(signal, sigsuspend64_sigpending64) { ASSERT_EQ(1, g_sigsuspend64_signal_handler_call_count); } -static void EmptySignalHandler(int) {} -static void EmptySignalAction(int, siginfo_t*, void*) {} - -TEST(signal, sigaction) { +template +static void TestSigAction(int (sigaction_fn)(int, const SigActionT*, SigActionT*), + int (sigaddset_fn)(SigSetT*, int), + int sig) { // Both bionic and glibc set SA_RESTORER when talking to the kernel on arm, // arm64, x86, and x86-64. The version of glibc we're using also doesn't // define SA_RESTORER, but luckily it's the same value everywhere, and mips // doesn't use the bit for anything. static const unsigned sa_restorer = 0x4000000; - // See what's currently set for SIGALRM. - struct sigaction original_sa; - memset(&original_sa, 0, sizeof(original_sa)); - ASSERT_EQ(0, sigaction(SIGALRM, NULL, &original_sa)); + // See what's currently set for this signal. + SigActionT original_sa = {}; + ASSERT_EQ(0, sigaction_fn(sig, NULL, &original_sa)); ASSERT_TRUE(original_sa.sa_handler == NULL); ASSERT_TRUE(original_sa.sa_sigaction == NULL); ASSERT_EQ(0U, original_sa.sa_flags & ~sa_restorer); // Set a traditional sa_handler signal handler. - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sigaddset(&sa.sa_mask, SIGALRM); + auto no_op_signal_handler = [](int) {}; + SigActionT sa = {}; + sigaddset_fn(&sa.sa_mask, sig); sa.sa_flags = SA_ONSTACK; - sa.sa_handler = EmptySignalHandler; - ASSERT_EQ(0, sigaction(SIGALRM, &sa, NULL)); + sa.sa_handler = no_op_signal_handler; + ASSERT_EQ(0, sigaction_fn(sig, &sa, NULL)); // Check that we can read it back. - memset(&sa, 0, sizeof(sa)); - ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa)); - ASSERT_TRUE(sa.sa_handler == EmptySignalHandler); + sa = {}; + ASSERT_EQ(0, sigaction_fn(sig, NULL, &sa)); + ASSERT_TRUE(sa.sa_handler == no_op_signal_handler); ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler); ASSERT_EQ(static_cast(SA_ONSTACK), sa.sa_flags & ~sa_restorer); // Set a new-style sa_sigaction signal handler. - memset(&sa, 0, sizeof(sa)); - sigaddset(&sa.sa_mask, SIGALRM); + auto no_op_sigaction = [](int, siginfo_t*, void*) {}; + sa = {}; + sigaddset_fn(&sa.sa_mask, sig); sa.sa_flags = SA_ONSTACK | SA_SIGINFO; - sa.sa_sigaction = EmptySignalAction; - ASSERT_EQ(0, sigaction(SIGALRM, &sa, NULL)); + sa.sa_sigaction = no_op_sigaction; + ASSERT_EQ(0, sigaction_fn(sig, &sa, NULL)); // Check that we can read it back. - memset(&sa, 0, sizeof(sa)); - ASSERT_EQ(0, sigaction(SIGALRM, NULL, &sa)); - ASSERT_TRUE(sa.sa_sigaction == EmptySignalAction); + sa = {}; + ASSERT_EQ(0, sigaction_fn(sig, NULL, &sa)); + ASSERT_TRUE(sa.sa_sigaction == no_op_sigaction); ASSERT_TRUE((void*) sa.sa_sigaction == (void*) sa.sa_handler); ASSERT_EQ(static_cast(SA_ONSTACK | SA_SIGINFO), sa.sa_flags & ~sa_restorer); // Put everything back how it was. - ASSERT_EQ(0, sigaction(SIGALRM, &original_sa, NULL)); + ASSERT_EQ(0, sigaction_fn(sig, &original_sa, NULL)); +} + +TEST(signal, sigaction) { + TestSigAction(sigaction, sigaddset, SIGALRM); +} + +TEST(signal, sigaction64_SIGRTMIN) { + TestSigAction(sigaction64, sigaddset64, SIGRTMIN); } TEST(signal, sys_signame) { @@ -495,8 +503,7 @@ TEST(signal, rt_tgsigqueueinfo) { "* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=66dd34ad31e5963d72a700ec3f2449291d322921\n"; static siginfo received; - struct sigaction handler; - memset(&handler, 0, sizeof(handler)); + struct sigaction handler = {}; handler.sa_sigaction = [](int, siginfo_t* siginfo, void*) { received = *siginfo; }; handler.sa_flags = SA_SIGINFO;