Commit 055fce5f authored by Stepan Palamarchuk's avatar Stepan Palamarchuk Committed by Facebook Github Bot

Properly handle negative timeouts

Summary:
We're always scheduling negative timeouts to fire immediately. However, there's a branch with invalid timeout that may end up getting us into an invalid state (in particular, setting negative `expireTick_`).

To avoid that, this adds input sanitization by making sure we don't have anything negative.

Reviewed By: yfeldblum

Differential Revision: D13934881

fbshipit-source-id: 28d7dc48f57da67d3266a7f33e058ff6994eb756
parent f1d6c61c
......@@ -136,6 +136,8 @@ void HHWheelTimer::scheduleTimeoutImpl(
void HHWheelTimer::scheduleTimeout(
Callback* callback,
std::chrono::milliseconds timeout) {
// Make sure that the timeout is not negative.
timeout = std::max(timeout, std::chrono::milliseconds::zero());
// Cancel the callback if it happens to be scheduled already.
callback->cancelTimeout();
callback->requestContext_ = RequestContext::saveContext();
......
......@@ -499,3 +499,21 @@ TEST_F(HHWheelTimerTest, Level1) {
ASSERT_EQ(tt.timestamps.size(), 1);
T_CHECK_TIMEOUT(start, end, milliseconds(500));
}
// Test that we handle negative timeouts properly (i.e. treat them as 0)
TEST_F(HHWheelTimerTest, NegativeTimeout) {
StackWheelTimer t(&eventBase, milliseconds(1));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
TestTimeout tt1;
TestTimeout tt2;
// Make sure we have event scheduled.
t.scheduleTimeout(&tt1, std::chrono::milliseconds(1));
// Schedule another timeout that would appear to be earlier than
// the already scheduled one.
t.scheduleTimeout(&tt2, std::chrono::milliseconds(-500000000));
TimePoint start;
eventBase.loop();
TimePoint end;
ASSERT_EQ(tt2.timestamps.size(), 1);
T_CHECK_TIMEOUT(start, end, milliseconds(1));
}
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