diff options
author | Marcin Siodelski <marcin@isc.org> | 2014-06-04 21:42:12 +0200 |
---|---|---|
committer | Marcin Siodelski <marcin@isc.org> | 2014-06-04 21:42:12 +0200 |
commit | 6c18e5addb9d96bfe66a4c1aa34fde48a00f3e4b (patch) | |
tree | 938ee80ddee02ceee10affa5bcc09e248ef2871b /src/lib/util/io | |
parent | [3405] Include shell test scripts when performing distcheck. (diff) | |
download | kea-6c18e5addb9d96bfe66a4c1aa34fde48a00f3e4b.tar.xz kea-6c18e5addb9d96bfe66a4c1aa34fde48a00f3e4b.zip |
[3405] Moved SignalSet class to util from util:io.
Diffstat (limited to 'src/lib/util/io')
-rw-r--r-- | src/lib/util/io/Makefile.am | 3 | ||||
-rw-r--r-- | src/lib/util/io/signal_set.cc | 227 | ||||
-rw-r--r-- | src/lib/util/io/signal_set.h | 189 | ||||
-rw-r--r-- | src/lib/util/io/tests/Makefile.am | 31 | ||||
-rw-r--r-- | src/lib/util/io/tests/run_unittests.cc | 23 | ||||
-rw-r--r-- | src/lib/util/io/tests/signal_set_unittest.cc | 188 |
6 files changed, 1 insertions, 660 deletions
diff --git a/src/lib/util/io/Makefile.am b/src/lib/util/io/Makefile.am index c0fae76b1f..8a1522d734 100644 --- a/src/lib/util/io/Makefile.am +++ b/src/lib/util/io/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = . tests +SUBDIRS = . AM_CXXFLAGS = $(B10_CXXFLAGS) AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib @@ -7,7 +7,6 @@ AM_CPPFLAGS += $(BOOST_INCLUDES) lib_LTLIBRARIES = libkea-util-io.la libkea_util_io_la_SOURCES = fd.h fd.cc fd_share.h fd_share.cc libkea_util_io_la_SOURCES += socketsession.h socketsession.cc sockaddr_util.h -libkea_util_io_la_SOURCES += signal_set.cc signal_set.h libkea_util_io_la_SOURCES += pktinfo_utilities.h libkea_util_io_la_LIBADD = $(top_builddir)/src/lib/exceptions/libkea-exceptions.la diff --git a/src/lib/util/io/signal_set.cc b/src/lib/util/io/signal_set.cc deleted file mode 100644 index b187df69d1..0000000000 --- a/src/lib/util/io/signal_set.cc +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include <util/io/signal_set.h> - -#include <cerrno> -#include <list> - -using namespace isc; -using namespace isc::util::io; - -namespace { - -/// @brief Returns a pointer to the global set of registered signals. -/// -/// Multiple instances of @c SignalSet may use this pointer to access -/// and update the set. -/// -/// @return Pointer to the global set of registered signals. This pointer -/// is always initialized and points to a valid object. -std::set<int>* getRegisteredSignals() { - static std::set<int> registered_signals; - return (®istered_signals); -} - -/// @brief Returns a pointer to static collection of signals received. -/// -/// Multiple instances of @c SignalSet may use this pointer to access -/// and update the queue of signals received. -/// -/// @return Static collection of signals received. This pointer is always -/// initialized and points to a valid object. -std::list<int>* getSignalStates() { - static std::list<int> states; - return (&states); -} - -/// @brief Internal signal handler for @c isc::util::io::SignalSet class. -/// -/// This signal handler adds a signal number for which it is being -/// invoked to the queue of received signals. It prevents adding duplicated -/// signals. All duplicated signals are dropped. This prevents hammering -/// a process to invoke handlers (e.g. DHCP server reconfiguration), when -/// many the same signals are received one after another. -/// -/// @param sig Signal number. -void internalHandler(int sig) { - std::list<int>* states = getSignalStates(); - for (std::list<int>::const_iterator it = states->begin(); - it != states->end(); ++it) { - if (sig == *it) { - return; - } - } - states->push_back(sig); -} - -} - -namespace isc { -namespace util { -namespace io { - -SignalSet::SignalSet(const int sig0) { - add(sig0); -} - -SignalSet::SignalSet(const int sig0, const int sig1) { - add(sig0); - add(sig1); -} - -SignalSet::SignalSet(const int sig0, const int sig1, const int sig2) { - add(sig0); - add(sig1); - add(sig2); -} - -SignalSet::~SignalSet() { - // Set default signal handlers. - try { - clear(); - } catch (...) { - // Not a good thing to throw from a destructor. in fact this should - // not throw an exception because we just unregister the signals - // that we have previously registered. So the signal codes are fine. - } -} - -void -SignalSet::add(const int sig) { - insert(sig); - struct sigaction sa; - sa.sa_handler = internalHandler; - if (sigaction(sig, &sa, 0) < 0) { - erase(sig); - isc_throw(SignalSetError, "failed to register a signal handler for" - " signal " << sig << ": " << strerror(errno)); - } -} - -void -SignalSet::clear() { - // Iterate over a copy of the registered signal set because the - // remove function is erasing the elements and we don't want to - // erase the elements we are iterating over. This would cause - // a segfault. - std::set<int> all_signals = local_signals_; - for (std::set<int>::const_iterator it = all_signals.begin(); - it != all_signals.end(); ++it) { - remove(*it); - } -} - -int -SignalSet::getNext() const { - std::list<int>* states = getSignalStates(); - for (std::list<int>::iterator it = states->begin(); - it != states->end(); ++it) { - if (local_signals_.find(*it) != local_signals_.end()) { - return (*it); - } - } - return (-1); -} - -void -SignalSet::erase(const int sig) { - if (local_signals_.find(sig) == local_signals_.end()) { - isc_throw(SignalSetError, "failed to unregister signal " << sig - << " from a signal set: signal is not owned by the" - " signal set"); - } - // Remove globally registered signal. - getRegisteredSignals()->erase(sig); - // Remove unhandled signals from the queue. - for (std::list<int>::iterator it = getSignalStates()->begin(); - it != getSignalStates()->end(); ++it) { - if (*it == sig) { - it = getSignalStates()->erase(it); - } - } - // Remove locally registered signal. - local_signals_.erase(sig); -} - -void -SignalSet::handleNext(SignalHandler signal_handler) { - block(); - int signum = getNext(); - if (signum >= 0) { - popNext(); - try { - signal_handler(signum); - } catch (...) { - unblock(); - throw; - } - } - unblock(); -} - -void -SignalSet::insert(const int sig) { - std::set<int>* global_signals = getRegisteredSignals(); - if ((global_signals->find(sig) != global_signals->end()) || - (local_signals_.find(sig) != local_signals_.end())) { - isc_throw(SignalSetError, "attempt to register a duplicate signal " - << sig); - } - global_signals->insert(sig); - local_signals_.insert(sig); -} - -void -SignalSet::maskSignals(const int mask) const { - sigset_t new_set; - for (std::set<int>::const_iterator it = getRegisteredSignals()->begin(); - it != getRegisteredSignals()->end(); ++it) { - sigaddset(&new_set, *it); - } - sigprocmask(mask, &new_set, 0); -} - -void -SignalSet::popNext() { - std::list<int>* states = getSignalStates(); - for (std::list<int>::iterator it = states->begin(); - it != states->end(); ++it) { - if (local_signals_.find(*it) != local_signals_.end()) { - states->erase(it); - return; - } - } -} - -void -SignalSet::remove(const int sig) { - // Unregister only if we own this signal. - if (local_signals_.find(sig) != local_signals_.end()) { - struct sigaction sa; - sa.sa_handler = SIG_DFL; - if (sigaction(sig, &sa, 0) < 0) { - isc_throw(SignalSetError, "unable to restore original signal" - " handler for signal: " << sig); - } - erase(sig); - } else { - isc_throw(SignalSetError, "failed to unregister signal " << sig - << ": this signal is not owned by the signal set"); - } -} - -} // end of isc::util::io -} // end of isc::util -} // end of isc diff --git a/src/lib/util/io/signal_set.h b/src/lib/util/io/signal_set.h deleted file mode 100644 index 5d52559568..0000000000 --- a/src/lib/util/io/signal_set.h +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#ifndef SIGNAL_SET_H -#define SIGNAL_SET_H - -#include <exceptions/exceptions.h> -#include <boost/function.hpp> -#include <boost/noncopyable.hpp> -#include <boost/shared_ptr.hpp> -#include <set> -#include <signal.h> - -namespace isc { -namespace util { -namespace io { - -/// @brief Exception thrown when the @c isc::util::io::SignalSet class -/// experiences an error. -class SignalSetError : public Exception { -public: - SignalSetError(const char* file, size_t line, const char* what) : - isc::Exception(file, line, what) { }; -}; - -/// @brief Forward declaration to the @c isc::util::io::SignalSet. -class SignalSet; -/// @brief Pointer to the @c isc::util::io::SignalSet. -typedef boost::shared_ptr<SignalSet> SignalSetPtr; -/// @brief Pointer to the signal handling function. -typedef boost::function<void(int signum)> SignalHandler; - -/// @brief Represents a collection of signals handled in a customized way. -/// -/// Kea processes must handle selected signals in a specialized way. For -/// example: SIGINT and SIGTERM must perform a graceful shut down of the -/// server. The SIGHUP signal is used to trigger server's reconfiguration. -/// -/// This class allows specifying signals which should be handled in a -/// specialized way as well as specifying a signal handler function. -/// When a signal is received the signal handler function is called and -/// the code of the received signal is recorded. This function doesn't -/// do anything beyond recording the signal number to minimize the time -/// spent on handling the signal and process interruption. The process -/// can later check the signals received and call the handlers on its -/// descretion by calling a @c isc::util::io::SignalSet::handleNext function. -/// -/// @note This class is not thread safe. It uses static variables and -/// functions to track a global state of signal registration and received -/// signals' queue. -class SignalSet : public boost::noncopyable { -public: - - /// @brief Constructor installing one signal. - /// - /// @param sig0 First signal. - /// @throw SignalSetError If attempting to add duplicated signal or - /// the signal is invalid. - SignalSet(const int sig0); - - /// @brief Constructor installing two signals. - /// - /// @param sig0 First signal. - /// @param sig1 Second signal. - /// @throw SignalSetError If attempting to add duplicated signal or - /// the signal is invalid. - SignalSet(const int sig0, const int sig1); - - /// @brief Constructor installing three signals. - /// - /// @param sig0 First signal. - /// @param sig1 Second signal. - /// @param sig2 Third signal. - /// @throw SignalSetError If attempting to add duplicated signal or - /// the signal is invalid. - SignalSet(const int sig0, const int sig1, const int sig2); - - /// @brief Destructor. - /// - /// Removes installed handlers. - ~SignalSet(); - - /// @brief Installs the handler for the specified signal. - /// - /// This function adds a signal to the set. When the signal is received - /// by the process, it will be recorded and a signal can be later handled - /// by the process. - /// - /// @param sig Signal code. - /// @throw SignalSetError if signal being added duplicates an existing - /// signal. - void add(const int sig); - - /// @brief Uninstalls all signals. - /// - /// This function calls @c isc::util::io::SignalSet::remove for each - /// installed signal. - void clear(); - - /// @brief Returns a code of the next received signal. - /// - /// @return A code of the next received signal or -1 if there are no - /// more signals received. - int getNext() const; - - /// @brief Calls a handler for the next received signal. - /// - /// This function handles the next received signal and removes it from the - /// queue of received signals. While the function is executed, all custom - /// signal handlers are blocked to prevent race condition. - /// - /// @param signal_handler A pointer to the signal handler function to - /// be used to handle the signal. - void handleNext(SignalHandler signal_handler); - - /// @brief Uninstalls signal handler for a specified signal. - /// - /// @param sig A code of the signal to be removed. - void remove(const int sig); - -private: - - /// @brief Blocks signals in the set. - /// - /// This function blocks the signals in a set to prevent race condition - /// between the signal handler and the new signal coming in. - void block() const { - maskSignals(SIG_BLOCK); - } - - /// @brief Removes the signal from the set. - /// - /// This function removes only a signal which is owned by this signal set. - /// - /// @param sig Signal to be removed. - /// @throw SignalSetError if the signal being removed is not owned by this - /// signal set. - void erase(const int sig); - - /// @brief Insert a signal to the set. - /// - /// @param sig Signal to be inserted. - /// @throw SignalSetError if a signal being inserted has already been - /// registered in this or other signal set. - void insert(const int sig); - - /// @brief Applies a mask to all signals in the set. - /// - /// This function is used by @c SignalSet::block and @c SignalSet::unblock - /// to apply the SIG_BLOCK and SIG_UNBLOCK mask to signals. - /// - /// @param mask A mask to be applied to all signals. - void maskSignals(const int mask) const; - - /// @brief Pops a next signal number from the static collection of signals. - /// - /// The static collection of signals is updated by the internal signal - /// handler being invoked when one of the installed signals is received by - /// the process. This function removes the first element of the collection. - void popNext(); - - /// @brief Unblocks signals in the set. - /// - /// This function unblocks the signals in a set. - void unblock() const { - maskSignals(SIG_UNBLOCK); - } - - /// @brief Stores the set of signals registered in this signal set. - std::set<int> local_signals_; -}; - -} -} -} - -#endif // SIGNAL_SET_H - diff --git a/src/lib/util/io/tests/Makefile.am b/src/lib/util/io/tests/Makefile.am deleted file mode 100644 index d71c28b8c3..0000000000 --- a/src/lib/util/io/tests/Makefile.am +++ /dev/null @@ -1,31 +0,0 @@ -SUBDIRS = . - -AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib -AM_CPPFLAGS += $(BOOST_INCLUDES) -AM_CXXFLAGS = $(B10_CXXFLAGS) - -if USE_STATIC_LINK -AM_LDFLAGS = -static -endif - -CLEANFILES = *.gcno *.gcda - -TESTS_ENVIRONMENT = \ - $(LIBTOOL) --mode=execute $(VALGRIND_COMMAND) - -TESTS = -if HAVE_GTEST -TESTS += run_unittests -run_unittests_SOURCES = run_unittests.cc -run_unittests_SOURCES += signal_set_unittest.cc - -run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) -run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) - -run_unittests_LDADD = $(top_builddir)/src/lib/exceptions/libkea-exceptions.la -run_unittests_LDADD += $(top_builddir)/src/lib/util/io/libkea-util-io.la -run_unittests_LDADD += $(GTEST_LDADD) - -endif - -noinst_PROGRAMS = $(TESTS) diff --git a/src/lib/util/io/tests/run_unittests.cc b/src/lib/util/io/tests/run_unittests.cc deleted file mode 100644 index 304c652382..0000000000 --- a/src/lib/util/io/tests/run_unittests.cc +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include <log/logger_support.h> -#include <gtest/gtest.h> - -int -main(int argc, char* argv[]) { - ::testing::InitGoogleTest(&argc, argv); - int result = RUN_ALL_TESTS(); - return (result); -} diff --git a/src/lib/util/io/tests/signal_set_unittest.cc b/src/lib/util/io/tests/signal_set_unittest.cc deleted file mode 100644 index 9fcd4fda47..0000000000 --- a/src/lib/util/io/tests/signal_set_unittest.cc +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include <util/io/signal_set.h> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <gtest/gtest.h> -#include <signal.h> - -namespace { - -using namespace isc; -using namespace isc::util::io; - -/// @brief Test fixture class for @c isc::util::io::SignalSet class. -/// -/// This class contains a handler function which records the signal -/// being handled. It allows for checking whether the signal set -/// has invoked the handler for the expected signal. -class SignalSetTest : public ::testing::Test { -public: - - /// @brief Constructor. - /// - /// Resets the signal sets and variables being modified by the - /// signal handler function. - SignalSetTest() - : signal_set_(), - secondary_signal_set_() { - handler_calls_ = 0; - signum_ = -1; - } - - /// @brief Destructor. - /// - /// Uninstalls the signals from the signal sets. - ~SignalSetTest() { - if (signal_set_) { - signal_set_->clear(); - } - if (secondary_signal_set_) { - secondary_signal_set_->clear(); - } - } - - /// @brief Signal handler used by unit tests. - /// - /// @param signum Signal being handled. - static void testHandler(int signum) { - signum_ = signum; - ++handler_calls_; - } - - /// @brief Number of handler calls so far. - static int handler_calls_; - /// @brief The last signal handled. - static int signum_; - /// @brief Test signal set object. - SignalSetPtr signal_set_; - /// @brief Second signal set object. - SignalSetPtr secondary_signal_set_; -}; - -int SignalSetTest::handler_calls_ = 0; -int SignalSetTest::signum_ = -1; - -/// Check that the signals are recorded by the signal handlers. -TEST_F(SignalSetTest, twoSignals) { - // Register handlers for two signals. - signal_set_.reset(new SignalSet(SIGHUP, SIGINT)); - // Send SIGHUP signal to the process. - ASSERT_EQ(0, raise(SIGHUP)); - // The SIGHUP should be the next one in the queue to be handled. - EXPECT_EQ(SIGHUP, signal_set_->getNext()); - // But, no handlers should have been called yet. - EXPECT_EQ(0, handler_calls_); - // Send a different signal. - ASSERT_EQ(0, raise(SIGINT)); - // The SIGHUP hasn't been handled yet so it should still be the first - // one in the queue. - EXPECT_EQ(SIGHUP, signal_set_->getNext()); - // No handlers have been called yet. - EXPECT_EQ(0, handler_calls_); - // Raise another SIGHUP before the first one has been handled. The - // second one should be dropped. - ASSERT_EQ(0, raise(SIGHUP)); - // Execute the first handler (for SIGHUP). - signal_set_->handleNext(boost::bind(&SignalSetTest::testHandler, _1)); - // The handler should have been called once and the signal - // handled should be SIGHUP. - EXPECT_EQ(1, handler_calls_); - EXPECT_EQ(SIGHUP, signum_); - // Next signal to be handled should be SIGINT. - EXPECT_EQ(SIGINT, signal_set_->getNext()); - signal_set_->handleNext(boost::bind(&SignalSetTest::testHandler, _1)); - EXPECT_EQ(2, handler_calls_); - EXPECT_EQ(SIGINT, signum_); - // There should be no more waiting handlers. - EXPECT_EQ(-1, signal_set_->getNext()); - // Make sure that signals can be unregistered. - EXPECT_NO_THROW(signal_set_->remove(SIGHUP)); - EXPECT_NO_THROW(signal_set_->remove(SIGINT)); -} - -/// Check that the signal set can only handle signals owned by it. -TEST_F(SignalSetTest, twoSignalSets) { - // Register handler for SIGHUP in the first signal set. - signal_set_.reset(new SignalSet(SIGHUP)); - // Register handler for SIGINT in the second signal set. - secondary_signal_set_.reset(new SignalSet(SIGINT)); - // Send SIGHUP. - ASSERT_EQ(0, raise(SIGHUP)); - // Send SIGINT. - ASSERT_EQ(0, raise(SIGINT)); - // Although the SIGHUP is the first signal received by the process - // it is not owned by the secondary signal set. The first signal - // to be handled by the secondary signal set is SIGINT. - EXPECT_EQ(SIGINT, secondary_signal_set_->getNext()); - // The signal set owns SIGHUP so it should be the next to handle. - EXPECT_EQ(SIGHUP, signal_set_->getNext()); - // Handle next signal owned by the secondary signal set. - secondary_signal_set_->handleNext(boost::bind(&SignalSetTest::testHandler, - _1)); - EXPECT_EQ(1, handler_calls_); - EXPECT_EQ(SIGINT, signum_); - // No more signals to be handled for this signal set. - EXPECT_EQ(-1, secondary_signal_set_->getNext()); - // Handle next signal owned by the signal set. - signal_set_->handleNext(boost::bind(&SignalSetTest::testHandler, _1)); - EXPECT_EQ(2, handler_calls_); - EXPECT_EQ(SIGHUP, signum_); - // No more signals to be handled by this signal set. - EXPECT_EQ(-1, signal_set_->getNext()); -} - -// Check that each signal set removes only the signals that it has been used -// to register. -TEST_F(SignalSetTest, remove) { - // Register handlers for SIGHUP using one signal set. - ASSERT_NO_THROW(signal_set_.reset(new SignalSet(SIGHUP))); - // Define another signal set and register a different signal. - ASSERT_NO_THROW(secondary_signal_set_.reset(new SignalSet(SIGINT))); - // The SIGHUP has been already registsred with the other signal - // set, so it should not be possible to register it again. - ASSERT_THROW(secondary_signal_set_->add(SIGHUP), SignalSetError); - // It shouldn't be possible to remove the signal registered in a different - // signal set. - ASSERT_THROW(secondary_signal_set_->remove(SIGHUP), SignalSetError); - // Remove all signals from the first signal set. The signals registered - // with the other signal signal set should be preserved. - ASSERT_NO_THROW(signal_set_->clear()); - // Check indirectly that the SIGINT is still registered. An attempt to - // register registered signal should result in failure. - EXPECT_THROW(secondary_signal_set_->add(SIGINT), SignalSetError); - // But, we should be able to regsiter SIGHUP. - EXPECT_NO_THROW(secondary_signal_set_->add(SIGHUP)); -} - -/// Check that it is not possible to duplicate signals. -TEST_F(SignalSetTest, duplicates) { - ASSERT_NO_THROW(signal_set_.reset(new SignalSet(SIGHUP))); - // It shouldn't be possible to register the same signal. - EXPECT_THROW(signal_set_->add(SIGHUP), SignalSetError); - // But ok to register a different one. - EXPECT_NO_THROW(signal_set_->add(SIGTERM)); - // Now, let's define other signal set. - SignalSetPtr other; - // SIGINT hasn't been registered in the first signal set - // so it should be fine to register. - ASSERT_NO_THROW(other.reset(new SignalSet(SIGINT))); - // SIGHUP has been already registered in the first signal set so - // an attempt to register it again should result in a failure. - EXPECT_THROW(other->add(SIGHUP), SignalSetError); -} - - -} // end of anonymous namespace |