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 16:05:11 UTC
[tcl-rivet] branch single-thread-exit updated: Further
simplifications ported from branch quattuor
This is an automated email from the ASF dual-hosted git repository.
mxmanghi pushed a commit to branch single-thread-exit
in repository https://gitbox.apache.org/repos/asf/tcl-rivet.git
The following commit(s) were added to refs/heads/single-thread-exit by this push:
new 1789515 Further simplifications ported from branch quattuor
1789515 is described below
commit 178951532c9cf09a6476dd63eef8f3828d808a23
Author: Massimo Manghi <mx...@apache.org>
AuthorDate: Tue Jun 25 18:04:56 2019 +0200
Further simplifications ported from branch quattuor
---
ChangeLog | 2 +
src/mod_rivet_ng/rivet_lazy_mpm.c | 82 ++++++++++++++++++-----
src/mod_rivet_ng/rivet_prefork_mpm.c | 28 ++++----
src/mod_rivet_ng/rivet_worker_mpm.c | 126 ++++++++++++++++++++++++++---------
4 files changed, 174 insertions(+), 64 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 7d83e1a..5bbfeae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
2019-06-25 Massimo Manghi <mx...@apache.org>
* : Single thread exit implementation for mod_rivet 3.2
+ * src/mod_rivet_ng/rivet_[.*]_mpm.c: further simplified code by removing
+ redundant flags. Changing function names scheme
2019-05-24 Massimo Manghi <mx...@apache.org>
* src/mod_rivet_ng/rivetCore.c: Add Tcl_DecrRefCnt after
diff --git a/src/mod_rivet_ng/rivet_lazy_mpm.c b/src/mod_rivet_ng/rivet_lazy_mpm.c
index f1e569d..f5bc6df 100644
--- a/src/mod_rivet_ng/rivet_lazy_mpm.c
+++ b/src/mod_rivet_ng/rivet_lazy_mpm.c
@@ -74,8 +74,6 @@ typedef struct vhost_iface {
typedef struct mpm_bridge_status {
apr_thread_mutex_t* mutex;
- 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;
@@ -221,7 +219,7 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
w->ap_sts = Rivet_SendContent(private);
- if (module_globals->mpm->server_shutdown) continue;
+ // if (module_globals->mpm->server_shutdown) continue;
w->status = done;
apr_thread_cond_signal(w->condition);
@@ -276,14 +274,14 @@ static lazy_tcl_worker* create_worker (apr_pool_t* pool,server_rec* server)
}
/*
- * -- Lazy_Bridge_ChildInit
+ * -- LazyBridge_ChildInit
*
* child process initialization. This function prepares the process
* data structures for virtual hosts and threads management
*
*/
-void Lazy_Bridge_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;
@@ -338,7 +336,7 @@ void Lazy_Bridge_ChildInit (apr_pool_t* pool, server_rec* server)
module_globals->mpm->server_shutdown = 0;
}
-/* -- Lazy_Bridge_Request
+/* -- LazyBridge_Request
*
* The lazy bridge HTTP request function. This function
* stores the request_rec pointer into the lazy_tcl_worker
@@ -347,7 +345,7 @@ void Lazy_Bridge_ChildInit (apr_pool_t* pool, server_rec* server)
* a new thread is created by calling create_worker
*/
-int Lazy_Bridge_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;
@@ -410,11 +408,11 @@ int Lazy_Bridge_Request (request_rec* r,rivet_req_ctype ctype)
return ap_sts;
}
-/* -- Lazy_Bridge_Interp: lazy bridge accessor to the interpreter database
+/* -- LazyBridge_Interp: lazy bridge accessor to the interpreter database
*
*/
-rivet_thread_interp* Lazy_Bridge_Interp (rivet_thread_private* private,
+rivet_thread_interp* LazyBridge_Interp (rivet_thread_private* private,
rivet_server_conf* conf,
rivet_thread_interp* interp)
{
@@ -423,11 +421,12 @@ rivet_thread_interp* Lazy_Bridge_Interp (rivet_thread_private* private,
return private->ext->interp;
}
-apr_status_t Lazy_Bridge_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;
@@ -438,7 +437,6 @@ apr_status_t Lazy_Bridge_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 {
@@ -465,7 +463,54 @@ apr_status_t Lazy_Bridge_Finalize (void* data)
return APR_SUCCESS;
}
-int Lazy_Bridge_ExitHandler(rivet_thread_private* private)
+int LazyBridge_ExitHandler(rivet_thread_private* private)
+{
+
+ /* This is not strictly necessary, because this command will
+ * eventually terminate the whole processes */
+
+ /* This will force the current thread to exit */
+
+ private->ext->keep_going = 0;
+
+ /*
+ * This is the only place where exit_command and
+ * exit_command_status are set, anywere alse these
+ * fields are only read. We lock on writing to synchronize
+ * with other threads that might try to access
+ * this info. That means that in the unlikely case
+ * of several threads calling ::rivet::exit
+ * simultaneously the first sets the exit code.
+ * This is just terrible, it highlights the bad habit
+ * of calling 'exit' when programming with mod_rivet
+ * 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)
+ {
+ module_globals->mpm->exit_command = 1;
+ module_globals->mpm->exit_command_status = private->exit_status;
+ }
+ apr_thread_mutex_unlock(module_globals->mpm->mutex);
+ */
+
+ if (!private->running_conf->single_thread_exit)
+ {
+ /* 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() */
+
+ LazyBridge_Finalize(private->r->server);
+
+ }
+
+ return TCL_OK;
+}
+
+#if 0
+int LazyBridge_ExitHandler(rivet_thread_private* private)
{
/* This is not strictly necessary, because this command will
@@ -504,16 +549,17 @@ int Lazy_Bridge_ExitHandler(rivet_thread_private* private)
* to exit and is sequence the whole process to shutdown
* by calling exit() */
- Lazy_Bridge_Finalize (private->r->server);
+ LazyBridge_Finalize (private->r->server);
return TCL_OK;
}
+#endif
DLLEXPORT
RIVET_MPM_BRIDGE {
NULL,
- Lazy_Bridge_ChildInit,
- Lazy_Bridge_Request,
- Lazy_Bridge_Finalize,
- Lazy_Bridge_ExitHandler,
- Lazy_Bridge_Interp
+ LazyBridge_ChildInit,
+ LazyBridge_Request,
+ LazyBridge_Finalize,
+ LazyBridge_ExitHandler,
+ LazyBridge_Interp
};
diff --git a/src/mod_rivet_ng/rivet_prefork_mpm.c b/src/mod_rivet_ng/rivet_prefork_mpm.c
index 8de9adb..3c20250 100644
--- a/src/mod_rivet_ng/rivet_prefork_mpm.c
+++ b/src/mod_rivet_ng/rivet_prefork_mpm.c
@@ -36,9 +36,9 @@ extern DLLIMPORT apr_threadkey_t* rivet_thread_key;
rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private);
-/* -- 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;
@@ -52,12 +52,12 @@ apr_status_t Prefork_Bridge_Finalize (void* data)
return OK;
}
-/* -- 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;
@@ -100,7 +100,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
@@ -114,7 +114,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;
@@ -159,7 +159,7 @@ rivet_thread_interp* MPM_MasterInterp(server_rec* server)
}
/*
- * -- Prefork_Bridge_ExitHandler
+ * -- PreforkBridge_ExitHandler
*
* Just calling Tcl_Exit
*
@@ -171,7 +171,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);
@@ -182,7 +182,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)
{
@@ -194,10 +194,10 @@ rivet_thread_interp* Prefork_Bridge_Interp (rivet_thread_private* private,
DLLEXPORT
RIVET_MPM_BRIDGE {
NULL,
- Prefork_Bridge_ChildInit,
- Prefork_Bridge_Request,
- Prefork_Bridge_Finalize,
- Prefork_Bridge_ExitHandler,
- Prefork_Bridge_Interp
+ PreforkBridge_ChildInit,
+ PreforkBridge_Request,
+ PreforkBridge_Finalize,
+ PreforkBridge_ExitHandler,
+ PreforkBridge_Interp
};
diff --git a/src/mod_rivet_ng/rivet_worker_mpm.c b/src/mod_rivet_ng/rivet_worker_mpm.c
index 9fdfc23..85b4606 100644
--- a/src/mod_rivet_ng/rivet_worker_mpm.c
+++ b/src/mod_rivet_ng/rivet_worker_mpm.c
@@ -68,8 +68,6 @@ 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 max_threads;
int min_spare_threads;
int max_spare_threads;
@@ -127,7 +125,58 @@ enum
* must be restared or (most likely) the child process can exit.
*
*/
+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;
@@ -177,6 +226,7 @@ void Worker_Bridge_Shutdown (void)
return;
}
+#endif
/*
* -- request_processor
@@ -439,23 +489,12 @@ static void* APR_THREAD_FUNC threaded_bridge_supervisor (apr_thread_t *thd, void
} while (!mpm->server_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);
return NULL;
}
-// int Worker_Bridge_ServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server_rec *s) { return OK; }
-
/*
* -- Worker_Bridge_ChildInit
*
@@ -493,7 +532,7 @@ void Worker_Bridge_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 */
@@ -676,31 +715,21 @@ 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;
- /* If the Function is called by the memory pool cleanup we wait
- * to join the supervisor, otherwise if the function was called
- * by Worker_Bridge_Exit we skip it because this thread itself must exit
- * to allow the supervisor to exit in the shortest possible time
- */
+ RIVET_PRIVATE_DATA(rivet_thread_key,private)
+ Worker_Bridge_Shutdown(private->thread_exit);
- if (!module_globals->mpm->exit_command)
+ rv = apr_thread_join (&thread_status,module_globals->mpm->supervisor);
+ if (rv != APR_SUCCESS)
{
- Worker_Bridge_Shutdown();
-
- 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");
- }
+ ap_log_error(APLOG_MARK,APLOG_ERR,rv,s,MODNAME": Error joining supervisor thread");
}
- // apr_threadkey_private_delete (handler_thread_key);
- exit(module_globals->mpm->exit_command_status);
-
return OK;
}
+
/*
* -- MPM_MasterInterp
*
@@ -742,6 +771,39 @@ rivet_thread_interp* MPM_MasterInterp(server_rec* s)
int Worker_Bridge_ExitHandler(rivet_thread_private* private)
{
/* This is not strictly necessary, because this command will
+ * eventually terminate the whole processes */
+
+ /* This will force the current thread to exit */
+
+ private->ext->keep_going = 0;
+
+ //module_globals->mpm->exit_command = 1;
+ //module_globals->mpm->exit_command_status = private->exit_status;
+
+ if (!private->running_conf->single_thread_exit)
+ {
+
+ /* 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_Bridge_Finalize (private->r->server);
+
+ exit(private->exit_status);
+ }
+
+ /*
+ * If single thread exit is enabled we continue and let the
+ * thread exit on its own interrupting the main loop
+ */
+
+ return TCL_OK;
+}
+
+
+#if 0
+int Worker_Bridge_ExitHandler(rivet_thread_private* private)
+{
+ /* This is not strictly necessary, because this command will
* eventually terminate the whole processes
*/
@@ -769,7 +831,7 @@ int Worker_Bridge_ExitHandler(rivet_thread_private* private)
return TCL_OK;
}
-
+#endif
rivet_thread_interp* Worker_Bridge_Interp (rivet_thread_private* private,
rivet_server_conf* conf,
rivet_thread_interp* interp)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tcl.apache.org
For additional commands, e-mail: commits-help@tcl.apache.org