-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix interrupt transaction race condition #1107
Changes from all commits
c9d4276
1a2a0c9
11f1e9a
8ad83f2
1a50b7b
0f4fbb4
d072fcd
848f90e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,14 +57,14 @@ platform_timer::~platform_timer() { | |
|
||
void platform_timer::start(fc::time_point tp) { | ||
if(tp == fc::time_point::maximum()) { | ||
expired = false; | ||
_state = state_t::running; | ||
return; | ||
} | ||
fc::microseconds x = tp.time_since_epoch() - fc::time_point::now().time_since_epoch(); | ||
if(x.count() <= 0) | ||
expired = true; | ||
_state = state_t::timed_out; | ||
else { | ||
expired = false; | ||
_state = state_t::running; | ||
my->timer->expires_after(std::chrono::microseconds(x.count())); | ||
my->timer->async_wait([this](const boost::system::error_code& ec) { | ||
if(ec) | ||
|
@@ -75,18 +75,25 @@ void platform_timer::start(fc::time_point tp) { | |
} | ||
|
||
void platform_timer::expire_now() { | ||
bool expected = false; | ||
if (expired.compare_exchange_strong(expected, true)) { | ||
state_t expected = state_t::running; | ||
if (_state.compare_exchange_strong(expected, state_t::timed_out)) { | ||
call_expiration_callback(); | ||
} | ||
} | ||
|
||
void platform_timer::interrupt_timer() { | ||
state_t expected = state_t::running; | ||
if (_state.compare_exchange_strong(expected, state_t::interrupted)) { | ||
Comment on lines
+78
to
+86
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why don't these call Isn't it possible that someone calls There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We would need to add a mutex around the timer to do that. I think the intention is that stop() should be called before calling start() again. |
||
call_expiration_callback(); | ||
} | ||
} | ||
|
||
void platform_timer::stop() { | ||
if(expired) | ||
if(_state == state_t::stopped) | ||
return; | ||
|
||
my->timer->cancel(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't it make sense to call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This now needs to set to stopped, so the assert on start() is not triggered. |
||
expired = true; | ||
_state = state_t::stopped; | ||
} | ||
|
||
}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not seeing why this added line is necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added it because I originally added an assert that start() only called when timer is stopped. However, we don't actually honor that constraint currently elsewhere. Seems like it is better to honor that constraint normally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Decided it best to fix the invariant that
stop()
always called beforestart()
. Surprise-surprise the issue there is with deferred-transactions.