You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tcl.apache.org by mx...@apache.org on 2019/06/25 15:22:17 UTC
[tcl-rivet] branch quattuor updated: new bridge function names,
better server shutdown and single thread termination handling
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 <mx...@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 <mx...@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 <mx...@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 <mx...@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 <mx...@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-unsubscribe@tcl.apache.org
For additional commands, e-mail: commits-help@tcl.apache.org