vlib: reset stop_timer_handle on expired processes
Type: fix The main loop populates a vector of suspended process nodes to dispatch by calling TW (tw_timer_expire_timers_vec), which identifies expired timers and appends the user handle for each one to the vector. Subsequently, the vector is iterated and the process node corresponding to each handle is dispatched. The vast majority of the time, the process node will end up suspending itself again to wait for a new timer or event. Given a process node A whose timer has expired, between the point when the timer expired and the point when A is dispatched and suspends itself again, its stop_timer_handle contains a stale value. If another process node B is dispatched before A is dispatched, it may end up using the timer ID that A formerly used. If another process node C is dispatched after B and before A and calls vlib_process_signal_event() to signal A, the timer started by B can be deleted by vlib_process_signal_event_helper(). After getting the vector of process node IDs for expired timers, reset the stop_timer_handle on each of those nodes. Change-Id: I266da438e76e1fc356016da0b9b4941efac1c28a Signed-off-by: Matthew Smith <mgsmith@netgate.com> (cherry picked from commit 9aa4ac55b0a205e333e567f87c3cc9379af2363c)
This commit is contained in:
parent
3be288f0d9
commit
0dfaadec8c
@ -1615,10 +1615,8 @@ vlib_main_or_worker_loop (vlib_main_t * vm, int is_main)
|
||||
if (PREDICT_FALSE (vm->elog_trace_graph_dispatch))
|
||||
ed = ELOG_DATA (&vlib_global_main.elog_main, es);
|
||||
|
||||
nm->data_from_advancing_timing_wheel =
|
||||
TW (tw_timer_expire_timers_vec)
|
||||
((TWT (tw_timer_wheel) *) nm->timing_wheel, vlib_time_now (vm),
|
||||
nm->data_from_advancing_timing_wheel);
|
||||
TW (tw_timer_expire_timers)
|
||||
((TWT (tw_timer_wheel) *) nm->timing_wheel, vlib_time_now (vm));
|
||||
|
||||
ASSERT (nm->data_from_advancing_timing_wheel != 0);
|
||||
|
||||
@ -1848,6 +1846,23 @@ vl_api_get_elog_trace_api_messages (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
process_expired_timer_cb (u32 *expired_timer_handles)
|
||||
{
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
vlib_node_main_t *nm = &vm->node_main;
|
||||
u32 *handle;
|
||||
|
||||
vec_foreach (handle, expired_timer_handles)
|
||||
{
|
||||
u32 pi = vlib_timing_wheel_data_get_index (*handle);
|
||||
vlib_process_t *p = vec_elt (nm->processes, pi);
|
||||
|
||||
p->stop_timer_handle = ~0;
|
||||
}
|
||||
vec_append (nm->data_from_advancing_timing_wheel, expired_timer_handles);
|
||||
}
|
||||
|
||||
/* Main function. */
|
||||
int
|
||||
vlib_main (vlib_main_t * volatile vm, unformat_input_t * input)
|
||||
@ -1953,10 +1968,10 @@ vlib_main (vlib_main_t * volatile vm, unformat_input_t * input)
|
||||
vec_set_len (nm->data_from_advancing_timing_wheel, 0);
|
||||
|
||||
/* Create the process timing wheel */
|
||||
TW (tw_timer_wheel_init) ((TWT (tw_timer_wheel) *) nm->timing_wheel,
|
||||
0 /* no callback */ ,
|
||||
10e-6 /* timer period 10us */ ,
|
||||
~0 /* max expirations per call */ );
|
||||
TW (tw_timer_wheel_init)
|
||||
((TWT (tw_timer_wheel) *) nm->timing_wheel,
|
||||
process_expired_timer_cb /* callback */, 10e-6 /* timer period 10us */,
|
||||
~0 /* max expirations per call */);
|
||||
|
||||
vec_validate (vm->pending_rpc_requests, 0);
|
||||
vec_set_len (vm->pending_rpc_requests, 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user