From 9c97d2c4ef34256817fd39bdbaecdfafda4080df Mon Sep 17 00:00:00 2001 From: "William A. Kennington III" Date: Fri, 2 Nov 2018 17:25:36 -0700 Subject: signal: Add idempotent block function This makes it trivial to block individual signals from being handled by a thread. Useful when tryng to set up signal handling in event loops. Tested: Builds and passes unit tests. Change-Id: I61739debe2a47ec0ec3e767cf138125c6f59165f Signed-off-by: William A. Kennington III --- .gitignore | 2 +- src/Makefile.am | 4 +-- src/stdplus/placeholder.cpp | 1 - src/stdplus/placeholder.hpp | 1 - src/stdplus/signal.cpp | 32 +++++++++++++++++++++++ src/stdplus/signal.hpp | 17 +++++++++++++ test/Makefile.am | 8 +++--- test/placeholder.cpp | 5 ---- test/signal.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 118 insertions(+), 14 deletions(-) delete mode 100644 src/stdplus/placeholder.cpp delete mode 100644 src/stdplus/placeholder.hpp create mode 100644 src/stdplus/signal.cpp create mode 100644 src/stdplus/signal.hpp delete mode 100644 test/placeholder.cpp create mode 100644 test/signal.cpp diff --git a/.gitignore b/.gitignore index 7d1eea5..205819a 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,4 @@ Makefile.in /src/stdplus.pc # Output binaries -/test/placeholder +/test/signal diff --git a/src/Makefile.am b/src/Makefile.am index de5de8d..5e935f4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,5 +4,5 @@ lib_LTLIBRARIES = libstdplus.la libstdplus_la_SOURCES = libstdplus_la_LIBADD = $(COMMON_LIBS) -nobase_include_HEADERS += stdplus/placeholder.hpp -libstdplus_la_SOURCES += stdplus/placeholder.cpp +nobase_include_HEADERS += stdplus/signal.hpp +libstdplus_la_SOURCES += stdplus/signal.cpp diff --git a/src/stdplus/placeholder.cpp b/src/stdplus/placeholder.cpp deleted file mode 100644 index a4c9e2b..0000000 --- a/src/stdplus/placeholder.cpp +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/src/stdplus/placeholder.hpp b/src/stdplus/placeholder.hpp deleted file mode 100644 index 6f70f09..0000000 --- a/src/stdplus/placeholder.hpp +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/src/stdplus/signal.cpp b/src/stdplus/signal.cpp new file mode 100644 index 0000000..10f8e39 --- /dev/null +++ b/src/stdplus/signal.cpp @@ -0,0 +1,32 @@ +#include +#include +#include + +namespace stdplus +{ +namespace signal +{ + +void block(int signum) +{ + sigset_t set; + if (sigprocmask(SIG_BLOCK, nullptr, &set) < 0) + { + throw std::system_error(errno, std::generic_category(), + "sigprocmask get"); + } + + if (sigaddset(&set, signum) < 0) + { + throw std::system_error(errno, std::generic_category(), "sigaddset"); + } + + if (sigprocmask(SIG_BLOCK, &set, nullptr) < 0) + { + throw std::system_error(errno, std::generic_category(), + "sigprocmask set"); + } +} + +} // namespace signal +} // namespace stdplus diff --git a/src/stdplus/signal.hpp b/src/stdplus/signal.hpp new file mode 100644 index 0000000..465181b --- /dev/null +++ b/src/stdplus/signal.hpp @@ -0,0 +1,17 @@ +#pragma once + +namespace stdplus +{ +namespace signal +{ + +/** @brief Blocks the signal from being handled by the designated + * sigaction. If the signal is already blocked this does nothing. + * + * @param[in] signum - The int representing the signal to block + * @throws std::system_error if any underlying error occurs. + */ +void block(int signum); + +} // namespace signal +} // namespace stdplus diff --git a/test/Makefile.am b/test/Makefile.am index c67e07a..1c4a5a1 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -7,7 +7,7 @@ gtest_ldadd = $(STDPLUS_LIBS) $(GTEST_LIBS) $(GMOCK_LIBS) -lgmock_main check_PROGRAMS = TESTS = $(check_PROGRAMS) -check_PROGRAMS += placeholder -placeholder_SOURCES = placeholder.cpp -placeholder_CPPFLAGS = $(gtest_cppflags) -placeholder_LDADD = $(gtest_ldadd) +check_PROGRAMS += signal +signal_SOURCES = signal.cpp +signal_CPPFLAGS = $(gtest_cppflags) +signal_LDADD = $(gtest_ldadd) diff --git a/test/placeholder.cpp b/test/placeholder.cpp deleted file mode 100644 index 782277f..0000000 --- a/test/placeholder.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include - -TEST(PlaceholderTest, None) -{ -} diff --git a/test/signal.cpp b/test/signal.cpp new file mode 100644 index 0000000..6389cd8 --- /dev/null +++ b/test/signal.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +namespace stdplus +{ +namespace signal +{ +namespace +{ + +TEST(SignalTest, BlockSignal) +{ + constexpr int s = SIGINT; + constexpr int otherS = SIGTERM; + constexpr int notBlocked = SIGPROF; + + sigset_t expectedSet; + EXPECT_EQ(0, sigprocmask(SIG_BLOCK, nullptr, &expectedSet)); + EXPECT_EQ(0, sigaddset(&expectedSet, otherS)); + EXPECT_EQ(0, sigprocmask(SIG_BLOCK, &expectedSet, nullptr)); + EXPECT_EQ(0, sigismember(&expectedSet, notBlocked)); + EXPECT_EQ(0, sigismember(&expectedSet, s)); + EXPECT_EQ(0, sigaddset(&expectedSet, s)); + + block(s); + + sigset_t newSet; + EXPECT_EQ(0, sigprocmask(SIG_BLOCK, nullptr, &newSet)); + EXPECT_EQ(sigismember(&expectedSet, s), sigismember(&newSet, s)); + EXPECT_EQ(sigismember(&expectedSet, otherS), sigismember(&newSet, otherS)); + EXPECT_EQ(sigismember(&expectedSet, notBlocked), + sigismember(&newSet, notBlocked)); +} + +TEST(SignalTest, KeepBlockSignal) +{ + constexpr int s = SIGINT; + constexpr int otherS = SIGTERM; + constexpr int notBlocked = SIGPROF; + + sigset_t expectedSet; + EXPECT_EQ(0, sigprocmask(SIG_BLOCK, nullptr, &expectedSet)); + EXPECT_EQ(0, sigaddset(&expectedSet, s)); + EXPECT_EQ(0, sigaddset(&expectedSet, otherS)); + EXPECT_EQ(0, sigismember(&expectedSet, notBlocked)); + EXPECT_EQ(0, sigprocmask(SIG_BLOCK, &expectedSet, nullptr)); + + block(s); + + sigset_t newSet; + EXPECT_EQ(0, sigprocmask(SIG_BLOCK, nullptr, &newSet)); + EXPECT_EQ(sigismember(&expectedSet, s), sigismember(&newSet, s)); + EXPECT_EQ(sigismember(&expectedSet, otherS), sigismember(&newSet, otherS)); + EXPECT_EQ(sigismember(&expectedSet, notBlocked), + sigismember(&newSet, notBlocked)); +} + +} // namespace +} // namespace signal +} // namespace stdplus -- cgit v1.2.3