From: Adam Simpkins Date: Tue, 27 Jun 2017 02:27:32 +0000 (-0700) Subject: allow AsyncSignalHandler to attach and detach from an EventBase X-Git-Tag: v2017.07.03.00~27 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=dc1c3dcc04baa70029d16351d4424af4a7ef4385 allow AsyncSignalHandler to attach and detach from an EventBase Summary: Add attachEventBase() and detachEventBase() methods to AsyncSignalHandler, similar to the methods of AsyncSocket. The main benefit of this is that it allows creating an AsyncSignalHandler with an initially null EventBase, and then attaching it to an EventBase at some later point in time. Reviewed By: yfeldblum Differential Revision: D5315325 fbshipit-source-id: 8a4ca483a62ca86837ea0bb54fa9a70d59f2f04e --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bf5def6..4bfa9974 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -407,6 +407,7 @@ if (BUILD_TESTS) AsyncSSLSocketTest.h SOURCES AsyncPipeTest.cpp + AsyncSignalHandlerTest.cpp AsyncSocketExceptionTest.cpp AsyncSocketTest.cpp AsyncSocketTest2.cpp diff --git a/folly/io/async/AsyncSignalHandler.cpp b/folly/io/async/AsyncSignalHandler.cpp index c81116d7..8c5c3247 100644 --- a/folly/io/async/AsyncSignalHandler.cpp +++ b/folly/io/async/AsyncSignalHandler.cpp @@ -38,6 +38,18 @@ AsyncSignalHandler::~AsyncSignalHandler() { } } +void AsyncSignalHandler::attachEventBase(EventBase* eventBase) { + assert(eventBase_ == nullptr); + assert(signalEvents_.empty()); + eventBase_ = eventBase; +} + +void AsyncSignalHandler::detachEventBase() { + assert(eventBase_ != nullptr); + assert(signalEvents_.empty()); + eventBase_ = nullptr; +} + void AsyncSignalHandler::registerSignalHandler(int signum) { pair ret = signalEvents_.insert(make_pair(signum, event())); diff --git a/folly/io/async/AsyncSignalHandler.h b/folly/io/async/AsyncSignalHandler.h index f4b6bdf6..05665533 100644 --- a/folly/io/async/AsyncSignalHandler.h +++ b/folly/io/async/AsyncSignalHandler.h @@ -48,6 +48,30 @@ class AsyncSignalHandler { explicit AsyncSignalHandler(EventBase* eventBase); virtual ~AsyncSignalHandler(); + /** + * Attach this AsyncSignalHandler to an EventBase. + * + * This should only be called if the AsyncSignalHandler is not currently + * registered for any signals and is not currently attached to an existing + * EventBase. + */ + void attachEventBase(EventBase* eventBase); + + /** + * Detach this AsyncSignalHandler from its EventBase. + * + * This should only be called if the AsyncSignalHandler is not currently + * registered for any signals. + */ + void detachEventBase(); + + /** + * Get the EventBase used by this AsyncSignalHandler. + */ + EventBase* getEventBase() const { + return eventBase_; + } + /** * Register to receive callbacks about the specified signal. * @@ -86,7 +110,7 @@ class AsyncSignalHandler { static void libeventCallback(libevent_fd_t signum, short events, void* arg); - EventBase* eventBase_; + EventBase* eventBase_{nullptr}; SignalEventMap signalEvents_; }; diff --git a/folly/io/async/test/AsyncSignalHandlerTest.cpp b/folly/io/async/test/AsyncSignalHandlerTest.cpp new file mode 100644 index 00000000..3d6d41d2 --- /dev/null +++ b/folly/io/async/test/AsyncSignalHandlerTest.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2017 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 +#include + +#include + +using namespace folly; + +namespace { +class TestSignalHandler : public AsyncSignalHandler { + public: + using AsyncSignalHandler::AsyncSignalHandler; + + void signalReceived(int /* signum */) noexcept override { + called = true; + } + + bool called{false}; +}; +} + +TEST(AsyncSignalHandler, basic) { + EventBase evb; + TestSignalHandler handler{&evb}; + + handler.registerSignalHandler(SIGUSR1); + kill(getpid(), SIGUSR1); + + EXPECT_FALSE(handler.called); + evb.loopOnce(EVLOOP_NONBLOCK); + EXPECT_TRUE(handler.called); +} + +TEST(AsyncSignalHandler, attachEventBase) { + TestSignalHandler handler{nullptr}; + EXPECT_FALSE(handler.getEventBase()); + EventBase evb; + + handler.attachEventBase(&evb); + EXPECT_EQ(&evb, handler.getEventBase()); + + handler.registerSignalHandler(SIGUSR1); + kill(getpid(), SIGUSR1); + EXPECT_FALSE(handler.called); + evb.loopOnce(EVLOOP_NONBLOCK); + EXPECT_TRUE(handler.called); + + handler.unregisterSignalHandler(SIGUSR1); + handler.detachEventBase(); + EXPECT_FALSE(handler.getEventBase()); +}