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 facebook {
namespace flipper { namespace flipper {
class ConnectionEvents { class FlipperConnectionManagerWrapper {
public: public:
ConnectionEvents(FlipperConnectionManagerImpl* impl) : impl_(impl) {} FlipperConnectionManagerWrapper(FlipperConnectionManagerImpl* impl)
void operator()(const SocketEvent event) { : impl_(impl) {}
switch (event) { FlipperConnectionManagerImpl* get_impl() {
case SocketEvent::OPEN: return impl_;
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: private:
FlipperConnectionManagerImpl* impl_; 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( FlipperConnectionManagerImpl::FlipperConnectionManagerImpl(
FlipperInitConfig config, FlipperInitConfig config,
@@ -75,7 +93,8 @@ FlipperConnectionManagerImpl::FlipperConnectionManagerImpl(
securePort(config.securePort), securePort(config.securePort),
flipperEventBase_(config.callbackWorker), flipperEventBase_(config.callbackWorker),
connectionEventBase_(config.connectionWorker), connectionEventBase_(config.connectionWorker),
contextStore_(contextStore) { contextStore_(contextStore),
implWrapper_(std::make_shared<FlipperConnectionManagerWrapper>(this)) {
CHECK_THROW(config.callbackWorker, std::invalid_argument); CHECK_THROW(config.callbackWorker, std::invalid_argument);
CHECK_THROW(config.connectionWorker, std::invalid_argument); CHECK_THROW(config.connectionWorker, std::invalid_argument);
} }
@@ -188,7 +207,7 @@ bool FlipperConnectionManagerImpl::connectAndExchangeCertificate() {
auto newClient = std::make_unique<FlipperRSocket>( auto newClient = std::make_unique<FlipperRSocket>(
endpoint, std::move(payload), connectionEventBase_); endpoint, std::move(payload), connectionEventBase_);
newClient->setEventHandler(ConnectionEvents(this)); newClient->setEventHandler(ConnectionEvents(implWrapper_));
auto connectingInsecurely = flipperState_->start("Connect insecurely"); auto connectingInsecurely = flipperState_->start("Connect insecurely");
connectionIsTrusted_ = false; connectionIsTrusted_ = false;
@@ -234,7 +253,7 @@ bool FlipperConnectionManagerImpl::connectSecurely() {
auto newClient = std::make_unique<FlipperRSocket>( auto newClient = std::make_unique<FlipperRSocket>(
endpoint, std::move(payload), connectionEventBase_, contextStore_.get()); endpoint, std::move(payload), connectionEventBase_, contextStore_.get());
newClient->setEventHandler(ConnectionEvents(this)); newClient->setEventHandler(ConnectionEvents(implWrapper_));
auto connectingSecurely = flipperState_->start("Connect securely"); auto connectingSecurely = flipperState_->start("Connect securely");
connectionIsTrusted_ = true; connectionIsTrusted_ = true;

View File

@@ -21,7 +21,7 @@ namespace flipper {
class ConnectionEvents; class ConnectionEvents;
class ConnectionContextStore; class ConnectionContextStore;
class FlipperRSocketResponder; class FlipperRSocketResponder;
class FlipperConnectionManagerWrapper;
class FlipperConnectionManagerImpl : public FlipperConnectionManager { class FlipperConnectionManagerImpl : public FlipperConnectionManager {
friend ConnectionEvents; friend ConnectionEvents;
@@ -70,6 +70,7 @@ class FlipperConnectionManagerImpl : public FlipperConnectionManager {
bool connectionIsTrusted_; bool connectionIsTrusted_;
int failedConnectionAttempts_ = 0; int failedConnectionAttempts_ = 0;
std::shared_ptr<ConnectionContextStore> contextStore_; std::shared_ptr<ConnectionContextStore> contextStore_;
std::shared_ptr<FlipperConnectionManagerWrapper> implWrapper_;
void startSync(); void startSync();
bool connectAndExchangeCertificate(); bool connectAndExchangeCertificate();

View File

@@ -35,11 +35,11 @@ rsocket::Payload toRSocketPayload(folly::dynamic data);
class RSocketEvents : public rsocket::RSocketConnectionEvents { class RSocketEvents : public rsocket::RSocketConnectionEvents {
private: private:
const SocketEventHandler& handler_; const SocketEventHandler handler_;
public: public:
RSocketEvents(const SocketEventHandler& eventHandler) RSocketEvents(const SocketEventHandler eventHandler)
: handler_(eventHandler) {} : handler_(std::move(eventHandler)) {}
void onConnected() { void onConnected() {
handler_(SocketEvent::OPEN); handler_(SocketEvent::OPEN);