signal_set.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef SIGNAL_SET_H
  15. #define SIGNAL_SET_H
  16. #include <exceptions/exceptions.h>
  17. #include <boost/function.hpp>
  18. #include <boost/noncopyable.hpp>
  19. #include <boost/shared_ptr.hpp>
  20. #include <set>
  21. #include <signal.h>
  22. namespace isc {
  23. namespace util {
  24. /// @brief Exception thrown when the @c isc::util::io::SignalSet class
  25. /// experiences an error.
  26. class SignalSetError : public Exception {
  27. public:
  28. SignalSetError(const char* file, size_t line, const char* what) :
  29. isc::Exception(file, line, what) { };
  30. };
  31. /// @brief Forward declaration to the @c isc::util::io::SignalSet.
  32. class SignalSet;
  33. /// @brief Pointer to the @c isc::util::io::SignalSet.
  34. typedef boost::shared_ptr<SignalSet> SignalSetPtr;
  35. /// @brief Pointer to the signal handling function.
  36. typedef boost::function<void(int signum)> SignalHandler;
  37. /// @brief Pointer to a signal handling function which returns bool result.
  38. ///
  39. /// The handler is expected to return true if the signal it was given has
  40. /// been processed (i.e. should not be recorded for deferred processing) or
  41. /// false in which case it will be recorded.
  42. typedef boost::function<bool(int signum)> BoolSignalHandler;
  43. /// @brief Represents a collection of signals handled in a customized way.
  44. ///
  45. /// Kea processes must handle selected signals in a specialized way. For
  46. /// example: SIGINT and SIGTERM must perform a graceful shut down of the
  47. /// server. The SIGHUP signal is used to trigger server's reconfiguration.
  48. ///
  49. /// This class allows the caller to register one or more signals to catch
  50. /// and process. Signals may be handled either immediately upon arrival and/or
  51. /// recorded and processed later. To process signals immediately, the caller
  52. /// must register an "on-receipt" handler. This handler is expected to return
  53. /// a true or false indicating whether or not the signal has been processed.
  54. /// Signal occurrences that are not processed by the on-receipt handler are
  55. /// remembered by SignalSet for deferred processing. The caller can then query
  56. /// SignalSet at their discretion to determine if any signal occurrences are
  57. /// pending and process them.
  58. ///
  59. /// SignalSet uses an internal handler to catch all registered signals. When
  60. /// a signal arrives the internal handler will first attempt to invoke the
  61. /// on-receipt handler. If one has been registered it is passed the
  62. /// signal value as an argument and if it returns true upon completion, the
  63. /// internal handler will exit without further action. If the on-receipt
  64. /// handler returned false or one is not registered, then internal handler
  65. /// will record the signal value for deferred processing. Note that once a
  66. /// particular signal has been recorded, any further occurrences of that signal
  67. /// will be discarded until the original occurrence has been processed. This
  68. /// guards against rapid-fire occurrences of the same signal.
  69. ///
  70. /// @note This class is not thread safe. It uses static variables and
  71. /// functions to track a global state of signal registration and received
  72. /// signals' queue.
  73. class SignalSet : public boost::noncopyable {
  74. public:
  75. /// @brief Constructor installing one signal.
  76. ///
  77. /// @param sig0 First signal.
  78. /// @throw SignalSetError If attempting to add duplicated signal or
  79. /// the signal is invalid.
  80. SignalSet(const int sig0);
  81. /// @brief Constructor installing two signals.
  82. ///
  83. /// @param sig0 First signal.
  84. /// @param sig1 Second signal.
  85. /// @throw SignalSetError If attempting to add duplicated signal or
  86. /// the signal is invalid.
  87. SignalSet(const int sig0, const int sig1);
  88. /// @brief Constructor installing three signals.
  89. ///
  90. /// @param sig0 First signal.
  91. /// @param sig1 Second signal.
  92. /// @param sig2 Third signal.
  93. /// @throw SignalSetError If attempting to add duplicated signal or
  94. /// the signal is invalid.
  95. SignalSet(const int sig0, const int sig1, const int sig2);
  96. /// @brief Destructor.
  97. ///
  98. /// Removes installed handlers.
  99. ~SignalSet();
  100. /// @brief Installs the handler for the specified signal.
  101. ///
  102. /// This function adds a signal to the set. When the signal is received
  103. /// by the process, it will be recorded and a signal can be later handled
  104. /// by the process.
  105. ///
  106. /// @param sig Signal code.
  107. /// @throw SignalSetError if signal being added duplicates an existing
  108. /// signal.
  109. void add(const int sig);
  110. /// @brief Uninstalls all signals.
  111. ///
  112. /// This function calls @c isc::util::io::SignalSet::remove for each
  113. /// installed signal.
  114. void clear();
  115. /// @brief Returns a code of the next received signal.
  116. ///
  117. /// @return A code of the next received signal or -1 if there are no
  118. /// more signals received.
  119. int getNext() const;
  120. /// @brief Calls a handler for the next received signal.
  121. ///
  122. /// This function handles the next received signal and removes it from the
  123. /// queue of received signals. While the function is executed, all custom
  124. /// signal handlers are blocked to prevent race condition.
  125. ///
  126. /// @param signal_handler A pointer to the signal handler function to
  127. /// be used to handle the signal.
  128. void handleNext(SignalHandler signal_handler);
  129. /// @brief Uninstalls signal handler for a specified signal.
  130. ///
  131. /// @param sig A code of the signal to be removed.
  132. void remove(const int sig);
  133. /// @brief Registers a handler as the onreceipt signal handler
  134. ///
  135. /// Sets the given handler as the handler to invoke immediately
  136. /// upon receipt of a a registered signal.
  137. ///
  138. /// @note Currently, the on-receipt handler is stored as a static
  139. /// value and hence there may only be one such handler at a time
  140. /// for a given process.
  141. ///
  142. /// @param handler the signal handler to register
  143. static void setOnReceiptHandler(BoolSignalHandler handler);
  144. /// @brief Unregeisters the onreceipt signal handler
  145. static void clearOnReceiptHandler();
  146. /// @brief Invokes the onreceipt handler if it exists
  147. ///
  148. /// This static method is used by @c isc::util::io::SignalSet class to
  149. /// invoke the registered handler (if one) immediately upon receipt of
  150. /// a registered signal.
  151. ///
  152. /// Prior to invoking the handler, it sets signal action for the given
  153. /// signal to SIG_IGN which prevents any repeat signal occurences from
  154. /// queuing while the handler is executing. Upon completion of the handler,
  155. /// the signal action is restored which reenables receipt and handling of
  156. /// the signal.
  157. ///
  158. /// @param sig Signal number.
  159. /// @return Boolean false if no on-receipt handler was registered,
  160. /// otherwise it is the value returned by the on-receipt handler.
  161. static bool invokeOnReceiptHandler(int sig);
  162. private:
  163. /// @brief Blocks signals in the set.
  164. ///
  165. /// This function blocks the signals in a set to prevent race condition
  166. /// between the signal handler and the new signal coming in.
  167. void block() const {
  168. maskSignals(SIG_BLOCK);
  169. }
  170. /// @brief Removes the signal from the set.
  171. ///
  172. /// This function removes only a signal which is owned by this signal set.
  173. ///
  174. /// @param sig Signal to be removed.
  175. /// @throw SignalSetError if the signal being removed is not owned by this
  176. /// signal set.
  177. void erase(const int sig);
  178. /// @brief Insert a signal to the set.
  179. ///
  180. /// @param sig Signal to be inserted.
  181. /// @throw SignalSetError if a signal being inserted has already been
  182. /// registered in this or other signal set.
  183. void insert(const int sig);
  184. /// @brief Applies a mask to all signals in the set.
  185. ///
  186. /// This function is used by @c SignalSet::block and @c SignalSet::unblock
  187. /// to apply the SIG_BLOCK and SIG_UNBLOCK mask to signals.
  188. ///
  189. /// @param mask A mask to be applied to all signals.
  190. void maskSignals(const int mask) const;
  191. /// @brief Pops a next signal number from the static collection of signals.
  192. ///
  193. /// The static collection of signals is updated by the internal signal
  194. /// handler being invoked when one of the installed signals is received by
  195. /// the process. This function removes the first element of the collection.
  196. void popNext();
  197. /// @brief Unblocks signals in the set.
  198. ///
  199. /// This function unblocks the signals in a set.
  200. void unblock() const {
  201. maskSignals(SIG_UNBLOCK);
  202. }
  203. /// @brief Stores the set of signals registered in this signal set.
  204. std::set<int> local_signals_;
  205. };
  206. }
  207. }
  208. #endif // SIGNAL_SET_H