AsyncSignalHandler.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. * Copyright 2015-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/io/async/AsyncSignalHandler.h>
  17. #include <folly/io/async/EventBase.h>
  18. #include <folly/Conv.h>
  19. using std::make_pair;
  20. using std::pair;
  21. using std::string;
  22. namespace folly {
  23. AsyncSignalHandler::AsyncSignalHandler(EventBase* eventBase)
  24. : eventBase_(eventBase) {}
  25. AsyncSignalHandler::~AsyncSignalHandler() {
  26. // Unregister any outstanding events
  27. for (SignalEventMap::iterator it = signalEvents_.begin();
  28. it != signalEvents_.end();
  29. ++it) {
  30. event_del(&it->second);
  31. }
  32. }
  33. void AsyncSignalHandler::attachEventBase(EventBase* eventBase) {
  34. assert(eventBase_ == nullptr);
  35. assert(signalEvents_.empty());
  36. eventBase_ = eventBase;
  37. }
  38. void AsyncSignalHandler::detachEventBase() {
  39. assert(eventBase_ != nullptr);
  40. assert(signalEvents_.empty());
  41. eventBase_ = nullptr;
  42. }
  43. void AsyncSignalHandler::registerSignalHandler(int signum) {
  44. pair<SignalEventMap::iterator, bool> ret =
  45. signalEvents_.insert(make_pair(signum, event()));
  46. if (!ret.second) {
  47. // This signal has already been registered
  48. throw std::runtime_error(
  49. folly::to<string>("handler already registered for signal ", signum));
  50. }
  51. struct event* ev = &(ret.first->second);
  52. try {
  53. signal_set(ev, signum, libeventCallback, this);
  54. if (event_base_set(eventBase_->getLibeventBase(), ev) != 0) {
  55. throw std::runtime_error(folly::to<string>(
  56. "error initializing event handler for signal ", signum));
  57. }
  58. if (event_add(ev, nullptr) != 0) {
  59. throw std::runtime_error(
  60. folly::to<string>("error adding event handler for signal ", signum));
  61. }
  62. } catch (...) {
  63. signalEvents_.erase(ret.first);
  64. throw;
  65. }
  66. }
  67. void AsyncSignalHandler::unregisterSignalHandler(int signum) {
  68. SignalEventMap::iterator it = signalEvents_.find(signum);
  69. if (it == signalEvents_.end()) {
  70. throw std::runtime_error(folly::to<string>(
  71. "unable to unregister handler for signal ",
  72. signum,
  73. ": signal not registered"));
  74. }
  75. event_del(&it->second);
  76. signalEvents_.erase(it);
  77. }
  78. void AsyncSignalHandler::libeventCallback(
  79. libevent_fd_t signum,
  80. short /* events */,
  81. void* arg) {
  82. AsyncSignalHandler* handler = static_cast<AsyncSignalHandler*>(arg);
  83. handler->signalReceived(int(signum));
  84. }
  85. } // namespace folly