diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt index 76307b0b5733..7e1a8974fa48 100644 --- a/libc/hdr/types/CMakeLists.txt +++ b/libc/hdr/types/CMakeLists.txt @@ -79,6 +79,14 @@ add_proxy_header_library( libc.include.llvm-libc-types.sigset_t ) +add_proxy_header_library( + siginfo_t + HDRS + siginfo_t.h + FULL_BUILD_DEPENDS + libc.include.llvm-libc-types.siginfo_t +) + add_proxy_header_library( struct_epoll_event HDRS diff --git a/libc/hdr/types/siginfo_t.h b/libc/hdr/types/siginfo_t.h new file mode 100644 index 000000000000..469738c94167 --- /dev/null +++ b/libc/hdr/types/siginfo_t.h @@ -0,0 +1,21 @@ +//===-- Proxy for siginfo_t -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIBC_HDR_TYPES_SIGINFO_T_H +#define LLVM_LIBC_HDR_TYPES_SIGINFO_T_H + +#ifdef LIBC_FULL_BUILD + +#include "include/llvm-libc-types/siginfo_t.h" + +#else + +#include + +#endif // LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_TYPES_SIGINFO_T_H diff --git a/libc/src/signal/linux/CMakeLists.txt b/libc/src/signal/linux/CMakeLists.txt index c8a7d95a4f22..44c41737b89b 100644 --- a/libc/src/signal/linux/CMakeLists.txt +++ b/libc/src/signal/linux/CMakeLists.txt @@ -3,10 +3,14 @@ add_header_library( HDRS signal_utils.h DEPENDS + libc.hdr.types.siginfo_t libc.hdr.types.sigset_t - libc.include.signal + libc.hdr.types.size_t + libc.hdr.types.struct_sigaction libc.include.sys_syscall + libc.src.__support.OSUtil.linux.vdso libc.src.__support.OSUtil.osutil + libc.src.__support.error_or ) add_entrypoint_object( @@ -57,10 +61,7 @@ add_entrypoint_object( ../sigaction.h DEPENDS .__restore - libc.hdr.types.sigset_t - libc.hdr.types.struct_sigaction - libc.include.sys_syscall - libc.src.__support.OSUtil.osutil + .signal_utils libc.src.errno.errno ) diff --git a/libc/src/signal/linux/sigaction.cpp b/libc/src/signal/linux/sigaction.cpp index 43a3e195474e..9e76c188ed44 100644 --- a/libc/src/signal/linux/sigaction.cpp +++ b/libc/src/signal/linux/sigaction.cpp @@ -8,7 +8,6 @@ #include "src/signal/sigaction.h" -#include "hdr/types/sigset_t.h" #include "src/__support/common.h" #include "src/__support/libc_errno.h" #include "src/__support/macros/config.h" @@ -16,35 +15,15 @@ namespace LIBC_NAMESPACE_DECL { -// TOOD: Some architectures will have their signal trampoline functions in the -// vdso, use those when available. - -extern "C" void __restore_rt(); - LLVM_LIBC_FUNCTION(int, sigaction, (int signal, const struct sigaction *__restrict libc_new, struct sigaction *__restrict libc_old)) { - KernelSigaction kernel_new; - if (libc_new) { - kernel_new = *libc_new; - if (!(kernel_new.sa_flags & SA_RESTORER)) { - kernel_new.sa_flags |= SA_RESTORER; - kernel_new.sa_restorer = __restore_rt; - } - } + ErrorOr ret = do_sigaction(signal, libc_new, libc_old); + if (ret) + return ret.value(); - KernelSigaction kernel_old; - int ret = LIBC_NAMESPACE::syscall_impl( - SYS_rt_sigaction, signal, libc_new ? &kernel_new : nullptr, - libc_old ? &kernel_old : nullptr, sizeof(sigset_t)); - if (ret) { - libc_errno = -ret; - return -1; - } - - if (libc_old) - *libc_old = kernel_old; - return 0; + libc_errno = ret.error(); + return -1; } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/signal/linux/signal_utils.h b/libc/src/signal/linux/signal_utils.h index 81021276d784..be4501c27dba 100644 --- a/libc/src/signal/linux/signal_utils.h +++ b/libc/src/signal/linux/signal_utils.h @@ -9,17 +9,23 @@ #ifndef LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_UTILS_H #define LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_UTILS_H +#include "hdr/signal_macros.h" +#include "hdr/types/siginfo_t.h" #include "hdr/types/sigset_t.h" +#include "hdr/types/size_t.h" +#include "hdr/types/struct_sigaction.h" +#include "src/__support/OSUtil/linux/vdso.h" #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" +#include "src/__support/error_or.h" #include "src/__support/macros/config.h" -#include // sigaction -#include -#include // For syscall numbers. +#include // For syscall numbers. namespace LIBC_NAMESPACE_DECL { +extern "C" void __restore_rt(); + // The POSIX definition of struct sigaction and the sigaction data structure // expected by the rt_sigaction syscall differ in their definition. So, we // define the equivalent of the what the kernel expects to help with making @@ -107,6 +113,31 @@ LIBC_INLINE int restore_signals(const sigset_t &set) { &set, nullptr, sizeof(sigset_t)); } +LIBC_INLINE ErrorOr +do_sigaction(int signal, const struct sigaction *__restrict libc_new, + struct sigaction *__restrict libc_old) { + vdso::TypedSymbol rt_sigreturn; + KernelSigaction kernel_new; + if (libc_new) { + kernel_new = *libc_new; + if (!(kernel_new.sa_flags & SA_RESTORER)) { + kernel_new.sa_flags |= SA_RESTORER; + kernel_new.sa_restorer = rt_sigreturn ? rt_sigreturn : __restore_rt; + } + } + + KernelSigaction kernel_old; + int ret = LIBC_NAMESPACE::syscall_impl( + SYS_rt_sigaction, signal, libc_new ? &kernel_new : nullptr, + libc_old ? &kernel_old : nullptr, sizeof(sigset_t)); + if (ret) + return Error(-ret); + + if (libc_old) + *libc_old = kernel_old; + return 0; +} + } // namespace LIBC_NAMESPACE_DECL #endif // LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_UTILS_H