forked from OSchip/llvm-project
[libc] Add sigprocmask
Summary: This patch adds `sigprocmask`, `sigemptyset` and `sigaddset` Reviewers: sivachandra, MaskRay, gchatelet Reviewed By: sivachandra Subscribers: mgorny, tschuett, libc-commits Differential Revision: https://reviews.llvm.org/D75026
This commit is contained in:
parent
802b22b5c8
commit
cd76a02639
libc
|
@ -135,12 +135,11 @@ def SysMManAPI : PublicAPI<"sys/mman.h"> {
|
|||
}
|
||||
|
||||
def SignalAPI : PublicAPI<"signal.h"> {
|
||||
let TypeDeclarations = [
|
||||
SizeT, // This is needed by <linux/signal.h>.
|
||||
];
|
||||
|
||||
let Functions = [
|
||||
"raise",
|
||||
"sigprocmask",
|
||||
"sigemptyset",
|
||||
"sigaddset",
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,11 @@
|
|||
|
||||
#include <__llvm-libc-common.h>
|
||||
|
||||
%%public_api()
|
||||
#define __need_size_t
|
||||
#include <stddef.h>
|
||||
|
||||
%%include_file(${platform_signal})
|
||||
|
||||
%%public_api()
|
||||
|
||||
#endif // LLVM_LIBC_SIGNAL_H
|
||||
|
|
|
@ -15,6 +15,9 @@ add_entrypoint_library(
|
|||
|
||||
# signal.h entrypoints
|
||||
raise
|
||||
sigaddset
|
||||
sigemptyset
|
||||
sigprocmask
|
||||
)
|
||||
|
||||
add_entrypoint_library(
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
def SigSetType : NamedType<"sigset_t">;
|
||||
def SigSetPtrType : PtrType<SigSetType>;
|
||||
def ConstSigSetPtrType : ConstType<SigSetPtrType>;
|
||||
def RestrictSigSetType : RestrictedPtrType<SigSetType>;
|
||||
def ConstRestrictSigSetType : ConstType<RestrictSigSetType>;
|
||||
|
||||
def POSIX : StandardSpec<"POSIX"> {
|
||||
NamedType OffTType = NamedType<"off_t">;
|
||||
|
||||
|
@ -128,8 +134,33 @@ def POSIX : StandardSpec<"POSIX"> {
|
|||
]
|
||||
>;
|
||||
|
||||
HeaderSpec Signal = HeaderSpec<
|
||||
"signal.h",
|
||||
[], // Macros
|
||||
[], // Types
|
||||
[], // Enumerations
|
||||
[
|
||||
FunctionSpec<
|
||||
"sigprocmask",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<IntType>, ArgSpec<ConstRestrictSigSetType>, ArgSpec<RestrictSigSetType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"sigemptyset",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<SigSetPtrType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"sigaddset",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<SigSetPtrType>]
|
||||
>,
|
||||
]
|
||||
>;
|
||||
|
||||
let Headers = [
|
||||
Errno,
|
||||
SysMMan,
|
||||
Signal,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -6,9 +6,46 @@ add_entrypoint_object(
|
|||
HDRS
|
||||
signal.h
|
||||
../raise.h
|
||||
DEPENDS
|
||||
sys_syscall_h
|
||||
linux_syscall_h
|
||||
signal_h
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
sigprocmask
|
||||
SRCS
|
||||
sigprocmask.cpp
|
||||
HDRS
|
||||
signal.h
|
||||
../sigprocmask.h
|
||||
DEPENDS
|
||||
sys_syscall_h
|
||||
linux_syscall_h
|
||||
__errno_location
|
||||
signal_h
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
sigemptyset
|
||||
SRCS
|
||||
sigemptyset.cpp
|
||||
HDRS
|
||||
signal.h
|
||||
../sigemptyset.h
|
||||
DEPENDS
|
||||
__errno_location
|
||||
signal_h
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
sigaddset
|
||||
SRCS
|
||||
sigaddset.cpp
|
||||
HDRS
|
||||
signal.h
|
||||
../sigaddset.h
|
||||
DEPENDS
|
||||
__errno_location
|
||||
signal_h
|
||||
)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//===----------------- Linux implementation of sigaddset ------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int LLVM_LIBC_ENTRYPOINT(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;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,27 @@
|
|||
//===--------------- Linux implementation of sigemptyset ------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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/__support/common.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int LLVM_LIBC_ENTRYPOINT(sigemptyset)(sigset_t *set) {
|
||||
if (!set) {
|
||||
llvmlibc_errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
*set = __llvm_libc::Sigset::emptySet();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -24,6 +24,11 @@ struct Sigset {
|
|||
sigset_t nativeSigset;
|
||||
|
||||
constexpr static Sigset fullset() { return {-1UL}; }
|
||||
constexpr static Sigset emptySet() { return {0}; }
|
||||
|
||||
constexpr void addset(int signal) {
|
||||
nativeSigset |= (1L << (signal - 1));
|
||||
}
|
||||
|
||||
operator sigset_t() const { return nativeSigset; }
|
||||
};
|
||||
|
@ -33,8 +38,10 @@ constexpr static Sigset all = Sigset::fullset();
|
|||
static inline int block_all_signals(Sigset &set) {
|
||||
sigset_t nativeSigset = all;
|
||||
sigset_t oldSet = set;
|
||||
return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_BLOCK, &nativeSigset,
|
||||
int ret = __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_BLOCK, &nativeSigset,
|
||||
&oldSet, sizeof(sigset_t));
|
||||
set = {oldSet};
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int restore_signals(const Sigset &set) {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//===--------------- Linux implementation of sigprocmask ------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/signal/sigprocmask.h"
|
||||
#include "src/errno/llvmlibc_errno.h"
|
||||
#include "src/signal/linux/signal.h"
|
||||
|
||||
#include "src/__support/common.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int LLVM_LIBC_ENTRYPOINT(sigprocmask)(int how, const sigset_t *__restrict set,
|
||||
sigset_t *__restrict oldset) {
|
||||
int ret = __llvm_libc::syscall(SYS_rt_sigprocmask, how, set, oldset,
|
||||
sizeof(sigset_t));
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
llvmlibc_errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
|||
//===------------- Implementation header for sigaddset ---------*- 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_SIGEADDSET_H
|
||||
#define LLVM_LIBC_SRC_SIGNAL_SIGEADDSET_H
|
||||
|
||||
#include "include/signal.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int sigaddset(sigset_t *set, int signum);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_SIGNAL_SIGEADDSET_H
|
|
@ -0,0 +1,20 @@
|
|||
//===------------ Implementation header for sigemptyset --------*- 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_SIGEMPTYSET_H
|
||||
#define LLVM_LIBC_SRC_SIGNAL_SIGEMPTYSET_H
|
||||
|
||||
#include "include/signal.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int sigemptyset(sigset_t *set);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_SIGNAL_SIGEMPTYSET_H
|
|
@ -0,0 +1,21 @@
|
|||
//===------------ Implementation header for sigprocmask --------*- 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_SIGPROCMASK_H
|
||||
#define LLVM_LIBC_SRC_SIGNAL_SIGPROCMASK_H
|
||||
|
||||
#include "include/signal.h"
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int sigprocmask(int how, const sigset_t *__restrict set,
|
||||
sigset_t *__restrict oldset);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_SIGNAL_SIGPROCMASK_H
|
|
@ -10,3 +10,30 @@ add_libc_unittest(
|
|||
raise
|
||||
signal_h
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
sigprocmask_test
|
||||
SUITE
|
||||
libc_signal_unittests
|
||||
SRCS
|
||||
sigprocmask_test.cpp
|
||||
DEPENDS
|
||||
raise
|
||||
sigprocmask
|
||||
sigaddset
|
||||
sigemptyset
|
||||
signal_h
|
||||
__errno_location
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
sigaddset_test
|
||||
SUITE
|
||||
libc_signal_unittests
|
||||
SRCS
|
||||
sigaddset_test.cpp
|
||||
DEPENDS
|
||||
sigaddset
|
||||
signal_h
|
||||
__errno_location
|
||||
)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "include/signal.h"
|
||||
#include "src/signal/raise.h"
|
||||
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
TEST(SignalTest, Raise) {
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
//===----------------------- Unittests for sigaddset ----------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "include/errno.h"
|
||||
#include "include/signal.h"
|
||||
#include "src/errno/llvmlibc_errno.h"
|
||||
#include "src/signal/sigaddset.h"
|
||||
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
// This tests invalid inputs and ensures errno is properly set.
|
||||
TEST(SignalTest, SigaddsetInvalid) {
|
||||
llvmlibc_errno = 0;
|
||||
EXPECT_EQ(__llvm_libc::sigaddset(nullptr, SIGSEGV), -1);
|
||||
EXPECT_EQ(llvmlibc_errno, EINVAL);
|
||||
|
||||
sigset_t sigset;
|
||||
llvmlibc_errno = 0;
|
||||
EXPECT_EQ(__llvm_libc::sigaddset(&sigset, -1), -1);
|
||||
EXPECT_EQ(llvmlibc_errno, EINVAL);
|
||||
|
||||
// This doesn't use NSIG because __llvm_libc::sigaddset error checking is
|
||||
// against sizeof(sigset_t) not NSIG.
|
||||
constexpr int bitsInSigsetT = 8 * sizeof(sigset_t);
|
||||
|
||||
llvmlibc_errno = 0;
|
||||
EXPECT_EQ(__llvm_libc::sigaddset(&sigset, bitsInSigsetT + 1), -1);
|
||||
EXPECT_EQ(llvmlibc_errno, EINVAL);
|
||||
|
||||
llvmlibc_errno = 0;
|
||||
EXPECT_EQ(__llvm_libc::sigaddset(&sigset, 0), -1);
|
||||
EXPECT_EQ(llvmlibc_errno, EINVAL);
|
||||
|
||||
llvmlibc_errno = 0;
|
||||
EXPECT_EQ(__llvm_libc::sigaddset(&sigset, bitsInSigsetT), 0);
|
||||
EXPECT_EQ(llvmlibc_errno, 0);
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
//===--------------------- Unittests for sigprocmask ----------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "include/errno.h"
|
||||
#include "include/signal.h"
|
||||
#include "src/errno/llvmlibc_errno.h"
|
||||
#include "src/signal/raise.h"
|
||||
#include "src/signal/sigaddset.h"
|
||||
#include "src/signal/sigemptyset.h"
|
||||
#include "src/signal/sigprocmask.h"
|
||||
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
class SignalTest : public __llvm_libc::testing::Test {
|
||||
sigset_t oldSet;
|
||||
|
||||
public:
|
||||
void SetUp() override { __llvm_libc::sigprocmask(0, nullptr, &oldSet); }
|
||||
|
||||
void TearDown() override {
|
||||
__llvm_libc::sigprocmask(SIG_SETMASK, &oldSet, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
// This tests for invalid input.
|
||||
TEST_F(SignalTest, SigprocmaskInvalid) {
|
||||
sigset_t valid;
|
||||
// 17 and -4 are out of the range for sigprocmask's how paramater.
|
||||
llvmlibc_errno = 0;
|
||||
EXPECT_EQ(__llvm_libc::sigprocmask(17, &valid, nullptr), -1);
|
||||
EXPECT_EQ(llvmlibc_errno, EINVAL);
|
||||
|
||||
llvmlibc_errno = 0;
|
||||
EXPECT_EQ(__llvm_libc::sigprocmask(-4, &valid, nullptr), -1);
|
||||
EXPECT_EQ(llvmlibc_errno, EINVAL);
|
||||
|
||||
// This pointer is out of this processes address range.
|
||||
sigset_t *invalid = reinterpret_cast<sigset_t *>(-1);
|
||||
|
||||
llvmlibc_errno = 0;
|
||||
EXPECT_EQ(__llvm_libc::sigprocmask(SIG_SETMASK, invalid, nullptr), -1);
|
||||
EXPECT_EQ(llvmlibc_errno, EFAULT);
|
||||
|
||||
llvmlibc_errno = 0;
|
||||
EXPECT_EQ(__llvm_libc::sigprocmask(-4, nullptr, invalid), -1);
|
||||
EXPECT_EQ(llvmlibc_errno, EFAULT);
|
||||
}
|
||||
|
||||
// This tests that when nothing is blocked, a process gets killed and alse tests
|
||||
// that when signals are blocked they are not delivered to the process.
|
||||
TEST_F(SignalTest, BlockUnblock) {
|
||||
sigset_t sigset;
|
||||
EXPECT_EQ(__llvm_libc::sigemptyset(&sigset), 0);
|
||||
EXPECT_EQ(__llvm_libc::sigprocmask(SIG_SETMASK, &sigset, nullptr), 0);
|
||||
EXPECT_DEATH([] { __llvm_libc::raise(SIGUSR1); }, SIGUSR1);
|
||||
EXPECT_EQ(__llvm_libc::sigaddset(&sigset, SIGUSR1), 0);
|
||||
EXPECT_EQ(__llvm_libc::sigprocmask(SIG_SETMASK, &sigset, nullptr), 0);
|
||||
EXPECT_EXITS([] { __llvm_libc::raise(SIGUSR1); }, 0);
|
||||
}
|
Loading…
Reference in New Issue