int sigaction(int signal, const struct sigaction* bionic_new_action, struct sigaction* bionic_old_action) { #if __LP64__ __kernel_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; 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 = &__rt_sigreturn; } } __kernel_sigaction kernel_old_action; int result = __rt_sigaction(signal, (bionic_new_action != NULL) ? &kernel_new_action : NULL, (bionic_old_action != NULL) ? &kernel_old_action : NULL, sizeof(sigset_t)); if (bionic_old_action != NULL) { bionic_old_action->sa_flags = kernel_old_action.sa_flags; bionic_old_action->sa_handler = kernel_old_action.sa_handler; bionic_old_action->sa_mask = kernel_old_action.sa_mask; bionic_old_action->sa_restorer = kernel_old_action.sa_restorer; if (bionic_old_action->sa_restorer == &__rt_sigreturn) { bionic_old_action->sa_flags &= ~SA_RESTORER; } } return result; #else // The 32-bit ABI is broken. struct sigaction includes a too-small sigset_t. // TODO: if we also had correct struct sigaction definitions available, we could copy in and out. return __sigaction(signal, bionic_new_action, bionic_old_action); #endif }
int sigaction(int signal, const struct sigaction* bionic_new_action, struct sigaction* bionic_old_action) { __kernel_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 defined(__aarch64__) // arm64 has sa_restorer, but unwinding works best if you just let the // kernel supply the default restorer from [vdso]. gdb doesn't care, but // libgcc needs the nop that the kernel includes before the actual code. // (We could add that ourselves, but why bother?) #else if (!(kernel_new_action.sa_flags & SA_RESTORER)) { kernel_new_action.sa_flags |= SA_RESTORER; kernel_new_action.sa_restorer = &__restore_rt; } #endif #endif } __kernel_sigaction kernel_old_action; int result = __rt_sigaction(signal, (bionic_new_action != NULL) ? &kernel_new_action : NULL, (bionic_old_action != NULL) ? &kernel_old_action : NULL, sizeof(sigset_t)); if (bionic_old_action != NULL) { bionic_old_action->sa_flags = kernel_old_action.sa_flags; bionic_old_action->sa_handler = kernel_old_action.sa_handler; bionic_old_action->sa_mask = kernel_old_action.sa_mask; #if defined(SA_RESTORER) bionic_old_action->sa_restorer = kernel_old_action.sa_restorer; #endif } return result; }
int __libc_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) { return __rt_sigaction(signum, act, oldact, 0, _NSIG/8); }