Commit 03439afb authored by Dave Watson's avatar Dave Watson Committed by Pavlo Kushnir

Fix cancel in ThreadWheelTimeKeeper

Summary: This is actually a bug, future.cancel() doesn't work with the current THreadWheelTimekeeper, because cancel() only works from the eventBase thread.

Test Plan: added unittest.  Crashes before, passes now

Reviewed By: hans@fb.com

Subscribers: doug, folly-diffs@, jsedgwick, yfeldblum, chalfant

FB internal diff: D2091531

Signature: t1:2091531:1432224024:4aa5dd71de15b1344034a414d47c97ffaba68949
parent 496a1139
...@@ -27,9 +27,9 @@ namespace { ...@@ -27,9 +27,9 @@ namespace {
// Our Callback object for HHWheelTimer // Our Callback object for HHWheelTimer
struct WTCallback : public folly::HHWheelTimer::Callback { struct WTCallback : public folly::HHWheelTimer::Callback {
// Only allow creation by this factory, to ensure heap allocation. // Only allow creation by this factory, to ensure heap allocation.
static WTCallback* create() { static WTCallback* create(EventBase* base) {
// optimization opportunity: memory pool // optimization opportunity: memory pool
return new WTCallback(); return new WTCallback(base);
} }
Future<void> getFuture() { Future<void> getFuture() {
...@@ -37,9 +37,11 @@ namespace { ...@@ -37,9 +37,11 @@ namespace {
} }
protected: protected:
EventBase* base_;
Promise<void> promise_; Promise<void> promise_;
explicit WTCallback() { explicit WTCallback(EventBase* base)
: base_(base) {
promise_.setInterruptHandler( promise_.setInterruptHandler(
std::bind(&WTCallback::interruptHandler, this)); std::bind(&WTCallback::interruptHandler, this));
} }
...@@ -50,8 +52,10 @@ namespace { ...@@ -50,8 +52,10 @@ namespace {
} }
void interruptHandler() { void interruptHandler() {
base_->runInEventBaseThread([=] {
cancelTimeout(); cancelTimeout();
delete this; delete this;
});
} }
}; };
...@@ -78,7 +82,7 @@ ThreadWheelTimekeeper::~ThreadWheelTimekeeper() { ...@@ -78,7 +82,7 @@ ThreadWheelTimekeeper::~ThreadWheelTimekeeper() {
} }
Future<void> ThreadWheelTimekeeper::after(Duration dur) { Future<void> ThreadWheelTimekeeper::after(Duration dur) {
auto cob = WTCallback::create(); auto cob = WTCallback::create(&eventBase_);
auto f = cob->getFuture(); auto f = cob->getFuture();
eventBase_.runInEventBaseThread([=]{ eventBase_.runInEventBaseThread([=]{
wheelTimer_->scheduleTimeout(cob, dur); wheelTimer_->scheduleTimeout(cob, dur);
......
...@@ -25,6 +25,7 @@ using Duration = folly::Duration; ...@@ -25,6 +25,7 @@ using Duration = folly::Duration;
std::chrono::milliseconds const one_ms(1); std::chrono::milliseconds const one_ms(1);
std::chrono::milliseconds const awhile(10); std::chrono::milliseconds const awhile(10);
std::chrono::seconds const too_long(10);
std::chrono::steady_clock::time_point now() { std::chrono::steady_clock::time_point now() {
return std::chrono::steady_clock::now(); return std::chrono::steady_clock::now();
...@@ -154,6 +155,11 @@ TEST(Timekeeper, onTimeoutVoid) { ...@@ -154,6 +155,11 @@ TEST(Timekeeper, onTimeoutVoid) {
// just testing compilation here // just testing compilation here
} }
TEST(Timekeeper, interruptDoesntCrash) {
auto f = futures::sleep(too_long);
f.cancel();
}
// TODO(5921764) // TODO(5921764)
/* /*
TEST(Timekeeper, onTimeoutPropagates) { TEST(Timekeeper, onTimeoutPropagates) {
......
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