Skip to content

Commit a0414e8

Browse files
committed
don't start the platform timer when applying a block
1 parent 909603c commit a0414e8

5 files changed

+42
-13
lines changed

libraries/chain/include/eosio/chain/platform_timer.hpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,19 @@ struct platform_timer {
1313
platform_timer();
1414
~platform_timer();
1515

16+
//start() & stop() are not thread safe to each other; i.e. do not overlap calls to start() and stop()
1617
void start(fc::time_point tp);
1718
void stop();
19+
//interrupt_timer() can be called from any thread
1820
void interrupt_timer();
1921

20-
/* Sets a callback for when timer expires. Be aware this could might fire from a signal handling context and/or
22+
/* Sets a callback for when timer expires. Be aware this could fire from a signal handling context and/or
2123
on any particular thread. Only a single callback can be registered at once; trying to register more will
22-
result in an exception. Setting to nullptr disables any current set callback */
24+
result in an exception. Setting to nullptr disables any current set callback.
25+
Also, stop() is not perfectly synchronized with the callback. It is possible for stop() to return and the
26+
callback still execute if the timer expires and stop() is called nearly simultaneously.
27+
However, set_expiration_callback() is synchronized with the callback.
28+
*/
2329
void set_expiration_callback(void(*func)(void*), void* user) {
2430
bool expect_false = false;
2531
while(!atomic_compare_exchange_strong(&_callback_variables_busy, &expect_false, true))
@@ -45,6 +51,7 @@ struct platform_timer {
4551
void expire_now();
4652

4753
std::atomic<state_t> _state = state_t::stopped;
54+
bool timer_running_forever = false;
4855

4956
struct impl;
5057
constexpr static size_t fwd_size = 8;

libraries/chain/platform_timer_asio_fallback.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,14 @@ platform_timer::~platform_timer() {
5656
}
5757

5858
void platform_timer::start(fc::time_point tp) {
59+
assert(_state == state_t::stopped);
5960
if(tp == fc::time_point::maximum()) {
6061
_state = state_t::running;
62+
timer_running_forever = true;
6163
return;
6264
}
6365
fc::microseconds x = tp.time_since_epoch() - fc::time_point::now().time_since_epoch();
66+
timer_running_forever = false;
6467
if(x.count() <= 0)
6568
_state = state_t::timed_out;
6669
else {
@@ -89,11 +92,14 @@ void platform_timer::interrupt_timer() {
8992
}
9093

9194
void platform_timer::stop() {
92-
if(_state == state_t::stopped)
95+
const state_t prior_state = _state;
96+
if(prior_state == state_t::stopped)
97+
return;
98+
_state = state_t::stopped;
99+
if(prior_state == state_t::timed_out || timer_running_forever)
93100
return;
94101

95102
my->timer->cancel();
96-
_state = state_t::stopped;
97103
}
98104

99105
}}

libraries/chain/platform_timer_kqueue.cpp

+12-5
Original file line numberDiff line numberDiff line change
@@ -88,20 +88,23 @@ platform_timer::~platform_timer() {
8888
}
8989

9090
void platform_timer::start(fc::time_point tp) {
91+
assert(_state == state_t::stopped);
9192
if(tp == fc::time_point::maximum()) {
92-
expired = false;
93+
_state = state_t::running;
94+
timer_running_forever = true;
9395
return;
9496
}
9597
fc::microseconds x = tp.time_since_epoch() - fc::time_point::now().time_since_epoch();
98+
timer_running_forever = false;
9699
if(x.count() <= 0)
97-
expired = true;
100+
_state = state_t::timed_out;
98101
else {
99102
struct kevent64_s aTimerEvent;
100103
EV_SET64(&aTimerEvent, my->timerid, EVFILT_TIMER, EV_ADD|EV_ENABLE|EV_ONESHOT, NOTE_USECONDS|NOTE_CRITICAL, x.count(), (uint64_t)this, 0, 0);
101104

102-
expired = false;
105+
_state = state_t::running;
103106
if(kevent64(kqueue_fd, &aTimerEvent, 1, NULL, 0, KEVENT_FLAG_IMMEDIATE, NULL) != 0)
104-
expired = true;
107+
_state = state_t::timed_out;
105108
}
106109
}
107110

@@ -120,7 +123,11 @@ void platform_timer::interrupt_timer() {
120123
}
121124

122125
void platform_timer::stop() {
123-
if(_state == state_t::stopped)
126+
const state_t prior_state = _state;
127+
if(prior_state == state_t::stopped)
128+
return;
129+
_state = state_t::stopped;
130+
if(prior_state == state_t::timed_out || timer_running_forever)
124131
return;
125132

126133
struct kevent64_s stop_timer_event;

libraries/chain/platform_timer_posix.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,11 @@ void platform_timer::start(fc::time_point tp) {
5858
assert(_state == state_t::stopped);
5959
if(tp == fc::time_point::maximum()) {
6060
_state = state_t::running;
61+
timer_running_forever = true;
6162
return;
6263
}
6364
fc::microseconds x = tp.time_since_epoch() - fc::time_point::now().time_since_epoch();
65+
timer_running_forever = false;
6466
if(x.count() <= 0)
6567
_state = state_t::timed_out;
6668
else {
@@ -88,11 +90,14 @@ void platform_timer::interrupt_timer() {
8890
}
8991

9092
void platform_timer::stop() {
91-
if(_state == state_t::stopped)
93+
const state_t prior_state = _state;
94+
if(prior_state == state_t::stopped)
95+
return;
96+
_state = state_t::stopped;
97+
if(prior_state == state_t::timed_out || timer_running_forever)
9298
return;
9399
struct itimerspec disable = {{0, 0}, {0, 0}};
94100
timer_settime(my->timerid, 0, &disable, NULL);
95-
_state = state_t::stopped;
96101
}
97102

98103
}

libraries/chain/transaction_context.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ namespace eosio::chain {
111111
init_net_usage = initial_net_usage;
112112

113113
// set maximum to a semi-valid deadline to allow for pause math and conversion to dates for logging
114-
if( block_deadline == fc::time_point::maximum() ) block_deadline = start + fc::hours(24*7*52);
114+
const fc::time_point far_future_time = start + fc::days(7*52);
115+
if( block_deadline == fc::time_point::maximum() ) block_deadline = far_future_time;
115116

116117
const auto& cfg = control.get_global_properties().configuration;
117118
auto& rl = control.get_mutable_resource_limits_manager();
@@ -250,7 +251,10 @@ namespace eosio::chain {
250251
_deadline = block_deadline;
251252
}
252253

253-
transaction_timer.start( _deadline );
254+
if(_deadline < far_future_time)
255+
transaction_timer.start( _deadline );
256+
else
257+
transaction_timer.start( fc::time_point::maximum() ); //avoids overhead in starting the timer at all
254258
checktime(); // Fail early if deadline has already been exceeded
255259
is_initialized = true;
256260
}

0 commit comments

Comments
 (0)