diff options
Diffstat (limited to 'src/vnet/session/application_worker.c')
-rw-r--r-- | src/vnet/session/application_worker.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/src/vnet/session/application_worker.c b/src/vnet/session/application_worker.c index f9740a300c2..17aeb57d49b 100644 --- a/src/vnet/session/application_worker.c +++ b/src/vnet/session/application_worker.c @@ -33,6 +33,7 @@ app_worker_alloc (application_t * app) app_wrk->wrk_map_index = ~0; app_wrk->connects_seg_manager = APP_INVALID_SEGMENT_MANAGER_INDEX; app_wrk->first_segment_manager = APP_INVALID_SEGMENT_MANAGER_INDEX; + clib_spinlock_init (&app_wrk->detached_seg_managers_lock); APP_DBG ("New app %v worker %u", app->name, app_wrk->wrk_index); return app_wrk; } @@ -131,17 +132,26 @@ app_worker_free (app_worker_t * app_wrk) vec_free (app_wrk->half_open_table); vec_free (handles); + /* + * Detached listener segment managers cleanup + */ + for (i = 0; i < vec_len (app_wrk->detached_seg_managers); i++) + { + sm = segment_manager_get (app_wrk->detached_seg_managers[i]); + segment_manager_init_free (sm); + } + vec_free (app_wrk->detached_seg_managers); + clib_spinlock_free (&app_wrk->detached_seg_managers_lock); + /* If first segment manager is used by a listener that recently * stopped listening, mark it as detached */ if (app_wrk->first_segment_manager != app_wrk->connects_seg_manager - && (sm = segment_manager_get_if_valid (app_wrk->first_segment_manager))) + && (sm = segment_manager_get_if_valid (app_wrk->first_segment_manager)) + && !segment_manager_app_detached (sm)) { sm->first_is_protected = 0; sm->app_wrk_index = SEGMENT_MANAGER_INVALID_APP_INDEX; - /* .. and has no fifos, e.g. it might be used for redirected sessions, - * remove it */ - if (!segment_manager_has_fifos (sm)) - segment_manager_free (sm); + segment_manager_init_free (sm); } if (CLIB_DEBUG) @@ -254,6 +264,29 @@ app_worker_start_listen (app_worker_t * app_wrk, } static void +app_worker_add_detached_sm (app_worker_t * app_wrk, u32 sm_index) +{ + vec_add1 (app_wrk->detached_seg_managers, sm_index); +} + +void +app_worker_del_detached_sm (app_worker_t * app_wrk, u32 sm_index) +{ + u32 i; + + clib_spinlock_lock (&app_wrk->detached_seg_managers_lock); + for (i = 0; i < vec_len (app_wrk->detached_seg_managers); i++) + { + if (app_wrk->detached_seg_managers[i] == sm_index) + { + vec_del1 (app_wrk->detached_seg_managers, i); + break; + } + } + clib_spinlock_unlock (&app_wrk->detached_seg_managers_lock); +} + +static void app_worker_stop_listen_session (app_worker_t * app_wrk, session_t * ls) { session_handle_t handle; @@ -279,6 +312,13 @@ app_worker_stop_listen_session (app_worker_t * app_wrk, session_t * ls) segment_manager_app_detach (sm); if (!segment_manager_has_fifos (sm)) segment_manager_free (sm); + else + { + /* Track segment manager in case app detaches and all the + * outstanding sessions need to be closed */ + app_worker_add_detached_sm (app_wrk, *sm_indexp); + sm->flags |= SEG_MANAGER_F_DETACHED_LISTENER; + } } hash_unset (app_wrk->listeners_table, handle); |