From 87d48ad8f6e8008bfd7ffaf56c91cb0c8b362330 Mon Sep 17 00:00:00 2001 From: liuyacan Date: Wed, 28 Apr 2021 11:34:03 +0000 Subject: session: cleanup CREATED sessions when listener goes down We should cleanup sessions in CREATED state when listener goes down, otherwise they may use unpredictable sessions as listeners later. Type: fix Signed-off-by: liuyacan Change-Id: Ifbd0a0fb46275bd9d89e5aee19a70c1d01d15764 --- src/vnet/session/application_worker.c | 8 ++++++ src/vnet/session/segment_manager.c | 53 +++++++++++++++++++++++++++++++++++ src/vnet/session/segment_manager.h | 2 ++ 3 files changed, 63 insertions(+) diff --git a/src/vnet/session/application_worker.c b/src/vnet/session/application_worker.c index d44f52c5340..8c3be22d4dc 100644 --- a/src/vnet/session/application_worker.c +++ b/src/vnet/session/application_worker.c @@ -293,6 +293,7 @@ app_worker_stop_listen_session (app_worker_t * app_wrk, session_t * ls) session_handle_t handle; segment_manager_t *sm; uword *sm_indexp; + session_state_t *states = 0; handle = listen_session_get_handle (ls); sm_indexp = hash_get (app_wrk->listeners_table, handle); @@ -308,6 +309,13 @@ app_worker_stop_listen_session (app_worker_t * app_wrk, session_t * ls) /* Try to cleanup segment manager */ sm = segment_manager_get (*sm_indexp); + if (sm && segment_manager_has_fifos (sm)) + { + /* Delete sessions in CREATED state */ + vec_add1 (states, SESSION_STATE_CREATED); + segment_manager_del_sessions_filter (sm, states); + vec_free (states); + } if (sm && app_wrk->first_segment_manager != *sm_indexp) { segment_manager_app_detach (sm); diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c index 73b2f7177bd..103f89ecfa8 100644 --- a/src/vnet/session/segment_manager.c +++ b/src/vnet/session/segment_manager.c @@ -626,6 +626,59 @@ segment_manager_del_sessions (segment_manager_t * sm) vec_free (handles); } +/** + * Initiate disconnects for sessions in specified state 'owned' by a segment + * manager + */ +void +segment_manager_del_sessions_filter (segment_manager_t *sm, + session_state_t *states) +{ + session_handle_t *handles = 0, *handle; + fifo_segment_t *fs; + session_t *session; + int slice_index; + svm_fifo_t *f; + + ASSERT (pool_elts (sm->segments) != 0); + + /* Across all fifo segments used by the server */ + segment_manager_foreach_segment_w_lock ( + fs, sm, ({ + for (slice_index = 0; slice_index < fs->n_slices; slice_index++) + { + f = fifo_segment_get_slice_fifo_list (fs, slice_index); + while (f) + { + session = session_get_if_valid (f->shr->master_session_index, + f->master_thread_index); + if (session) + { + session_state_t *state; + vec_foreach (state, states) + { + if (session->session_state == *state) + { + vec_add1 (handles, session_handle (session)); + break; + } + } + } + f = f->next; + } + } + })); + + vec_foreach (handle, handles) + { + session = session_get_from_handle (*handle); + session_close (session); + /* Avoid propagating notifications back to the app */ + session->app_wrk_index = APP_INVALID_INDEX; + } + vec_free (handles); +} + int segment_manager_try_alloc_fifos (fifo_segment_t * fifo_segment, u32 thread_index, diff --git a/src/vnet/session/segment_manager.h b/src/vnet/session/segment_manager.h index e73a70fda16..3278d8d825d 100644 --- a/src/vnet/session/segment_manager.h +++ b/src/vnet/session/segment_manager.h @@ -159,6 +159,8 @@ void segment_manager_app_detach (segment_manager_t * sm); * @param sm segment manager whose sessions are to be disconnected */ void segment_manager_del_sessions (segment_manager_t * sm); +void segment_manager_del_sessions_filter (segment_manager_t *sm, + session_state_t *states); void segment_manager_format_sessions (segment_manager_t * sm, int verbose); void segment_manager_main_init (void); -- cgit 1.2.3-korg