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 11:28:09 UTC

[tcl-rivet] branch single-thread-exit updated: Single thread exit implementation for 3.2 with better function task definition

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 856cfd2  Single thread exit implementation for 3.2 with better function task definition
856cfd2 is described below

commit 856cfd298fca965d3da7b9126b3c3827d60903d5
Author: Massimo Manghi <mx...@apache.org>
AuthorDate: Tue Jun 25 13:27:50 2019 +0200

    Single thread exit implementation for 3.2 with better function task definition
---
 ChangeLog                              |  3 ++
 src/mod_rivet_ng/mod_rivet.c           |  8 +--
 src/mod_rivet_ng/mod_rivet_generator.c |  5 +-
 src/mod_rivet_ng/rivetCore.c           |  2 -
 src/mod_rivet_ng/rivet_lazy_mpm.c      | 28 +++++-----
 src/mod_rivet_ng/rivet_prefork_mpm.c   | 31 +++++------
 src/mod_rivet_ng/rivet_worker_mpm.c    | 98 ++++++++++++++++++++--------------
 7 files changed, 95 insertions(+), 80 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index d1c8088..7d83e1a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+2019-06-25 Massimo Manghi <mx...@apache.org>
+    * : Single thread exit implementation for mod_rivet 3.2
+
 2019-05-24 Massimo Manghi <mx...@apache.org>
     * src/mod_rivet_ng/rivetCore.c: Add Tcl_DecrRefCnt after
     RivetCache_StoreScript as this function itself calls
diff --git a/src/mod_rivet_ng/mod_rivet.c b/src/mod_rivet_ng/mod_rivet.c
index c6ffb60..d3dbc5c 100644
--- a/src/mod_rivet_ng/mod_rivet.c
+++ b/src/mod_rivet_ng/mod_rivet.c
@@ -65,9 +65,9 @@
 #include "mod_rivet_generator.h"
 
 module AP_MODULE_DECLARE_DATA rivet_module;
-extern Tcl_ChannelType   RivetChan;
-DLLEXPORT apr_threadkey_t*         rivet_thread_key    = NULL;
-DLLEXPORT mod_rivet_globals*       module_globals      = NULL;
+extern Tcl_ChannelType        RivetChan;
+DLLEXPORT apr_threadkey_t*    rivet_thread_key    = NULL;
+DLLEXPORT mod_rivet_globals*  module_globals      = NULL;
 
 #define ERRORBUF_SZ         256
 #define TCL_HANDLER_FILE    RIVET_DIR"/default_request_handler.tcl"
@@ -441,7 +441,7 @@ static void Rivet_ChildInit (apr_pool_t *pChild, server_rec *server)
      * to each of them 
      */
 
-    root_server_conf = RIVET_SERVER_CONF( server->module_config );
+    root_server_conf = RIVET_SERVER_CONF(server->module_config);
     idx = 0;
     for (s = server; s != NULL; s = s->next)
     {
diff --git a/src/mod_rivet_ng/mod_rivet_generator.c b/src/mod_rivet_ng/mod_rivet_generator.c
index 5adae3a..9944d93 100644
--- a/src/mod_rivet_ng/mod_rivet_generator.c
+++ b/src/mod_rivet_ng/mod_rivet_generator.c
@@ -333,9 +333,10 @@ sendcleanup:
     
     if (private->thread_exit)
     {
-        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, private->r, 
-                                  "process terminating with code %d",private->exit_status);
+        ap_log_rerror(APLOG_MARK,APLOG_DEBUG,APR_SUCCESS,private->r, 
+                                "process terminating with code %d",private->exit_status);
         RIVET_MPM_BRIDGE_CALL(exit_handler,private);
+
         //Tcl_Exit(private->exit_status);
         //exit(private->exit_status);
     }
diff --git a/src/mod_rivet_ng/rivetCore.c b/src/mod_rivet_ng/rivetCore.c
index e8c3dfd..35c8fa1 100644
--- a/src/mod_rivet_ng/rivetCore.c
+++ b/src/mod_rivet_ng/rivetCore.c
@@ -19,8 +19,6 @@
     under the License.
 */
 
-/* $Id$ */
-
 /* Rivet config */
 #ifdef HAVE_CONFIG_H
 #include <rivet_config.h>
diff --git a/src/mod_rivet_ng/rivet_lazy_mpm.c b/src/mod_rivet_ng/rivet_lazy_mpm.c
index 9c7f15b..f1e569d 100644
--- a/src/mod_rivet_ng/rivet_lazy_mpm.c
+++ b/src/mod_rivet_ng/rivet_lazy_mpm.c
@@ -276,14 +276,14 @@ static lazy_tcl_worker* create_worker (apr_pool_t* pool,server_rec* server)
 }
 
 /*
- * -- Lazy_MPM_ChildInit
+ * -- Lazy_Bridge_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 Lazy_Bridge_ChildInit (apr_pool_t* pool, server_rec* server)
 {
     apr_status_t    rv;
     server_rec*     s;
@@ -338,7 +338,7 @@ void Lazy_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
     module_globals->mpm->server_shutdown = 0;
 }
 
-/* -- Lazy_MPM_Request
+/* -- Lazy_Bridge_Request
  *
  * The lazy bridge HTTP request function. This function 
  * stores the request_rec pointer into the lazy_tcl_worker
@@ -347,7 +347,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 Lazy_Bridge_Request (request_rec* r,rivet_req_ctype ctype)
 {
     lazy_tcl_worker*    w;
     int                 ap_sts;
@@ -410,11 +410,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
+/* -- Lazy_Bridge_Interp: lazy bridge accessor to the interpreter database
  *
  */
 
-rivet_thread_interp* Lazy_MPM_Interp (rivet_thread_private* private,
+rivet_thread_interp* Lazy_Bridge_Interp (rivet_thread_private* private,
                                       rivet_server_conf*    conf,
                                       rivet_thread_interp*  interp)
 {
@@ -423,7 +423,7 @@ 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 Lazy_Bridge_Finalize (void* data)
 {
     int vh;
     rivet_server_conf* conf = RIVET_SERVER_CONF(((server_rec*) data)->module_config);
@@ -465,7 +465,7 @@ apr_status_t Lazy_MPM_Finalize (void* data)
     return APR_SUCCESS;
 }
 
-int Lazy_MPM_ExitHandler(rivet_thread_private* private)
+int Lazy_Bridge_ExitHandler(rivet_thread_private* private)
 {
 
     /* This is not strictly necessary, because this command will 
@@ -504,16 +504,16 @@ 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);
+    Lazy_Bridge_Finalize (private->r->server);
     return TCL_OK;
 }
 
 DLLEXPORT
 RIVET_MPM_BRIDGE {
     NULL,
-    Lazy_MPM_ChildInit,
-    Lazy_MPM_Request,
-    Lazy_MPM_Finalize,
-    Lazy_MPM_ExitHandler,
-    Lazy_MPM_Interp
+    Lazy_Bridge_ChildInit,
+    Lazy_Bridge_Request,
+    Lazy_Bridge_Finalize,
+    Lazy_Bridge_ExitHandler,
+    Lazy_Bridge_Interp
 };
diff --git a/src/mod_rivet_ng/rivet_prefork_mpm.c b/src/mod_rivet_ng/rivet_prefork_mpm.c
index ad252db..8de9adb 100644
--- a/src/mod_rivet_ng/rivet_prefork_mpm.c
+++ b/src/mod_rivet_ng/rivet_prefork_mpm.c
@@ -19,8 +19,6 @@
     under the License.
  */
 
-/* $Id$ */
-
 #include <apr_strings.h>
 
 #include "mod_rivet.h"
@@ -38,9 +36,9 @@ extern DLLIMPORT apr_threadkey_t*   rivet_thread_key;
 
 rivet_thread_private*   Rivet_VirtualHostsInterps (rivet_thread_private* private);
 
-/* -- Prefork_MPM_Finalize */
+/* -- Prefork_Bridge_Finalize */
 
-apr_status_t Prefork_MPM_Finalize (void* data)
+apr_status_t Prefork_Bridge_Finalize (void* data)
 {
     rivet_thread_private*   private;
     server_rec* s = (server_rec*) data;
@@ -54,13 +52,12 @@ apr_status_t Prefork_MPM_Finalize (void* data)
     return OK;
 }
 
-
-/* -- Prefork_MPM_ChildInit: bridge child process initialization
+/* -- Prefork_Bridge_ChildInit: bridge child process initialization
  *
  */
 
 
-void Prefork_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
+void Prefork_Bridge_ChildInit (apr_pool_t* pool, server_rec* server)
 {
     rivet_thread_private*   private;
 
@@ -103,7 +100,7 @@ void Prefork_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
 }
 
 /*
- * -- Prefork_MPM_Request
+ * -- Prefork_Bridge_Request
  *
  *  The prefork implementation of this function is basically a wrapper of
  *  Rivet_SendContent. The real job is fetching the thread private data
@@ -117,7 +114,7 @@ void Prefork_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
  *   HTTP status code (see the Apache HTTP web server documentation)
  */
 
-int Prefork_MPM_Request (request_rec* r,rivet_req_ctype ctype)
+int Prefork_Bridge_Request (request_rec* r,rivet_req_ctype ctype)
 {
     rivet_thread_private*   private;
 
@@ -162,7 +159,7 @@ rivet_thread_interp* MPM_MasterInterp(server_rec* server)
 }
 
 /*
- * -- Prefork_MPM_ExitHandler
+ * -- Prefork_Bridge_ExitHandler
  *
  *  Just calling Tcl_Exit  
  *
@@ -174,7 +171,7 @@ rivet_thread_interp* MPM_MasterInterp(server_rec* server)
  *  the thread running the Tcl script will exit 
  */
 
-int Prefork_MPM_ExitHandler(rivet_thread_private* private)
+int Prefork_Bridge_ExitHandler(rivet_thread_private* private)
 {
     Tcl_Exit(private->exit_status);
 
@@ -185,7 +182,7 @@ int Prefork_MPM_ExitHandler(rivet_thread_private* private)
     return TCL_OK;
 }
 
-rivet_thread_interp* Prefork_MPM_Interp (rivet_thread_private* private,
+rivet_thread_interp* Prefork_Bridge_Interp (rivet_thread_private* private,
                                          rivet_server_conf*    conf,
                                          rivet_thread_interp*  interp)
 {
@@ -197,10 +194,10 @@ rivet_thread_interp* Prefork_MPM_Interp (rivet_thread_private* private,
 DLLEXPORT
 RIVET_MPM_BRIDGE {
     NULL,
-    Prefork_MPM_ChildInit,
-    Prefork_MPM_Request,
-    Prefork_MPM_Finalize,
-    Prefork_MPM_ExitHandler,
-    Prefork_MPM_Interp
+    Prefork_Bridge_ChildInit,
+    Prefork_Bridge_Request,
+    Prefork_Bridge_Finalize,
+    Prefork_Bridge_ExitHandler,
+    Prefork_Bridge_Interp
 };
 
diff --git a/src/mod_rivet_ng/rivet_worker_mpm.c b/src/mod_rivet_ng/rivet_worker_mpm.c
index 729b4b3..9fdfc23 100644
--- a/src/mod_rivet_ng/rivet_worker_mpm.c
+++ b/src/mod_rivet_ng/rivet_worker_mpm.c
@@ -136,8 +136,18 @@ void Worker_Bridge_Shutdown (void)
     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;
-    threads_to_stop = apr_atomic_read32(module_globals->mpm->threads_count);
     do
     {
 
@@ -154,6 +164,7 @@ void Worker_Bridge_Shutdown (void)
             apr_sleep(200000);
             continue;
         }
+
         thread_obj = (handler_private*)v;
         apr_thread_mutex_lock(thread_obj->mutex);
         thread_obj->status = init;
@@ -352,7 +363,7 @@ static void supervisor_housekeeping (void)
  * 
  * This function runs within a single thread and to the
  * start and stop of Tcl worker thread pool. It could be extended also
- * provide some basic monitoring data. 
+ * to provide some basic monitoring data. 
  *
  * As we don't delete Tcl interpreters anymore because it can lead
  * to seg faults or delays the supervisor threads doesn't restart
@@ -405,7 +416,8 @@ static void* APR_THREAD_FUNC threaded_bridge_supervisor (apr_thread_t *thd, void
                     /* terminated thread restart */
 
                     rv = create_worker_thread (&((apr_thread_t **)mpm->workers)[i]);
-                    if (rv != APR_SUCCESS) {
+                    if (rv != APR_SUCCESS) 
+                    {
                         char errorbuf[RIVET_MSG_BUFFER_SIZE];
 
                         /* we shouldn't ever be in the condition of not being able to start a new thread
@@ -424,15 +436,17 @@ 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)
-    {
+    /*
+     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);
@@ -440,10 +454,10 @@ static void* APR_THREAD_FUNC threaded_bridge_supervisor (apr_thread_t *thd, void
     return NULL;
 }
 
-// int Worker_MPM_ServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server_rec *s) { return OK; }
+// int Worker_Bridge_ServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server_rec *s) { return OK; }
 
 /*
- * -- Worker_MPM_ChildInit
+ * -- Worker_Bridge_ChildInit
  *
  * Child initialization function called by the web server framework.
  * For this bridge tasks are 
@@ -454,7 +468,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;
     
@@ -468,7 +482,8 @@ void Worker_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
 
     module_globals->mpm = apr_pcalloc(pool,sizeof(mpm_bridge_status));
 
-    /* apr_calloc is supposed to allocate zerod memory, but we still make esplicit the initialization
+    /* apr_calloc is supposed to allocate zeroed memory,
+     * but we still make esplicit the initialization
      * of some of its fields
      */
 
@@ -574,7 +589,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 
@@ -594,7 +609,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;
@@ -651,35 +666,27 @@ 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;
-    
-    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);
 
     /* 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
+     * 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 
      */
 
     if (!module_globals->mpm->exit_command)
     {
+        Worker_Bridge_Shutdown();
+
         rv = apr_thread_join (&thread_status,module_globals->mpm->supervisor);
         if (rv != APR_SUCCESS)
         {
@@ -689,6 +696,8 @@ apr_status_t Worker_MPM_Finalize (void* data)
     }
 
     // apr_threadkey_private_delete (handler_thread_key);
+    exit(module_globals->mpm->exit_command_status);
+
     return OK;
 }
 
@@ -717,7 +726,7 @@ rivet_thread_interp* MPM_MasterInterp(server_rec* s)
 }
 
 /*
- * -- 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
@@ -730,12 +739,15 @@ 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 */
+     * eventually terminate the whole processes
+     */
 
-    /* This will force the current thread to exit */
+    /* By setting this flag to 0 we let the thread exit when the
+     * request processing has completed 
+     */
 
     private->ext->keep_going = 0;
 
@@ -744,17 +756,21 @@ int Worker_MPM_ExitHandler(rivet_thread_private* private)
 
     /* In case single_thread_exit we return preparing this thread to exit */
  
-    if (private->running_conf->single_thread_exit) return TCL_OK;
-
-    /* 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() */
+    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_MPM_Finalize (private->r->server);
+        Worker_Bridge_Finalize (private->r->server);
 
+    }
+    
     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)
 {
@@ -766,9 +782,9 @@ 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
 };


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tcl.apache.org
For additional commands, e-mail: commits-help@tcl.apache.org