xref: /llvm-project/libc/src/signal/linux/sigaction.cpp (revision 5ff3ff33ff930e4ec49da7910612d8a41eb068cb)
166d00febSPaula Toth //===-- Linux implementation of sigaction ---------------------------------===//
24d350556SAlex Brachet //
34d350556SAlex Brachet // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44d350556SAlex Brachet // See https://llvm.org/LICENSE.txt for license information.
54d350556SAlex Brachet // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64d350556SAlex Brachet //
74d350556SAlex Brachet //===----------------------------------------------------------------------===//
84d350556SAlex Brachet 
94d350556SAlex Brachet #include "src/signal/sigaction.h"
10f626a350SNick Desaulniers 
11f626a350SNick Desaulniers #include "hdr/types/sigset_t.h"
12f626a350SNick Desaulniers #include "src/__support/common.h"
13*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
147abf6c25SSiva Chandra Reddy #include "src/errno/libc_errno.h"
15215c9fa4SSiva Chandra Reddy #include "src/signal/linux/signal_utils.h"
164d350556SAlex Brachet 
17*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL {
184d350556SAlex Brachet 
194d350556SAlex Brachet // TOOD: Some architectures will have their signal trampoline functions in the
204d350556SAlex Brachet // vdso, use those when available.
214d350556SAlex Brachet 
224d350556SAlex Brachet extern "C" void __restore_rt();
234d350556SAlex Brachet 
24a0b65a7bSMichael Jones LLVM_LIBC_FUNCTION(int, sigaction,
25215c9fa4SSiva Chandra Reddy                    (int signal, const struct sigaction *__restrict libc_new,
26215c9fa4SSiva Chandra Reddy                     struct sigaction *__restrict libc_old)) {
27215c9fa4SSiva Chandra Reddy   KernelSigaction kernel_new;
284d350556SAlex Brachet   if (libc_new) {
29215c9fa4SSiva Chandra Reddy     kernel_new = *libc_new;
304d350556SAlex Brachet     if (!(kernel_new.sa_flags & SA_RESTORER)) {
314d350556SAlex Brachet       kernel_new.sa_flags |= SA_RESTORER;
324d350556SAlex Brachet       kernel_new.sa_restorer = __restore_rt;
334d350556SAlex Brachet     }
344d350556SAlex Brachet   }
354d350556SAlex Brachet 
36215c9fa4SSiva Chandra Reddy   KernelSigaction kernel_old;
37b6bc9d72SGuillaume Chatelet   int ret = LIBC_NAMESPACE::syscall_impl<int>(
381801c356SMichael Jones       SYS_rt_sigaction, signal, libc_new ? &kernel_new : nullptr,
394d350556SAlex Brachet       libc_old ? &kernel_old : nullptr, sizeof(sigset_t));
404d350556SAlex Brachet   if (ret) {
417abf6c25SSiva Chandra Reddy     libc_errno = -ret;
424d350556SAlex Brachet     return -1;
434d350556SAlex Brachet   }
444d350556SAlex Brachet 
454d350556SAlex Brachet   if (libc_old)
46215c9fa4SSiva Chandra Reddy     *libc_old = kernel_old;
474d350556SAlex Brachet   return 0;
484d350556SAlex Brachet }
494d350556SAlex Brachet 
50*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
51