This is an automated email from the ASF dual-hosted git repository. mxmanghi pushed a commit to branch quattuor in repository https://gitbox.apache.org/repos/asf/tcl-rivet.git
The following commit(s) were added to refs/heads/quattuor by this push: new b512414 new bridge function names, better server shutdown and single thread termination handling b512414 is described below commit b512414b2bc1834e391ae3f61ad2cf2a78d1ea93 Author: Massimo Manghi <mxman...@apache.org> AuthorDate: Tue Jun 25 17:21:58 2019 +0200 new bridge function names, better server shutdown and single thread termination handling --- ChangeLog | 9 ++- src/mod_rivet_ng/mod_rivet.h | 20 +++--- src/mod_rivet_ng/rivet_lazy_mpm.c | 44 ++++++------ src/mod_rivet_ng/rivet_prefork_mpm.c | 32 ++++----- src/mod_rivet_ng/rivet_worker_mpm.c | 128 +++++++++++++++++++++++++++-------- 5 files changed, 153 insertions(+), 80 deletions(-) diff --git a/ChangeLog b/ChangeLog index 99c63a7..fe80fb0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2019-06-25 Massimo Manghi <mxman...@apache.org> + * src/mod_rivet_ng/rivet_worker_mpm.c: Better handling of exit signal, assigning tasks + to functions in a more consistent way. Worker_Shutdown declared as 'static' + * src/mod_rivet_ng/rivet_[prefork|lazy]_mpm.c: New scheme for bridge function names + * src/mod_rivet_ng/rivet_lazy_mpm.c: Removed redundant exit command handling flags + 2019-05-29 Massimo Manghi <mxman...@apache.org> * src/mod_rivet_ng/apache_config.c: Now handling the directive SingleThreadExit * src/mod_rivet_ng/[worker|lazy|prefork].c: Now handling single thread exit @@ -29,8 +35,7 @@ here and there) 2019-01-14 Massimo Manghi <mxman...@apache.org> - * src/mod_rivet_ng/rivetCore.c: add experimental ::rivet::thread_id - command + * src/mod_rivet_ng/rivetCore.c: add experimental ::rivet::thread_id command 2019-01-08 Massimo Manghi <mxman...@apache.org> * : new branch quattuor created with an initial commit that tries diff --git a/src/mod_rivet_ng/mod_rivet.h b/src/mod_rivet_ng/mod_rivet.h index 58e3d16..db0d593 100644 --- a/src/mod_rivet_ng/mod_rivet.h +++ b/src/mod_rivet_ng/mod_rivet.h @@ -190,13 +190,13 @@ typedef rivet_thread_interp* (RivetBridge_Thread_Interp) (rivet_thread_privat typedef bool RivetBridge_InheritsInterps; typedef struct _mpm_bridge_table { - RivetBridge_ServerInit *server_init; - RivetBridge_ThreadInit *thread_init; - RivetBridge_Request *request_processor; - RivetBridge_Finalize *child_finalize; - RivetBridge_Exit_Handler *exit_handler; - RivetBridge_Thread_Interp *thread_interp; - RivetBridge_InheritsInterps inherits_interps; + RivetBridge_ServerInit *server_init; + RivetBridge_ThreadInit *thread_init; + RivetBridge_Request *request_processor; + RivetBridge_Finalize *child_finalize; + RivetBridge_Exit_Handler *exit_handler; + RivetBridge_Thread_Interp *thread_interp; + RivetBridge_InheritsInterps inherits_interps; } rivet_bridge_table; /* we need also a place where to store globals with module wide scope */ @@ -247,9 +247,9 @@ typedef struct _thread_worker_private { /* eventually we will transfer 'global' variables in here and 'de-globalize' them */ -typedef struct _rivet_interp_globals { - Tcl_Namespace* rivet_ns; /* Rivet commands namespace */ -} rivet_interp_globals; +//typedef struct _rivet_interp_globals { +// Tcl_Namespace* rivet_ns; /* Rivet commands namespace */ +//} rivet_interp_globals; rivet_server_conf *Rivet_GetConf(request_rec *r); diff --git a/src/mod_rivet_ng/rivet_lazy_mpm.c b/src/mod_rivet_ng/rivet_lazy_mpm.c index 44ae7f5..8a0281c 100644 --- a/src/mod_rivet_ng/rivet_lazy_mpm.c +++ b/src/mod_rivet_ng/rivet_lazy_mpm.c @@ -74,8 +74,8 @@ typedef struct vhost_iface { typedef struct mpm_bridge_status { apr_thread_mutex_t* mutex; - int exit_command; - int exit_command_status; + //int exit_command; + //int exit_command_status; int server_shutdown; /* the child process is shutting down */ vhost* vhosts; /* array of vhost descriptors */ } mpm_bridge_status; @@ -228,7 +228,7 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data) w->ap_sts = Rivet_SendContent(private,w->r); - if (module_globals->mpm->server_shutdown) continue; + // if (module_globals->mpm->server_shutdown) continue; w->status = done; apr_thread_cond_signal(w->condition); @@ -245,7 +245,7 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data) apr_thread_mutex_unlock(module_globals->mpm->vhosts[idx].mutex); } - } while (private->ext->keep_going); + } while (private->ext->keep_going && !module_globals->mpm->server_shutdown); apr_thread_mutex_unlock(w->mutex); ap_log_error(APLOG_MARK,APLOG_DEBUG,APR_SUCCESS,w->server,"processor thread orderly exit"); @@ -295,14 +295,14 @@ static lazy_tcl_worker* create_worker (apr_pool_t* pool,server_rec* server) } /* - * -- Lazy_MPM_ChildInit + * -- LazyBridge_ChildInit * * child process initialization. This function prepares the process * data structures for virtual hosts and threads management * */ -void Lazy_MPM_ChildInit (apr_pool_t* pool, server_rec* server) +void LazyBridge_ChildInit (apr_pool_t* pool, server_rec* server) { apr_status_t rv; server_rec* s; @@ -361,7 +361,7 @@ void Lazy_MPM_ChildInit (apr_pool_t* pool, server_rec* server) module_globals->mpm->server_shutdown = 0; } -/* -- Lazy_MPM_Request +/* -- LazyBridge_Request * * The lazy bridge HTTP request function. This function * stores the request_rec pointer into the lazy_tcl_worker @@ -370,7 +370,7 @@ void Lazy_MPM_ChildInit (apr_pool_t* pool, server_rec* server) * a new thread is created by calling create_worker */ -int Lazy_MPM_Request (request_rec* r,rivet_req_ctype ctype) +int LazyBridge_Request (request_rec* r,rivet_req_ctype ctype) { lazy_tcl_worker* w; int ap_sts; @@ -433,11 +433,11 @@ int Lazy_MPM_Request (request_rec* r,rivet_req_ctype ctype) return ap_sts; } -/* -- Lazy_MPM_Interp: lazy bridge accessor to the interpreter database +/* -- LazyBridge_Interp: lazy bridge accessor to the interpreter database * */ -rivet_thread_interp* Lazy_MPM_Interp (rivet_thread_private* private, +rivet_thread_interp* LazyBridge_Interp (rivet_thread_private* private, rivet_server_conf* conf, rivet_thread_interp* interp) { @@ -446,11 +446,12 @@ rivet_thread_interp* Lazy_MPM_Interp (rivet_thread_private* private, return private->ext->interp; } -apr_status_t Lazy_MPM_Finalize (void* data) +apr_status_t LazyBridge_Finalize (void* data) { int vh; rivet_server_conf* conf = RIVET_SERVER_CONF(((server_rec*) data)->module_config); + module_globals->mpm->server_shutdown = 1; for (vh = 0; vh < module_globals->vhosts_count; vh++) { int try; @@ -461,7 +462,6 @@ apr_status_t Lazy_MPM_Finalize (void* data) mutex = module_globals->mpm->vhosts[vh].mutex; array = module_globals->mpm->vhosts[vh].array; apr_thread_mutex_lock(mutex); - module_globals->mpm->server_shutdown = 1; try = 0; do { @@ -485,11 +485,11 @@ apr_status_t Lazy_MPM_Finalize (void* data) apr_thread_mutex_unlock(mutex); } - apr_threadkey_private_delete (rivet_thread_key); + apr_threadkey_private_delete(rivet_thread_key); return APR_SUCCESS; } -int Lazy_MPM_ExitHandler(rivet_thread_private* private) +int LazyBridge_ExitHandler(rivet_thread_private* private) { /* This is not strictly necessary, because this command will @@ -512,8 +512,7 @@ int Lazy_MPM_ExitHandler(rivet_thread_private* private) * and calls out for a version of Tcl with which * we could safely call Tcl_DeleteInterp and then terminate * a single thread - */ - + apr_thread_mutex_lock(module_globals->mpm->mutex); if (module_globals->mpm->exit_command == 0) { @@ -521,6 +520,7 @@ int Lazy_MPM_ExitHandler(rivet_thread_private* private) module_globals->mpm->exit_command_status = private->exit_status; } apr_thread_mutex_unlock(module_globals->mpm->mutex); + */ if (!private->running_conf->single_thread_exit) { @@ -528,7 +528,7 @@ int Lazy_MPM_ExitHandler(rivet_thread_private* private) * to exit and is sequence the whole process to shutdown * by calling exit() */ - Lazy_MPM_Finalize (private->r->server); + LazyBridge_Finalize(private->r->server); } @@ -538,10 +538,10 @@ int Lazy_MPM_ExitHandler(rivet_thread_private* private) DLLEXPORT RIVET_MPM_BRIDGE { NULL, - Lazy_MPM_ChildInit, - Lazy_MPM_Request, - Lazy_MPM_Finalize, - Lazy_MPM_ExitHandler, - Lazy_MPM_Interp, + LazyBridge_ChildInit, + LazyBridge_Request, + LazyBridge_Finalize, + LazyBridge_ExitHandler, + LazyBridge_Interp, false }; diff --git a/src/mod_rivet_ng/rivet_prefork_mpm.c b/src/mod_rivet_ng/rivet_prefork_mpm.c index 58facc5..983f23d 100644 --- a/src/mod_rivet_ng/rivet_prefork_mpm.c +++ b/src/mod_rivet_ng/rivet_prefork_mpm.c @@ -36,7 +36,7 @@ module rivet_module; extern TclWebRequest* TclWeb_NewRequestObject (apr_pool_t *p); -int Prefork_Bridge_ServerInit (apr_pool_t *pPool, +int PreforkBridge_ServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server_rec *server) { @@ -95,9 +95,9 @@ int Prefork_Bridge_ServerInit (apr_pool_t *pPool, return OK; } -/* -- Prefork_Bridge_Finalize */ +/* -- PreforkBridge_Finalize */ -apr_status_t Prefork_Bridge_Finalize (void* data) +apr_status_t PreforkBridge_Finalize (void* data) { rivet_thread_private* private; server_rec* s = (server_rec*) data; @@ -129,9 +129,9 @@ static void Prefork_ReseedRNG(server_rec* server,rivet_thread_interp* interp_obj } -/* -- Prefork_Bridge_ChildInit: bridge child process initialization */ +/* -- PreforkBridge_ChildInit: bridge child process initialization */ -void Prefork_Bridge_ChildInit (apr_pool_t* pool, server_rec* server) +void PreforkBridge_ChildInit (apr_pool_t* pool, server_rec* server) { rivet_thread_private* private; rivet_server_conf* root_server_conf; @@ -203,7 +203,7 @@ void Prefork_Bridge_ChildInit (apr_pool_t* pool, server_rec* server) } /* - * -- Prefork_Bridge_Request + * -- PreforkBridge_Request * * The prefork implementation of this function is basically a wrapper of * Rivet_SendContent. The real job is fetching the thread private data @@ -217,7 +217,7 @@ void Prefork_Bridge_ChildInit (apr_pool_t* pool, server_rec* server) * HTTP status code (see the Apache HTTP web server documentation) */ -int Prefork_Bridge_Request (request_rec* r,rivet_req_ctype ctype) +int PreforkBridge_Request (request_rec* r,rivet_req_ctype ctype) { rivet_thread_private* private; @@ -263,7 +263,7 @@ rivet_thread_interp* MPM_MasterInterp(server_rec* server) #endif /* - * -- Prefork_Bridge_ExitHandler + * -- PreforkBridge_ExitHandler * * Just calling Tcl_Exit * @@ -275,7 +275,7 @@ rivet_thread_interp* MPM_MasterInterp(server_rec* server) * the thread running the Tcl script will exit */ -int Prefork_Bridge_ExitHandler(rivet_thread_private* private) +int PreforkBridge_ExitHandler(rivet_thread_private* private) { Tcl_Exit(private->exit_status); @@ -283,7 +283,7 @@ int Prefork_Bridge_ExitHandler(rivet_thread_private* private) return TCL_OK; } -rivet_thread_interp* Prefork_Bridge_Interp (rivet_thread_private* private, +rivet_thread_interp* PreforkBridge_Interp (rivet_thread_private* private, rivet_server_conf* conf, rivet_thread_interp* interp) { @@ -294,12 +294,12 @@ rivet_thread_interp* Prefork_Bridge_Interp (rivet_thread_private* private, DLLEXPORT RIVET_MPM_BRIDGE { - Prefork_Bridge_ServerInit, - Prefork_Bridge_ChildInit, - Prefork_Bridge_Request, - Prefork_Bridge_Finalize, - Prefork_Bridge_ExitHandler, - Prefork_Bridge_Interp, + PreforkBridge_ServerInit, + PreforkBridge_ChildInit, + PreforkBridge_Request, + PreforkBridge_Finalize, + PreforkBridge_ExitHandler, + PreforkBridge_Interp, true }; diff --git a/src/mod_rivet_ng/rivet_worker_mpm.c b/src/mod_rivet_ng/rivet_worker_mpm.c index c588d7d..38443a3 100644 --- a/src/mod_rivet_ng/rivet_worker_mpm.c +++ b/src/mod_rivet_ng/rivet_worker_mpm.c @@ -67,8 +67,8 @@ typedef struct mpm_bridge_status { apr_uint32_t* running_threads_count; apr_queue_t* queue; /* jobs queue */ void** workers; /* thread pool ids */ - int exit_command; - int exit_command_status; + // int exit_command; + // int exit_command_status; int max_threads; int min_spare_threads; int max_spare_threads; @@ -127,6 +127,58 @@ enum * */ +static +void Worker_Bridge_Shutdown (int not_to_be_waited) +{ + int waits; + void* v; + handler_private* thread_obj; + apr_status_t rv; + apr_uint32_t threads_to_stop; + + apr_thread_mutex_lock(module_globals->mpm->job_mutex); + + module_globals->mpm->server_shutdown = 1; + + /* We wake up the supervisor who is now supposed to stop + * all the Tcl worker threads + */ + + apr_thread_cond_signal(module_globals->mpm->job_cond); + apr_thread_mutex_unlock(module_globals->mpm->job_mutex); + + waits = 5; + do + { + + rv = apr_queue_trypop(module_globals->mpm->queue,&v); + + /* We wait for possible threads that are taking + * time to serve requests and haven't had a chance to + * see the signal yet + */ + + if (rv == APR_EAGAIN) + { + waits--; + apr_sleep(200000); + continue; + } + + thread_obj = (handler_private*)v; + apr_thread_mutex_lock(thread_obj->mutex); + thread_obj->status = init; + apr_thread_cond_signal(thread_obj->cond); + apr_thread_mutex_unlock(thread_obj->mutex); + + threads_to_stop = apr_atomic_read32(module_globals->mpm->threads_count); + + } while ((waits > 0) && (threads_to_stop > not_to_be_waited)); + + return; +} + +#if 0 void Worker_Bridge_Shutdown (void) { int waits; @@ -166,6 +218,8 @@ void Worker_Bridge_Shutdown (void) return; } +#endif + /* -- Worker_CreateInterps * */ @@ -495,14 +549,6 @@ static void* APR_THREAD_FUNC threaded_bridge_supervisor (apr_thread_t *thd, void apr_thread_mutex_unlock(mpm->job_mutex); } while (!mpm->server_shutdown); - Worker_Bridge_Shutdown(); - - if (module_globals->mpm->exit_command) - { - ap_log_error(APLOG_MARK,APLOG_DEBUG,APR_SUCCESS,module_globals->server,"Orderly child process exits."); - exit(module_globals->mpm->exit_command_status); - } - ap_log_error(APLOG_MARK,APLOG_DEBUG,APR_SUCCESS,module_globals->server,"Worker bridge supervisor shuts down"); apr_thread_exit(thd,APR_SUCCESS); @@ -510,7 +556,7 @@ static void* APR_THREAD_FUNC threaded_bridge_supervisor (apr_thread_t *thd, void } /* - * -- Worker_MPM_ChildInit + * -- Worker_Bridge_ChildInit * * Child initialization function called by the web server framework. * For this bridge tasks are @@ -521,7 +567,7 @@ static void* APR_THREAD_FUNC threaded_bridge_supervisor (apr_thread_t *thd, void * */ -void Worker_MPM_ChildInit (apr_pool_t* pool, server_rec* server) +void Worker_Bridge_ChildInit (apr_pool_t* pool, server_rec* server) { apr_status_t rv; @@ -553,7 +599,7 @@ void Worker_MPM_ChildInit (apr_pool_t* pool, server_rec* server) module_globals->mpm->max_spare_threads = 0; module_globals->mpm->workers = NULL; module_globals->mpm->server_shutdown = 0; - module_globals->mpm->exit_command = 0; + //module_globals->mpm->exit_command = 0; /* We keep some atomic counters that could provide basic data for a workload balancer */ @@ -650,7 +696,7 @@ apr_status_t Worker_RequestPrivateCleanup (void *client_data) } /* - * -- Worker_MPM_Request + * -- Worker_Bridge_Request * * Content generation callback. Actually this function is not * generating directly content but instead builds a handler_private @@ -670,7 +716,7 @@ apr_status_t Worker_RequestPrivateCleanup (void *client_data) * HTTP status code (see the Apache HTTP web server documentation) */ -int Worker_MPM_Request (request_rec* r,rivet_req_ctype ctype) +int Worker_Bridge_Request (request_rec* r,rivet_req_ctype ctype) { void* v; apr_queue_t* q = module_globals->mpm->queue; @@ -727,12 +773,32 @@ int Worker_MPM_Request (request_rec* r,rivet_req_ctype ctype) } /* - * -- Worker_MPM_Finalize + * -- Worker_Bridge_Finalize * * */ -apr_status_t Worker_MPM_Finalize (void* data) +apr_status_t Worker_Bridge_Finalize (void* data) +{ + apr_status_t rv; + apr_status_t thread_status; + server_rec* s = (server_rec*) data; + rivet_thread_private* private; + + RIVET_PRIVATE_DATA(rivet_thread_key,private) + Worker_Bridge_Shutdown(private->thread_exit); + + rv = apr_thread_join (&thread_status,module_globals->mpm->supervisor); + if (rv != APR_SUCCESS) + { + ap_log_error(APLOG_MARK,APLOG_ERR,rv,s,MODNAME": Error joining supervisor thread"); + } + + return OK; +} + +#if 0 +apr_status_t Worker_Bridge_Finalize (void* data) { apr_status_t rv; apr_status_t thread_status; @@ -750,7 +816,7 @@ apr_status_t Worker_MPM_Finalize (void* data) /* If the function is called by the memory pool cleanup we wait * to join the supervisor, otherwise we if the function was called - * by Worker_MPM_Exit we skip it because this thread itself must exit + * by Worker_Bridge_Exit we skip it because this thread itself must exit * to allow the supervisor to exit in the shortest possible time */ @@ -767,6 +833,7 @@ apr_status_t Worker_MPM_Finalize (void* data) apr_threadkey_private_delete (rivet_thread_key); return OK; } +#endif /* * -- MPM_MasterInterp @@ -794,7 +861,7 @@ rivet_thread_interp* MPM_MasterInterp(server_rec* s) #endif /* - * -- Worker_MPM_ExitHandler + * -- Worker_Bridge_ExitHandler * * Signals a thread to exit by setting the loop control flag to 0 * and by returning a Tcl error with error code THREAD_EXIT_CODE @@ -808,7 +875,7 @@ rivet_thread_interp* MPM_MasterInterp(server_rec* s) * the thread running the Tcl script will exit */ -int Worker_MPM_ExitHandler(rivet_thread_private* private) +int Worker_Bridge_ExitHandler(rivet_thread_private* private) { /* This is not strictly necessary, because this command will * eventually terminate the whole processes */ @@ -817,8 +884,8 @@ int Worker_MPM_ExitHandler(rivet_thread_private* private) private->ext->keep_going = 0; - module_globals->mpm->exit_command = 1; - module_globals->mpm->exit_command_status = private->exit_status; + //module_globals->mpm->exit_command = 1; + //module_globals->mpm->exit_command_status = private->exit_status; if (!private->running_conf->single_thread_exit) { @@ -826,8 +893,9 @@ int Worker_MPM_ExitHandler(rivet_thread_private* private) /* We now tell the supervisor to terminate the Tcl worker thread pool to exit * and is sequence the whole process to shutdown by calling exit() */ - Worker_MPM_Finalize (private->r->server); - + Worker_Bridge_Finalize (private->r->server); + + exit(private->exit_status); } /* @@ -838,7 +906,7 @@ int Worker_MPM_ExitHandler(rivet_thread_private* private) return TCL_OK; } -rivet_thread_interp* Worker_MPM_Interp (rivet_thread_private* private, +rivet_thread_interp* Worker_Bridge_Interp (rivet_thread_private* private, rivet_server_conf* conf, rivet_thread_interp* interp) { @@ -850,10 +918,10 @@ rivet_thread_interp* Worker_MPM_Interp (rivet_thread_private* private, DLLEXPORT RIVET_MPM_BRIDGE { NULL, - Worker_MPM_ChildInit, - Worker_MPM_Request, - Worker_MPM_Finalize, - Worker_MPM_ExitHandler, - Worker_MPM_Interp, + Worker_Bridge_ChildInit, + Worker_Bridge_Request, + Worker_Bridge_Finalize, + Worker_Bridge_ExitHandler, + Worker_Bridge_Interp, false, }; --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@tcl.apache.org For additional commands, e-mail: commits-h...@tcl.apache.org