Clear event handler on deallocation

Summary:
It's just bad that we give a naked pointer of the connection manager to other instances. If the connection manager gets deallocated, the instances keeping a pointer to it are doomed to crash.

This change creates a wrapper on top of the pointer that can be freely shared. On deallocation, the shared wrapper gets invalidated.

Reviewed By: timur-valiev

Differential Revision: D30398466

fbshipit-source-id: 8f228e7fbaebc0ea28921409de071b58bbb69f1e
This commit is contained in:
Lorenzo Blasa
2021-08-19 04:41:35 -07:00
committed by Facebook GitHub Bot
parent ebe5e7f9ff
commit 8e2a839f9d
3 changed files with 49 additions and 29 deletions

View File

@@ -36,34 +36,52 @@ using namespace folly;
namespace facebook {
namespace flipper {
class ConnectionEvents {
class FlipperConnectionManagerWrapper {
public:
ConnectionEvents(FlipperConnectionManagerImpl* impl) : impl_(impl) {}
void operator()(const SocketEvent event) {
switch (event) {
case SocketEvent::OPEN:
impl_->isOpen_ = true;
if (impl_->connectionIsTrusted_) {
impl_->callbacks_->onConnected();
}
break;
case SocketEvent::CLOSE:
case SocketEvent::ERROR:
if (!impl_->isOpen_)
return;
impl_->isOpen_ = false;
if (impl_->connectionIsTrusted_) {
impl_->connectionIsTrusted_ = false;
impl_->callbacks_->onDisconnected();
}
impl_->reconnect();
break;
}
FlipperConnectionManagerWrapper(FlipperConnectionManagerImpl* impl)
: impl_(impl) {}
FlipperConnectionManagerImpl* get_impl() {
return impl_;
}
private:
FlipperConnectionManagerImpl* impl_;
};
class ConnectionEvents {
public:
ConnectionEvents(std::weak_ptr<FlipperConnectionManagerWrapper> impl)
: impl_(impl) {}
void operator()(const SocketEvent event) {
if (auto w = impl_.lock()) {
FlipperConnectionManagerImpl* impl = w->get_impl();
if (impl == nullptr) {
return;
}
switch (event) {
case SocketEvent::OPEN:
impl->isOpen_ = true;
if (impl->connectionIsTrusted_) {
impl->callbacks_->onConnected();
}
break;
case SocketEvent::CLOSE:
case SocketEvent::ERROR:
if (!impl->isOpen_)
return;
impl->isOpen_ = false;
if (impl->connectionIsTrusted_) {
impl->connectionIsTrusted_ = false;
impl->callbacks_->onDisconnected();
}
impl->reconnect();
break;
}
}
}
private:
std::weak_ptr<FlipperConnectionManagerWrapper> impl_;
};
FlipperConnectionManagerImpl::FlipperConnectionManagerImpl(
FlipperInitConfig config,
@@ -75,7 +93,8 @@ FlipperConnectionManagerImpl::FlipperConnectionManagerImpl(
securePort(config.securePort),
flipperEventBase_(config.callbackWorker),
connectionEventBase_(config.connectionWorker),
contextStore_(contextStore) {
contextStore_(contextStore),
implWrapper_(std::make_shared<FlipperConnectionManagerWrapper>(this)) {
CHECK_THROW(config.callbackWorker, std::invalid_argument);
CHECK_THROW(config.connectionWorker, std::invalid_argument);
}
@@ -188,7 +207,7 @@ bool FlipperConnectionManagerImpl::connectAndExchangeCertificate() {
auto newClient = std::make_unique<FlipperRSocket>(
endpoint, std::move(payload), connectionEventBase_);
newClient->setEventHandler(ConnectionEvents(this));
newClient->setEventHandler(ConnectionEvents(implWrapper_));
auto connectingInsecurely = flipperState_->start("Connect insecurely");
connectionIsTrusted_ = false;
@@ -234,7 +253,7 @@ bool FlipperConnectionManagerImpl::connectSecurely() {
auto newClient = std::make_unique<FlipperRSocket>(
endpoint, std::move(payload), connectionEventBase_, contextStore_.get());
newClient->setEventHandler(ConnectionEvents(this));
newClient->setEventHandler(ConnectionEvents(implWrapper_));
auto connectingSecurely = flipperState_->start("Connect securely");
connectionIsTrusted_ = true;