--- /dev/null
+/*
+ * Copyright 2015 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <folly/io/async/AsyncSignalHandler.h>
+
+#include <folly/io/async/EventBase.h>
+
+#include <folly/Conv.h>
+
+using std::make_pair;
+using std::pair;
+using std::string;
+
+namespace folly {
+
+AsyncSignalHandler::AsyncSignalHandler(EventBase* eventBase)
+ : eventBase_(eventBase) {
+}
+
+AsyncSignalHandler::~AsyncSignalHandler() {
+ // Unregister any outstanding events
+ for (SignalEventMap::iterator it = signalEvents_.begin();
+ it != signalEvents_.end();
+ ++it) {
+ event_del(&it->second);
+ }
+}
+
+void AsyncSignalHandler::registerSignalHandler(int signum) {
+ pair<SignalEventMap::iterator, bool> ret =
+ signalEvents_.insert(make_pair(signum, event()));
+ if (!ret.second) {
+ // This signal has already been registered
+ throw std::runtime_error(folly::to<string>(
+ "handler already registered for signal ",
+ signum));
+ }
+
+ struct event* ev = &(ret.first->second);
+ try {
+ signal_set(ev, signum, libeventCallback, this);
+ if (event_base_set(eventBase_->getLibeventBase(), ev) != 0 ) {
+ throw std::runtime_error(folly::to<string>(
+ "error initializing event handler for signal ",
+ signum));
+ }
+
+ if (event_add(ev, nullptr) != 0) {
+ throw std::runtime_error(folly::to<string>(
+ "error adding event handler for signal ",
+ signum));
+ }
+ } catch (...) {
+ signalEvents_.erase(ret.first);
+ throw;
+ }
+}
+
+void AsyncSignalHandler::unregisterSignalHandler(int signum) {
+ SignalEventMap::iterator it = signalEvents_.find(signum);
+ if (it == signalEvents_.end()) {
+ throw std::runtime_error(folly::to<string>(
+ "unable to unregister handler for signal ",
+ signum, ": signal not registered"));
+ }
+
+ event_del(&it->second);
+ signalEvents_.erase(it);
+}
+
+void AsyncSignalHandler::libeventCallback(int signum, short events,
+ void* arg) {
+ AsyncSignalHandler* handler = static_cast<AsyncSignalHandler*>(arg);
+ handler->signalReceived(signum);
+}
+
+} // folly
--- /dev/null
+/*
+ * Copyright 2015 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <folly/io/async/EventBase.h>
+#include <event.h>
+#include <map>
+
+namespace folly {
+
+/**
+ * A handler to receive notification about POSIX signals.
+ *
+ * TAsyncSignalHandler allows code to process signals from within a EventBase
+ * loop. Standard signal handlers interrupt execution of the main thread, and
+ * are run while the main thread is paused. As a result, great care must be
+ * taken to avoid race conditions if the signal handler has to access or modify
+ * any data used by the main thread.
+ *
+ * TAsyncSignalHandler solves this problem by running the TAsyncSignalHandler
+ * callback in normal thread of execution, as a EventBase callback.
+ *
+ * TAsyncSignalHandler may only be used in a single thread. It will only
+ * process signals received by the thread where the TAsyncSignalHandler is
+ * registered. It is the user's responsibility to ensure that signals are
+ * delivered to the desired thread in multi-threaded programs.
+ */
+class AsyncSignalHandler {
+ public:
+ /**
+ * Create a new AsyncSignalHandler.
+ */
+ explicit AsyncSignalHandler(EventBase* eventBase);
+ virtual ~AsyncSignalHandler();
+
+ /**
+ * Register to receive callbacks about the specified signal.
+ *
+ * Once the handler has been registered for a particular signal,
+ * signalReceived() will be called each time this thread receives this
+ * signal.
+ *
+ * Throws a TException if an error occurs, or if this handler is already
+ * registered for this signal.
+ */
+ void registerSignalHandler(int signum);
+
+ /**
+ * Unregister for callbacks about the specified signal.
+ *
+ * Throws a TException if an error occurs, or if this signal was not
+ * registered.
+ */
+ void unregisterSignalHandler(int signum);
+
+ /**
+ * signalReceived() will called to indicate that the specified signal has
+ * been received.
+ *
+ * signalReceived() will always be invoked from the EventBase loop (i.e.,
+ * after the main POSIX signal handler has returned control to the EventBase
+ * thread).
+ */
+ virtual void signalReceived(int signum) noexcept = 0;
+
+ private:
+ typedef std::map<int, struct event> SignalEventMap;
+
+ // Forbidden copy constructor and assignment operator
+ AsyncSignalHandler(AsyncSignalHandler const &);
+ AsyncSignalHandler& operator=(AsyncSignalHandler const &);
+
+ static void libeventCallback(int signum, short events, void* arg);
+
+ EventBase* eventBase_;
+ SignalEventMap signalEvents_;
+};
+
+} // folly
* TIMEOUT - this library has specific timeout support, instead of
being attached to read/write fds.
* SIGNAL - similarly, signals are handled separately, see
- AsyncSignalHandler (TODO:currently in fbthrift)
+ AsyncSignalHandler
* EV_ET - Currently all the implementations of EventHandler are set up
for level triggered. Benchmarking hasn't shown that edge triggered
provides much improvement.
a bit, because only a single HHWheelTimer is needed per thread, as
opposed to one AsyncTimeoutSet per timeout time per thread.
-### TAsyncSignalHandler
-
-TODO: still in fbthrift
+### AsyncSignalHandler
Used to handle AsyncSignals. Similar to AsyncTimeout, for code
clarity, we don't reuse the same fd as a socket to receive signals.