Postpone trigger_nearest to prevent timer callbacks called from setTimer/clearTimer

This commit is contained in:
Vitaliy Filippov
2024-11-10 15:51:16 +03:00
parent be66791e59
commit 5ce20116d8
2 changed files with 12 additions and 9 deletions
+11 -8
View File
@@ -62,7 +62,7 @@ int timerfd_manager_t::set_timer_us(uint64_t micros, bool repeat, std::function<
.callback = callback, .callback = callback,
}); });
inc_timer(timers[timers.size()-1]); inc_timer(timers[timers.size()-1]);
set_nearest(); set_nearest(false);
return timer_id; return timer_id;
} }
@@ -82,13 +82,13 @@ void timerfd_manager_t::clear_timer(int timer_id)
{ {
nearest--; nearest--;
} }
set_nearest(); set_nearest(false);
break; break;
} }
} }
} }
void timerfd_manager_t::set_nearest() void timerfd_manager_t::set_nearest(bool trigger_inline)
{ {
if (onstack > 0) if (onstack > 0)
{ {
@@ -134,10 +134,13 @@ again:
} }
if (exp.it_value.tv_sec < 0 || exp.it_value.tv_sec == 0 && exp.it_value.tv_nsec <= 0) if (exp.it_value.tv_sec < 0 || exp.it_value.tv_sec == 0 && exp.it_value.tv_nsec <= 0)
{ {
// It already happened // It already happened - set minimal timeout
// FIXME: Postpone to setImmediate/BH to avoid reenterability problems if (trigger_inline)
trigger_nearest(); {
goto again; trigger_nearest();
goto again;
}
exp.it_value = { .tv_sec = 0, .tv_nsec = 1 };
} }
if (timerfd_settime(timerfd, 0, &exp, NULL)) if (timerfd_settime(timerfd, 0, &exp, NULL))
{ {
@@ -157,7 +160,7 @@ void timerfd_manager_t::handle_readable()
trigger_nearest(); trigger_nearest();
} }
wait_state = 0; wait_state = 0;
set_nearest(); set_nearest(true);
} }
void timerfd_manager_t::trigger_nearest() void timerfd_manager_t::trigger_nearest()
+1 -1
View File
@@ -26,7 +26,7 @@ class timerfd_manager_t
std::vector<timerfd_timer_t> timers; std::vector<timerfd_timer_t> timers;
void inc_timer(timerfd_timer_t & t); void inc_timer(timerfd_timer_t & t);
void set_nearest(); void set_nearest(bool trigger_inline);
void trigger_nearest(); void trigger_nearest();
void handle_readable(); void handle_readable();
public: public: