2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <folly/io/async/AsyncSignalHandler.h>
18 #include <folly/io/async/EventBase.h>
20 #include <folly/Conv.h>
28 AsyncSignalHandler::AsyncSignalHandler(EventBase* eventBase)
29 : eventBase_(eventBase) {
32 AsyncSignalHandler::~AsyncSignalHandler() {
33 // Unregister any outstanding events
34 for (SignalEventMap::iterator it = signalEvents_.begin();
35 it != signalEvents_.end();
37 event_del(&it->second);
41 void AsyncSignalHandler::attachEventBase(EventBase* eventBase) {
42 assert(eventBase_ == nullptr);
43 assert(signalEvents_.empty());
44 eventBase_ = eventBase;
47 void AsyncSignalHandler::detachEventBase() {
48 assert(eventBase_ != nullptr);
49 assert(signalEvents_.empty());
53 void AsyncSignalHandler::registerSignalHandler(int signum) {
54 pair<SignalEventMap::iterator, bool> ret =
55 signalEvents_.insert(make_pair(signum, event()));
57 // This signal has already been registered
58 throw std::runtime_error(folly::to<string>(
59 "handler already registered for signal ",
63 struct event* ev = &(ret.first->second);
65 signal_set(ev, signum, libeventCallback, this);
66 if (event_base_set(eventBase_->getLibeventBase(), ev) != 0 ) {
67 throw std::runtime_error(folly::to<string>(
68 "error initializing event handler for signal ",
72 if (event_add(ev, nullptr) != 0) {
73 throw std::runtime_error(folly::to<string>(
74 "error adding event handler for signal ",
78 signalEvents_.erase(ret.first);
83 void AsyncSignalHandler::unregisterSignalHandler(int signum) {
84 SignalEventMap::iterator it = signalEvents_.find(signum);
85 if (it == signalEvents_.end()) {
86 throw std::runtime_error(folly::to<string>(
87 "unable to unregister handler for signal ",
88 signum, ": signal not registered"));
91 event_del(&it->second);
92 signalEvents_.erase(it);
95 void AsyncSignalHandler::libeventCallback(libevent_fd_t signum,
98 AsyncSignalHandler* handler = static_cast<AsyncSignalHandler*>(arg);
99 handler->signalReceived(int(signum));