Commit dc1c3dcc authored by Adam Simpkins's avatar Adam Simpkins Committed by Facebook Github Bot

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
parent 46c5dbce
...@@ -407,6 +407,7 @@ if (BUILD_TESTS) ...@@ -407,6 +407,7 @@ if (BUILD_TESTS)
AsyncSSLSocketTest.h AsyncSSLSocketTest.h
SOURCES SOURCES
AsyncPipeTest.cpp AsyncPipeTest.cpp
AsyncSignalHandlerTest.cpp
AsyncSocketExceptionTest.cpp AsyncSocketExceptionTest.cpp
AsyncSocketTest.cpp AsyncSocketTest.cpp
AsyncSocketTest2.cpp AsyncSocketTest2.cpp
......
...@@ -38,6 +38,18 @@ AsyncSignalHandler::~AsyncSignalHandler() { ...@@ -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) { void AsyncSignalHandler::registerSignalHandler(int signum) {
pair<SignalEventMap::iterator, bool> ret = pair<SignalEventMap::iterator, bool> ret =
signalEvents_.insert(make_pair(signum, event())); signalEvents_.insert(make_pair(signum, event()));
......
...@@ -48,6 +48,30 @@ class AsyncSignalHandler { ...@@ -48,6 +48,30 @@ class AsyncSignalHandler {
explicit AsyncSignalHandler(EventBase* eventBase); explicit AsyncSignalHandler(EventBase* eventBase);
virtual ~AsyncSignalHandler(); 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. * Register to receive callbacks about the specified signal.
* *
...@@ -86,7 +110,7 @@ class AsyncSignalHandler { ...@@ -86,7 +110,7 @@ class AsyncSignalHandler {
static void libeventCallback(libevent_fd_t signum, short events, void* arg); static void libeventCallback(libevent_fd_t signum, short events, void* arg);
EventBase* eventBase_; EventBase* eventBase_{nullptr};
SignalEventMap signalEvents_; SignalEventMap signalEvents_;
}; };
......
/*
* 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 <folly/io/async/AsyncSignalHandler.h>
#include <folly/io/async/EventBase.h>
#include <folly/portability/GTest.h>
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());
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment