Commit 7e2adb23 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

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

parent e8f1f73d
......@@ -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);
......@@ -118,14 +147,6 @@ SignalSet::maskSignals(const int mask) const {
sigprocmask(mask, &new_set, 0);
}
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()) {
......
......@@ -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_;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment