[libc] Re-enable functions from signal.h and re-enable abort.

They were disabled because we were including linux/signal.h from our
signal.h. Linux's signal.h is not designed to be included from user
programs as it causes a lot of non-standard name pollution. Also, it is
not self-contained. This change defines types and macros relevant for
signal related syscalls within libc's headers and removes inclusion of
Linux headers.

This patch enables the funtions only for x86_64. They will be enabled
for aarch64 also in a follow up patch after testing.

Reviewed By: abrachet, lntue

Differential Revision: https://reviews.llvm.org/D134567
This commit is contained in:
Siva Chandra Reddy 2022-09-07 23:04:09 +00:00
parent 6886f094e8
commit 215c9fa4de
33 changed files with 423 additions and 181 deletions

View File

@ -205,7 +205,7 @@ def SysMManAPI : PublicAPI<"sys/mman.h"> {
}
def SignalAPI : PublicAPI<"signal.h"> {
let Types = ["struct sigaction", "__sighandler_t"];
let Types = ["sigset_t", "struct sigaction", "union sigval", "siginfo_t"];
}
def ThreadsAPI : PublicAPI<"threads.h"> {

View File

@ -355,20 +355,20 @@ if(LLVM_LIBC_FULL_BUILD)
# stdlib.h entrypoints
libc.src.stdlib._Exit
libc.src.stdlib.abort
libc.src.stdlib.atexit
libc.src.stdlib.exit
libc.src.stdlib.getenv
# signal.h entrypoints
# TODO: Enable signal.h entrypoints after fixing signal.h
# libc.src.signal.raise
# libc.src.signal.sigaction
# libc.src.signal.sigdelset
# libc.src.signal.sigaddset
# libc.src.signal.sigemptyset
# libc.src.signal.sigprocmask
# libc.src.signal.sigfillset
# libc.src.signal.signal
libc.src.signal.raise
libc.src.signal.sigaction
libc.src.signal.sigdelset
libc.src.signal.sigaddset
libc.src.signal.sigemptyset
libc.src.signal.sigprocmask
libc.src.signal.sigfillset
libc.src.signal.signal
# threads.h entrypoints
libc.src.threads.call_once

View File

@ -133,8 +133,10 @@ add_gen_header(
DATA_FILES
../config/${LIBC_TARGET_OS}/signal.h.in
DEPENDS
.llvm-libc-macros.signal_macros
.llvm-libc-types.struct_sigaction
.llvm-libc-types.__sighandler_t
.llvm-libc-types.sigset_t
)
add_gen_header(

View File

@ -14,6 +14,14 @@ add_header(
file-seek-macros.h
)
add_header(
signal_macros
HDR
signal-macros.h
DEPENDS
.linux.signal_macros
)
add_header(
sys_stat_macros
HDR

View File

@ -33,3 +33,9 @@ add_header(
HDR
unistd-macros.h
)
add_header(
signal_macros
HDR
signal-macros.h
)

View File

@ -0,0 +1,78 @@
//===-- Definition of Linux signal number macros --------------------------===//
//
// 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_MACROS_LINUX_SIGNUM_MACROS_H
#define __LLVM_LIBC_MACROS_LINUX_SIGNUM_MACROS_H
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGTRAP 5
#define SIGABRT 6
#define SIGIOT 6
#define SIGBUS 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGUSR1 10
#define SIGSEGV 11
#define SIGUSR2 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGSTKFLT 16
#define SIGCHLD 17
#define SIGCONT 18
#define SIGSTOP 19
#define SIGTSTP 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGURG 23
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
#define SIGIO 29
#define SIGPOLL SIGIO
#define SIGPWR 30
#define SIGSYS 31
// Max signal number
#define NSIG 64
// SIGRTMIN is current set to the minimum usable from user mode programs. If
// the libc itself uses some of these signal numbers for private operations,
// then it has to be adjusted in future to reflect that.
#define SIGRTMIN 32
#define SIGRTMAX NSIG
// The kernel sigset is stored as an array of long values. Each bit of this
// array corresponds to a signal, adjusted by 1. That is, bit 0 corresponds
// to signal number 1, bit 1 corresponds to signal number 2 and so on. The
// below macro denotes the size of that array (in number of long words and
// not bytes).
#define __NSIGSET_WORDS (NSIG / (sizeof(unsigned long) * 8))
#define SIG_BLOCK 0 // For blocking signals
#define SIG_UNBLOCK 1 // For unblocking signals
#define SIG_SETMASK 2 // For setting signal mask
// Flag values to be used for setting sigaction.sa_flags.
#define SA_NOCLDSTOP 0x00000001
#define SA_NOCLDWAIT 0x00000002
#define SA_SIGINFO 0x00000004
#define SA_RESTART 0x10000000
#define SA_RESTORER 0x04000000
#define SIG_DFL ((__sighandler_t)0)
#define SIG_IGN ((__sighandler_t)1)
#define SIG_ERR ((__sighandler_t)-1)
#endif // __LLVM_LIBC_MACROS_LINUX_SIGNUM_MACROS_H

View File

@ -0,0 +1,16 @@
//===-- Definition of signal number macros --------------------------------===//
//
// 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_MACROS_SIGNUM_MACROS_H
#define __LLVM_LIBC_MACROS_SIGNUM_MACROS_H
#ifdef __linux__
#include "linux/signal-macros.h"
#endif
#endif // __LLVM_LIBC_MACROS_SIGNUM_MACROS_H

View File

@ -46,7 +46,10 @@ add_header(rlim_t HDR rlim_t.h)
add_header(struct_rlimit HDR struct_rlimit.h DEPENDS .rlim_t)
add_header(ssize_t HDR ssize_t.h)
add_header(struct_dirent HDR struct_dirent.h DEPENDS .ino_t .off_t)
add_header(struct_sigaction HDR struct_sigaction.h)
add_header(union_sigval HDR union_sigval.h)
add_header(siginfo_t HDR siginfo_t.h DEPENDS .union_sigval .pid_t .uid_t)
add_header(sigset_t HDR sigset_t.h DEPENDS libc.include.llvm-libc-macros.signal_macros)
add_header(struct_sigaction HDR struct_sigaction.h DEPENDS .sigset_t .siginfo_t)
add_header(time_t HDR time_t.h)
add_header(struct_timespec HDR struct_timespec.h DEPENDS .time_t)
add_header(

View File

@ -0,0 +1,28 @@
//===-- Definition of siginfo_t type --------------------------------------===//
//
// 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_TYPES_SIGINFO_T_H__
#define __LLVM_LIBC_TYPES_SIGINFO_T_H__
#include <llvm-libc-types/pid_t.h>
#include <llvm-libc-types/uid_t.h>
#include <llvm-libc-types/union_sigval.h>
typedef struct {
int si_signo;
int si_code;
int si_errno;
pid_t si_pid;
uid_t si_uid;
void *si_addr;
int si_status;
long si_band;
union sigval si_value;
} siginfo_t;
#endif // __LLVM_LIBC_TYPES_SIGINFO_T_H__

View File

@ -0,0 +1,20 @@
//===-- Definition of sigset_t type ---------------------------------------===//
//
// 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_TYPES_SIGSET_T_H__
#define __LLVM_LIBC_TYPES_SIGSET_T_H__
#include <llvm-libc-macros/signal-macros.h>
// This definition can be adjusted/specialized for different targets and
// platforms as necessary. This definition works for Linux on most targets.
typedef struct {
unsigned long __signals[__NSIGSET_WORDS];
} sigset_t;
#endif // __LLVM_LIBC_TYPES_SIGSET_T_H__

View File

@ -9,14 +9,22 @@
#ifndef __LLVM_LIBC_TYPES_SIGACTION_H__
#define __LLVM_LIBC_TYPES_SIGACTION_H__
struct __sigaction {
#include <llvm-libc-types/siginfo_t.h>
#include <llvm-libc-types/sigset_t.h>
struct sigaction {
union {
void (*sa_handler)(int);
void (*sa_action)(int, siginfo_t *, void *);
void (*sa_sigaction)(int, siginfo_t *, void *);
};
sigset_t sa_mask;
int sa_flags;
#ifdef __linux__
// This field is present on linux for most targets.
void (*sa_restorer)(void);
#endif
};
typedef void (*__sighandler_t)(int);
#endif // __LLVM_LIBC_TYPES_SIGACTION_H__

View File

@ -0,0 +1,17 @@
//===-- Definition of type union sigval -----------------------------------===//
//
// 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_TYPES_UNION_SIGVAL_H__
#define __LLVM_LIBC_TYPES_UNION_SIGVAL_H__
union sigval {
int sival_int;
void *sival_ptr;
};
#endif // __LLVM_LIBC_TYPES_UNION_SIGVAL_H__

View File

@ -14,7 +14,7 @@
#define __need_size_t
#include <stddef.h>
%%include_file(${platform_signal})
#include <llvm-libc-macros/signal-macros.h>
%%public_api()

View File

@ -4,6 +4,9 @@ def ConstSigSetPtrType : ConstType<SigSetPtrType>;
def RestrictedSigSetType : RestrictedPtrType<SigSetType>;
def ConstRestrictedSigSetType : ConstType<RestrictedSigSetType>;
def SigInfoType : NamedType<"siginfo_t">;
def UnionSigVal : NamedType<"union sigval">;
def StructSigaction : NamedType<"struct sigaction">;
def StructSigactionPtr : PtrType<StructSigaction>;
def ConstStructSigactionPtr : ConstType<StructSigactionPtr>;
@ -248,8 +251,10 @@ def POSIX : StandardSpec<"POSIX"> {
"signal.h",
[], // Macros
[
SigInfoType,
SigSetType,
StructSigaction,
UnionSigVal,
],
[], // Enumerations
[

View File

@ -25,6 +25,6 @@ endif()
# The signal API is currently disabled as signal.h is incorrect.
# since assert uses the signal API, we disable assert also.
# add_subdirectory(assert)
# add_subdirectory(signal)
add_subdirectory(signal)
add_subdirectory(threads)
add_subdirectory(time)

View File

@ -1,12 +1,20 @@
add_header_library(
signal_utils
HDRS
signal_utils.h
DEPENDS
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
)
add_entrypoint_object(
raise
SRCS
raise.cpp
HDRS
signal.h
../raise.h
DEPENDS
.signal_utils
libc.include.signal
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
@ -34,7 +42,6 @@ add_entrypoint_object(
SRCS
sigaction.cpp
HDRS
signal.h
../sigaction.h
DEPENDS
.__restore
@ -49,9 +56,9 @@ add_entrypoint_object(
SRCS
sigprocmask.cpp
HDRS
signal.h
../sigprocmask.h
DEPENDS
.signal_utils
libc.include.signal
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
@ -63,9 +70,9 @@ add_entrypoint_object(
SRCS
sigemptyset.cpp
HDRS
signal.h
../sigemptyset.h
DEPENDS
.signal_utils
libc.include.errno
libc.include.signal
libc.src.errno.errno
@ -76,9 +83,9 @@ add_entrypoint_object(
SRCS
sigaddset.cpp
HDRS
signal.h
../sigaddset.h
DEPENDS
.signal_utils
libc.include.errno
libc.include.signal
libc.src.errno.errno
@ -89,7 +96,6 @@ add_entrypoint_object(
SRCS
signal.cpp
HDRS
signal.h
../signal.h
DEPENDS
.sigaction
@ -101,9 +107,9 @@ add_entrypoint_object(
SRCS
sigfillset.cpp
HDRS
signal.h
../sigfillset.h
DEPENDS
.signal_utils
libc.include.errno
libc.include.signal
libc.src.errno.errno
@ -114,9 +120,9 @@ add_entrypoint_object(
SRCS
sigdelset.cpp
HDRS
signal.h
../sigdelset.h
DEPENDS
.signal_utils
libc.include.errno
libc.include.signal
libc.src.errno.errno

View File

@ -7,19 +7,19 @@
//===----------------------------------------------------------------------===//
#include "src/signal/raise.h"
#include "src/signal/linux/signal.h"
#include "src/signal/linux/signal_utils.h"
#include "src/__support/common.h"
namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, raise, (int sig)) {
__llvm_libc::Sigset sigset;
__llvm_libc::block_all_signals(sigset);
::sigset_t sigset;
block_all_signals(sigset);
long pid = __llvm_libc::syscall(SYS_getpid);
long tid = __llvm_libc::syscall(SYS_gettid);
int ret = __llvm_libc::syscall(SYS_tgkill, pid, tid, sig);
__llvm_libc::restore_signals(sigset);
restore_signals(sigset);
return ret;
}

View File

@ -6,13 +6,14 @@
//
//===----------------------------------------------------------------------===//
#define __LLVM_LIBC_INTERNAL_SIGACTION
#include "src/signal/sigaction.h"
#include "src/errno/llvmlibc_errno.h"
#include "src/signal/linux/signal.h"
#include "src/signal/linux/signal_utils.h"
#include "src/__support/common.h"
#include <errno.h>
#include <signal.h>
namespace __llvm_libc {
// TOOD: Some architectures will have their signal trampoline functions in the
@ -20,36 +21,28 @@ namespace __llvm_libc {
extern "C" void __restore_rt();
template <typename T, typename V>
static void copy_sigaction(T &dest, const V &source) {
dest.sa_handler = source.sa_handler;
dest.sa_mask = source.sa_mask;
dest.sa_flags = source.sa_flags;
dest.sa_restorer = source.sa_restorer;
}
LLVM_LIBC_FUNCTION(int, sigaction,
(int signal, const struct __sigaction *__restrict libc_new,
struct __sigaction *__restrict libc_old)) {
struct sigaction kernel_new;
(int signal, const struct sigaction *__restrict libc_new,
struct sigaction *__restrict libc_old)) {
KernelSigaction kernel_new;
if (libc_new) {
copy_sigaction(kernel_new, *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;
}
}
struct sigaction kernel_old;
KernelSigaction kernel_old;
int ret = syscall(SYS_rt_sigaction, signal, libc_new ? &kernel_new : nullptr,
libc_old ? &kernel_old : nullptr, sizeof(sigset_t));
if (ret) {
llvmlibc_errno = -ret;
errno = -ret;
return -1;
}
if (libc_old)
copy_sigaction(*libc_old, kernel_old);
*libc_old = kernel_old;
return 0;
}

View File

@ -7,22 +7,19 @@
//===----------------------------------------------------------------------===//
#include "src/signal/sigaddset.h"
#include "include/errno.h" // For E* macros.
#include "src/errno/llvmlibc_errno.h"
#include "src/signal/linux/signal.h"
#include "src/__support/common.h"
#include "src/signal/linux/signal_utils.h"
#include <errno.h>
#include <signal.h>
namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, sigaddset, (sigset_t * set, int signum)) {
if (!set || (unsigned)(signum - 1) >= (8 * sizeof(sigset_t))) {
llvmlibc_errno = EINVAL;
return -1;
}
auto *sigset = reinterpret_cast<__llvm_libc::Sigset *>(set);
sigset->addset(signum);
return 0;
if (set != nullptr && add_signal(*set, signum))
return 0;
errno = EINVAL;
return -1;
}
} // namespace __llvm_libc

View File

@ -7,22 +7,19 @@
//===----------------------------------------------------------------------===//
#include "src/signal/sigdelset.h"
#include "include/errno.h"
#include "src/errno/llvmlibc_errno.h"
#include "src/signal/linux/signal.h"
#include "src/__support/common.h"
#include "src/signal/linux/signal_utils.h"
#include <errno.h>
#include <signal.h>
namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, sigdelset, (sigset_t * set, int signum)) {
if (!set || (unsigned)(signum - 1) >= (8 * sizeof(sigset_t))) {
llvmlibc_errno = EINVAL;
return -1;
}
auto *sigset = reinterpret_cast<__llvm_libc::Sigset *>(set);
sigset->delset(signum);
return 0;
if (set != nullptr && delete_signal(*set, signum))
return 0;
errno = EINVAL;
return -1;
}
} // namespace __llvm_libc

View File

@ -7,20 +7,21 @@
//===----------------------------------------------------------------------===//
#include "src/signal/sigemptyset.h"
#include "include/errno.h" // For E* macros.
#include "src/errno/llvmlibc_errno.h"
#include "src/signal/linux/signal.h"
#include "src/signal/linux/signal_utils.h"
#include "src/__support/common.h"
#include <errno.h>
#include <signal.h>
namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, sigemptyset, (sigset_t * set)) {
if (!set) {
llvmlibc_errno = EINVAL;
errno = EINVAL;
return -1;
}
*set = __llvm_libc::Sigset::empty_set();
*set = empty_set();
return 0;
}

View File

@ -7,21 +7,20 @@
//===----------------------------------------------------------------------===//
#include "src/signal/sigfillset.h"
#include "include/errno.h"
#include "src/errno/llvmlibc_errno.h"
#include "src/signal/linux/signal.h"
#include "src/__support/common.h"
#include "src/signal/linux/signal_utils.h"
#include <errno.h>
#include <signal.h>
namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, sigfillset, (sigset_t * set)) {
if (!set) {
llvmlibc_errno = EINVAL;
errno = EINVAL;
return -1;
}
auto *sigset = reinterpret_cast<__llvm_libc::Sigset *>(set);
*sigset = __llvm_libc::Sigset::fullset();
*set = full_set();
return 0;
}

View File

@ -6,16 +6,17 @@
//
//===----------------------------------------------------------------------===//
#define __LLVM_LIBC_INTERNAL_SIGACTION
#include "src/signal/signal.h"
#include "src/signal/sigaction.h"
#include "src/__support/common.h"
#include <signal.h>
namespace __llvm_libc {
LLVM_LIBC_FUNCTION(sighandler_t, signal, (int signum, sighandler_t handler)) {
struct __sigaction action, old;
struct sigaction action, old;
action.sa_handler = handler;
action.sa_flags = SA_RESTART;
// Errno will already be set so no need to worry about changing errno here.

View File

@ -1,55 +0,0 @@
//===-- Internal header for Linux signals -----------------------*- C++ -*-===//
//
// 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_SRC_SIGNAL_LINUX_SIGNAL_H
#define LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_H
#include "include/sys/syscall.h" // For syscall numbers.
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "include/signal.h"
static_assert(sizeof(sigset_t) * 8 >= NSIG, "sigset_t cannot hold all signals");
namespace __llvm_libc {
// Using this internally defined type will make it easier in the future to port
// to different architectures.
struct Sigset {
sigset_t native_sigset;
constexpr static Sigset fullset() { return {-1UL}; }
constexpr static Sigset empty_set() { return {0}; }
constexpr void addset(int signal) { native_sigset |= (1L << (signal - 1)); }
constexpr void delset(int signal) { native_sigset &= ~(1L << (signal - 1)); }
operator sigset_t() const { return native_sigset; }
};
constexpr static Sigset ALL = Sigset::fullset();
static inline int block_all_signals(Sigset &set) {
sigset_t native_sigset = ALL;
sigset_t old_set = set;
int ret = __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_BLOCK, &native_sigset,
&old_set, sizeof(sigset_t));
set = {old_set};
return ret;
}
static inline int restore_signals(const Sigset &set) {
sigset_t native_sigset = set;
return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &native_sigset,
nullptr, sizeof(sigset_t));
}
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_H

View File

@ -0,0 +1,109 @@
//===-- Internal header for Linux signals -----------------------*- C++ -*-===//
//
// 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_SRC_SIGNAL_LINUX_SIGNAL_UTILS_H
#define LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_UTILS_H
#include "include/sys/syscall.h" // For syscall numbers.
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include <signal.h>
#include <stddef.h>
namespace __llvm_libc {
// 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
// the rt_sigaction syscall.
//
// NOTE: Though the kernel definition does not have a union to include the
// handler taking siginfo_t * argument, one can set sa_handler to sa_sigaction
// if SA_SIGINFO is set in sa_flags.
struct KernelSigaction {
using HandlerType = void(int);
using SiginfoHandlerType = void(int, siginfo_t *, void *);
KernelSigaction &operator=(const struct sigaction &sa) {
sa_flags = sa.sa_flags;
sa_restorer = sa.sa_restorer;
sa_mask = sa.sa_mask;
if (sa_flags & SA_SIGINFO) {
sa_handler = reinterpret_cast<HandlerType *>(sa.sa_sigaction);
} else {
sa_handler = sa.sa_handler;
}
return *this;
}
operator struct sigaction() const {
struct sigaction sa;
sa.sa_flags = sa_flags;
sa.sa_mask = sa_mask;
sa.sa_restorer = sa_restorer;
if (sa_flags & SA_SIGINFO)
sa.sa_sigaction = reinterpret_cast<SiginfoHandlerType *>(sa_handler);
else
sa.sa_handler = sa_handler;
return sa;
}
HandlerType *sa_handler;
unsigned long sa_flags;
void (*sa_restorer)(void);
// Our public definition of sigset_t matches that of the kernel's definition.
// So, we can use the public sigset_t type here.
sigset_t sa_mask;
};
static constexpr size_t BITS_PER_SIGWORD = sizeof(unsigned long) * 8;
constexpr sigset_t full_set() { return sigset_t{{-1UL}}; }
constexpr sigset_t empty_set() { return sigset_t{{0}}; }
// Set the bit corresponding to |signal| in |set|. Return true on success
// and false on failure. The function will fail if |signal| is greater than
// NSIG or negative.
constexpr inline bool add_signal(sigset_t &set, int signal) {
if (signal > NSIG || signal <= 0)
return false;
size_t n = size_t(signal) - 1;
size_t word = n / BITS_PER_SIGWORD;
size_t bit = n % BITS_PER_SIGWORD;
set.__signals[word] |= (1UL << bit);
return true;
}
// Reset the bit corresponding to |signal| in |set|. Return true on success
// and false on failure. The function will fail if |signal| is greater than
// NSIG or negative.
constexpr inline bool delete_signal(sigset_t &set, int signal) {
if (signal > NSIG || signal <= 0)
return false;
size_t n = size_t(signal) - 1;
size_t word = n / BITS_PER_SIGWORD;
size_t bit = n % BITS_PER_SIGWORD;
set.__signals[word] &= ~(1UL << bit);
return true;
}
static inline int block_all_signals(sigset_t &set) {
sigset_t full = full_set();
return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_BLOCK, &full, &set,
sizeof(sigset_t));
}
static inline int restore_signals(const sigset_t &set) {
return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &set, nullptr,
sizeof(sigset_t));
}
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_UTILS_H

View File

@ -7,11 +7,15 @@
//===----------------------------------------------------------------------===//
#include "src/signal/sigprocmask.h"
#include "src/errno/llvmlibc_errno.h"
#include "src/signal/linux/signal.h"
#include "include/sys/syscall.h" // For syscall numbers.
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/signal/linux/signal_utils.h"
#include "src/__support/common.h"
#include <errno.h>
#include <signal.h>
namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, sigprocmask,
@ -22,7 +26,7 @@ LLVM_LIBC_FUNCTION(int, sigprocmask,
if (!ret)
return 0;
llvmlibc_errno = -ret;
errno = -ret;
return -1;
}

View File

@ -9,13 +9,12 @@
#ifndef LLVM_LIBC_SRC_SIGNAL_SIGACTION_H
#define LLVM_LIBC_SRC_SIGNAL_SIGACTION_H
#define __LLVM_LIBC_INTERNAL_SIGACTION
#include "include/signal.h"
#include <signal.h>
namespace __llvm_libc {
int sigaction(int signal, const struct __sigaction *__restrict libc_new,
struct __sigaction *__restrict libc_old);
int sigaction(int signal, const struct sigaction *__restrict libc_new,
struct sigaction *__restrict libc_old);
} // namespace __llvm_libc

View File

@ -9,7 +9,7 @@
#ifndef LLVM_LIBC_SRC_SIGNAL_SIGEADDSET_H
#define LLVM_LIBC_SRC_SIGNAL_SIGEADDSET_H
#include "include/signal.h"
#include <signal.h>
namespace __llvm_libc {

View File

@ -302,9 +302,9 @@ add_entrypoint_object(
.atexit
)
# add_entrypoint_object(
# abort
# ALIAS
# DEPENDS
# .${LIBC_TARGET_OS}.abort
# )
add_entrypoint_object(
abort
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.abort
)

View File

@ -10,14 +10,14 @@ add_entrypoint_object(
libc.src.__support.OSUtil.osutil
)
# add_entrypoint_object(
# abort
# SRCS
# abort.cpp
# HDRS
# ../abort.h
# DEPENDS
# libc.include.stdlib
# libc.src.signal.raise
# ._Exit
# )
add_entrypoint_object(
abort
SRCS
abort.cpp
HDRS
../abort.h
DEPENDS
libc.include.stdlib
libc.src.signal.raise
._Exit
)

View File

@ -51,7 +51,7 @@ add_subdirectory(dirent)
# The signal API is currently disabled as signal.h is incorrect.
# since assert uses the signal API, we disable assert also.
# add_subdirectory(assert)
# add_subdirectory(signal)
add_subdirectory(signal)
add_subdirectory(time)
if(${LIBC_TARGET_OS} STREQUAL "linux")

View File

@ -6,15 +6,15 @@
//
//===----------------------------------------------------------------------===//
#include "include/errno.h"
#define __LLVM_LIBC_INTERNAL_SIGACTION
#include "include/signal.h"
#include "src/signal/raise.h"
#include "src/signal/sigaction.h"
#include "test/ErrnoSetterMatcher.h"
#include "utils/UnitTest/Test.h"
#include <errno.h>
#include <signal.h>
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
@ -25,7 +25,7 @@ TEST(LlvmLibcSigaction, Invalid) {
// SIGKILL cannot have its action changed, but it can be examined.
TEST(LlvmLibcSigaction, Sigkill) {
struct __sigaction action;
struct sigaction action;
EXPECT_THAT(__llvm_libc::sigaction(SIGKILL, nullptr, &action), Succeeds());
EXPECT_THAT(__llvm_libc::sigaction(SIGKILL, &action, nullptr), Fails(EINVAL));
}
@ -37,7 +37,7 @@ TEST(LlvmLibcSigaction, CustomAction) {
// Zero this incase tests get run multiple times in the future.
sigusr1Count = 0;
struct __sigaction action;
struct sigaction action;
EXPECT_THAT(__llvm_libc::sigaction(SIGUSR1, nullptr, &action), Succeeds());
action.sa_handler = +[](int signal) {
@ -57,7 +57,7 @@ TEST(LlvmLibcSigaction, CustomAction) {
}
TEST(LlvmLibcSigaction, Ignore) {
struct __sigaction action;
struct sigaction action;
EXPECT_THAT(__llvm_libc::sigaction(SIGUSR1, nullptr, &action), Succeeds());
action.sa_handler = SIG_IGN;
EXPECT_THAT(__llvm_libc::sigaction(SIGUSR1, &action, nullptr), Succeeds());

View File

@ -231,18 +231,18 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.__support.CPP.utility
)
# add_libc_unittest(
# abort_test
# SUITE
# libc_stdlib_unittests
# SRCS
# abort_test.cpp
# DEPENDS
# libc.include.stdlib
# libc.include.signal
# libc.src.stdlib.abort
# libc.src.stdlib._Exit
# libc.src.signal.raise
# )
add_libc_unittest(
abort_test
SUITE
libc_stdlib_unittests
SRCS
abort_test.cpp
DEPENDS
libc.include.stdlib
libc.include.signal
libc.src.stdlib.abort
libc.src.stdlib._Exit
libc.src.signal.raise
)
endif()