Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 25 additions & 10 deletions packages/streamr-dht/modules/connection/simulator/Simulator.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ module;
#include <condition_variable>
#include <cstddef>
#include <cstdint>
#include <exception>
#include <functional>
#include <map>
#include <memory>
Expand Down Expand Up @@ -301,16 +302,30 @@ private:
this->inFlightOperations++;
lock.unlock();
executor->add([this, operation]() {
switch (operation.type) {
case OperationType::CONNECT:
this->executeConnectOperation(operation);
break;
case OperationType::CLOSE:
this->executeCloseOperation(operation);
break;
case OperationType::SEND:
this->executeSendOperation(operation);
break;
// The decrement below must run even if the call-out
// throws: folly's SerialExecutor swallows task exceptions
// (SerialExecutor::worker invokeCatchingExns), so a
// propagated exception would silently skip the decrement
// and park stop()'s drain-wait forever.
try {
switch (operation.type) {
case OperationType::CONNECT:
this->executeConnectOperation(operation);
break;
case OperationType::CLOSE:
this->executeCloseOperation(operation);
break;
case OperationType::SEND:
this->executeSendOperation(operation);
break;
}
} catch (const std::exception& e) {
SLogger::error(
"Simulator operation threw an exception: " +
std::string(e.what()));
} catch (...) {
SLogger::error(
"Simulator operation threw a non-std exception");
}
// Notify under the lock: once stop()'s drain-wait sees the
// count hit zero the Simulator may be destroyed, so this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,21 @@ public:
}

void destroy() {
transport.off<transportevents::Message>(this->onMessageHandlerToken);
// The waiting variant: the owner destroys this communicator right
// after destroy() returns, and a Message/Disconnected handler
// mid-invocation on another thread would then dereference freed
// memory. offAndWait() returns only once no such invocation is
// running (unless destroy() itself is called from inside a
// handler invocation, where waiting could deadlock and the
// historical non-blocking semantics are kept).
transport.offAndWait<transportevents::Message>(
this->onMessageHandlerToken);
// Also detach the Disconnected listener: leaving it registered
// dangles `this` on the transport after destruction, and a live
// listener could still add client errors while a retired
// communicator waits to be destroyed (see
// RecursiveOperationManager::retiredSessionCommunicators).
transport.off<transportevents::Disconnected>(
transport.offAndWait<transportevents::Disconnected>(
this->onDisconnectedHandlerToken);
}
using RpcCommunicator::registerRpcMethod;
Expand Down
Loading
Loading