[libc-commits] [libc] ca04d0c - [libc] Add signal

Alex Brachet via libc-commits libc-commits at lists.llvm.org
Sun Mar 22 11:15:54 PDT 2020


Author: Alex Brachet
Date: 2020-03-22T14:15:47-04:00
New Revision: ca04d0c8fd269978be1c13fe1241172cdfe6a6ea

URL: https://github.com/llvm/llvm-project/commit/ca04d0c8fd269978be1c13fe1241172cdfe6a6ea
DIFF: https://github.com/llvm/llvm-project/commit/ca04d0c8fd269978be1c13fe1241172cdfe6a6ea.diff

LOG: [libc] Add signal

Summary:
This patch adds a Linux implementation for `signal`
It also fixes `ASSERT|EXPECT_THAT` macros

Reviewers: sivachandra, PaulkaToast, MaskRay

Reviewed By: sivachandra

Subscribers: mgorny, tschuett, libc-commits

Differential Revision: https://reviews.llvm.org/D76536

Added: 
    libc/src/signal/linux/signal.cpp
    libc/src/signal/signal.h
    libc/test/src/signal/signal_test.cpp

Modified: 
    libc/config/linux/api.td
    libc/lib/CMakeLists.txt
    libc/spec/stdc.td
    libc/src/signal/linux/CMakeLists.txt
    libc/test/src/signal/CMakeLists.txt
    libc/utils/UnitTest/Test.h

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index e9391cb52feb..d9c2470b6e52 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -194,9 +194,16 @@ def StructSigactionDefn : TypeDecl<"struct sigaction"> {
   }];
 }
 
+def SighandlerTDefn : TypeDecl<"__sighandler_t"> {
+  let Decl = [{
+    typedef void(*__sighandler_t)(int);
+  }];
+}
+
 def SignalAPI : PublicAPI<"signal.h"> {
   let TypeDeclarations = [
     StructSigactionDefn,
+    SighandlerTDefn,
   ];
 
   let Functions = [
@@ -205,6 +212,7 @@ def SignalAPI : PublicAPI<"signal.h"> {
     "sigprocmask",
     "sigemptyset",
     "sigaddset",
+    "signal",
   ];
 }
 

diff  --git a/libc/lib/CMakeLists.txt b/libc/lib/CMakeLists.txt
index b234c91704a9..748dac161043 100644
--- a/libc/lib/CMakeLists.txt
+++ b/libc/lib/CMakeLists.txt
@@ -23,6 +23,7 @@ add_entrypoint_library(
     sigaddset
     sigemptyset
     sigprocmask
+    signal
 
     # stdlib.h entrypoints
     _Exit

diff  --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index dfac8ebed3c7..8505b70c7eee 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -16,6 +16,8 @@ def StdC : StandardSpec<"stdc"> {
 
   PtrType IntPtr = PtrType<IntType>;
 
+  NamedType SigHandlerT = NamedType<"__sighandler_t">;
+
   HeaderSpec Assert = HeaderSpec<
       "assert.h",
       [
@@ -226,10 +228,16 @@ def StdC : StandardSpec<"stdc"> {
       ],
       [
         SizeTType,
+        SigHandlerT,
       ],
       [], // Enumerations
       [
         FunctionSpec<"raise", RetValSpec<IntType>, [ArgSpec<IntType>]>,
+        FunctionSpec<
+          "signal",
+          RetValSpec<SigHandlerT>,
+          [ArgSpec<IntType>, ArgSpec<SigHandlerT>]
+        >,
       ]
   >;
 

diff  --git a/libc/src/signal/linux/CMakeLists.txt b/libc/src/signal/linux/CMakeLists.txt
index 1d59b7502f7b..447818e0fd20 100644
--- a/libc/src/signal/linux/CMakeLists.txt
+++ b/libc/src/signal/linux/CMakeLists.txt
@@ -84,3 +84,15 @@ add_entrypoint_object(
     errno_h
     signal_h
 )
+
+add_entrypoint_object(
+  signal
+  SRCS
+    signal.cpp
+  HDRS
+    signal.h
+    ../signal.h
+  DEPENDS
+    sigaction
+    signal_h
+)

diff  --git a/libc/src/signal/linux/signal.cpp b/libc/src/signal/linux/signal.cpp
new file mode 100644
index 000000000000..5a7a12d6c842
--- /dev/null
+++ b/libc/src/signal/linux/signal.cpp
@@ -0,0 +1,26 @@
+//===------------------ Linux implementation of signal --------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#define __LLVM_LIBC_INTERNAL_SIGACTION
+#include "src/signal/signal.h"
+#include "src/signal/sigaction.h"
+
+#include "src/__support/common.h"
+
+namespace __llvm_libc {
+
+sighandler_t LLVM_LIBC_ENTRYPOINT(signal)(int signum, sighandler_t handler) {
+  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.
+  return __llvm_libc::sigaction(signum, &action, &old) == -1 ? SIG_ERR
+                                                             : old.sa_handler;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/signal/signal.h b/libc/src/signal/signal.h
new file mode 100644
index 000000000000..fb4e12d89ec5
--- /dev/null
+++ b/libc/src/signal/signal.h
@@ -0,0 +1,22 @@
+//===------------- Implementation header for signal ------------*- 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_SIGNAL_H
+#define LLVM_LIBC_SRC_SIGNAL_SIGNAL_H
+
+#include "include/signal.h"
+
+namespace __llvm_libc {
+
+using sighandler_t = __sighandler_t;
+
+sighandler_t signal(int signum, sighandler_t handler);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SIGNAL_SIGNAL_H

diff  --git a/libc/test/src/signal/CMakeLists.txt b/libc/test/src/signal/CMakeLists.txt
index db919b6f5d01..3fc33c3dbecc 100644
--- a/libc/test/src/signal/CMakeLists.txt
+++ b/libc/test/src/signal/CMakeLists.txt
@@ -52,3 +52,18 @@ add_libc_unittest(
     signal_h
     __errno_location
 )
+
+add_libc_unittest(
+  signal_test
+  SUITE
+    libc_signal_unittests
+  SRCS
+    signal_test.cpp
+  DEPENDS
+    signal
+    signal_h
+    sigaction
+    raise
+    __errno_location
+    errno_h
+)

diff  --git a/libc/test/src/signal/signal_test.cpp b/libc/test/src/signal/signal_test.cpp
new file mode 100644
index 000000000000..6be38fc27bdc
--- /dev/null
+++ b/libc/test/src/signal/signal_test.cpp
@@ -0,0 +1,41 @@
+//===------------------------ Unittests for signal ------------------------===//
+//
+// 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/signal.h"
+
+#include "utils/UnitTest/ErrnoSetterMatcher.h"
+#include "utils/UnitTest/Test.h"
+
+using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
+using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
+
+TEST(Signal, Invalid) {
+  llvmlibc_errno = 0;
+  __llvm_libc::sighandler_t valid = +[](int) {};
+  EXPECT_THAT((void *)__llvm_libc::signal(0, valid),
+              Fails(EINVAL, (void *)SIG_ERR));
+  EXPECT_THAT((void *)__llvm_libc::signal(65, valid),
+              Fails(EINVAL, (void *)SIG_ERR));
+}
+
+static int sum;
+TEST(Signal, Basic) {
+  // In case test get run multiple times.
+  sum = 0;
+  ASSERT_NE(__llvm_libc::signal(SIGUSR1, +[](int) { sum++; }),
+            SIG_ERR);
+  ASSERT_THAT(__llvm_libc::raise(SIGUSR1), Succeeds());
+  EXPECT_EQ(sum, 1);
+  for (int i = 0; i < 10; i++)
+    ASSERT_THAT(__llvm_libc::raise(SIGUSR1), Succeeds());
+  EXPECT_EQ(sum, 11);
+}

diff  --git a/libc/utils/UnitTest/Test.h b/libc/utils/UnitTest/Test.h
index 7982cd66a8cc..3c042de4c12d 100644
--- a/libc/utils/UnitTest/Test.h
+++ b/libc/utils/UnitTest/Test.h
@@ -249,13 +249,20 @@ class Test {
 #define UNIQUE_VAR(prefix) __CAT(prefix, __LINE__)
 
 #define EXPECT_THAT(MATCH, MATCHER)                                            \
-  auto UNIQUE_VAR(__matcher) = (MATCHER);                                      \
-  __llvm_libc::testing::Test::testMatch(                                       \
-      Ctx, UNIQUE_VAR(__matcher).match((MATCH)), UNIQUE_VAR(__matcher),        \
-      #MATCH, #MATCHER, __FILE__, __LINE__)
+  do {                                                                         \
+    auto UNIQUE_VAR(__matcher) = (MATCHER);                                    \
+    __llvm_libc::testing::Test::testMatch(                                     \
+        Ctx, UNIQUE_VAR(__matcher).match((MATCH)), UNIQUE_VAR(__matcher),      \
+        #MATCH, #MATCHER, __FILE__, __LINE__);                                 \
+  } while (0)
 
 #define ASSERT_THAT(MATCH, MATCHER)                                            \
-  if (!EXPECT_THAT(MATCH, MATCHER))                                            \
-  return
+  do {                                                                         \
+    auto UNIQUE_VAR(__matcher) = (MATCHER);                                    \
+    if (!__llvm_libc::testing::Test::testMatch(                                \
+            Ctx, UNIQUE_VAR(__matcher).match((MATCH)), UNIQUE_VAR(__matcher),  \
+            #MATCH, #MATCHER, __FILE__, __LINE__))                             \
+      return;                                                                  \
+  } while (0)
 
 #endif // LLVM_LIBC_UTILS_UNITTEST_H


        


More information about the libc-commits mailing list