Browse Source

[3405] Cleanup in the isc::util::io::SignalSet class.

Marcin Siodelski 11 years ago
parent
commit
7e2adb23b0
2 changed files with 105 additions and 14 deletions
  1. 29 8
      src/lib/util/io/signal_set.cc
  2. 76 6
      src/lib/util/io/signal_set.h

+ 29 - 8
src/lib/util/io/signal_set.cc

@@ -21,11 +21,23 @@ using namespace isc::util::io;
 
 namespace {
 
+/// @brief Returns a pointer to static collection of signals.
+///
+/// @return Static collection of signals.
 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();
@@ -37,6 +49,18 @@ void internalHandler(int sig) {
     states->push_back(sig);
 }
 
+/// @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() {
+    std::list<int>* states = getSignalStates();
+    if (!states->empty()) {
+        states->pop_front();
+    }
+}
+
 }
 
 namespace isc {
@@ -58,6 +82,11 @@ SignalSet::SignalSet(const int sig0, const int sig1, const int sig2) {
     add(sig2);
 }
 
+SignalSet::~SignalSet() {
+    // Set default signal handlers.
+    clear();
+}
+
 void
 SignalSet::add(const int sig) {
     std::pair<Pool::iterator, bool> ret = registered_signals_.insert(sig);
@@ -119,14 +148,6 @@ SignalSet::maskSignals(const int mask) const {
 }
 
 void
-SignalSet::popNext() const {
-    std::list<int>* states = getSignalStates();
-    if (!states->empty()) {
-        states->pop_front();
-    }
-}
-
-void
 SignalSet::remove(const int sig) {
     if (registered_signals_.find(sig) != registered_signals_.end()) {
         struct sigaction sa;

+ 76 - 6
src/lib/util/io/signal_set.h

@@ -32,52 +32,122 @@ public:
         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.
 class SignalSet : public boost::noncopyable {
 private:
+    /// @brief Defines a type representing a collection of signals.
     typedef std::set<int> Pool;
 
 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 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);
     }
 
-    Pool::iterator erase(const int signal);
-
+    /// @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;
 
-    void popNext() const;
-
+    /// @brief Unblocks signals in the set.
+    ///
+    /// This function unblocks the signals in a set.
     void unblock() const {
         maskSignals(SIG_UNBLOCK);
     }
 
+    /// @brief Holds a collection of installed signals.
     Pool registered_signals_;
 };