Commit a9fdc51d authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook GitHub Bot

Make ExecutorLoopController cancel local callback in destructor

Summary: EventBaseLoopController does this already. This way it's safe to destroy FiberManager even if some local callback is left in the executor.

Differential Revision: D26563934

fbshipit-source-id: 0845e5c532634fa9c53694cd67e983886cea82de
parent 22e61b3f
......@@ -36,7 +36,16 @@ inline void ExecutorLoopController::schedule() {
if (!executorKeepAlive_) {
executorKeepAlive_ = getKeepAliveToken(executor_);
}
executor_->add([this]() { return runLoop(); });
auto guard = localCallbackControlBlock_->trySchedule();
if (!guard) {
return;
}
executor_->add([this, guard = std::move(guard)]() {
if (guard->isCancelled()) {
return;
}
runLoop();
});
}
inline void ExecutorLoopController::runLoop() {
......
......@@ -86,6 +86,51 @@ class ExecutorLoopController : public fibers::ExecutorBasedLoopController {
ExecutorTimeoutManager timeoutManager_;
HHWheelTimer::UniquePtr timer_;
class LocalCallbackControlBlock {
public:
struct DeleteOrCancel {
void operator()(LocalCallbackControlBlock* controlBlock) {
if (controlBlock->scheduled_) {
controlBlock->cancelled_ = true;
} else {
delete controlBlock;
}
}
};
using Ptr = std::unique_ptr<LocalCallbackControlBlock, DeleteOrCancel>;
struct GuardDeleter {
void operator()(LocalCallbackControlBlock* controlBlock) {
DCHECK(controlBlock->scheduled_);
controlBlock->scheduled_ = false;
if (controlBlock->cancelled_) {
delete controlBlock;
}
}
};
using Guard = std::unique_ptr<LocalCallbackControlBlock, GuardDeleter>;
static Ptr create() { return Ptr(new LocalCallbackControlBlock()); }
Guard trySchedule() {
if (scheduled_) {
return {};
}
scheduled_ = true;
return Guard(this);
}
bool isCancelled() const { return cancelled_; }
private:
LocalCallbackControlBlock() {}
bool cancelled_{false};
bool scheduled_{false};
};
LocalCallbackControlBlock::Ptr localCallbackControlBlock_{
LocalCallbackControlBlock::create()};
void setFiberManager(fibers::FiberManager* fm) override;
void schedule() override;
void runLoop() override;
......
......@@ -46,8 +46,6 @@ cdef class FiberManager:
def __dealloc__(FiberManager self):
while deref(self.cManager).hasTasks():
self.cExecutor.drive()
# drive one last time
self.cExecutor.drive()
# Explicitly reset here, otherwise it is possible
# that self.cManager dstor runs after python finalizes
......
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