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/24 13:01:26 UTC

[tcl-rivet] 01/01: single thread exit code for mod_rivet 3.2

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

commit ca4eb9431b65e16a1e0453dd1e70f19a66e124da
Author: Massimo Manghi <mx...@apache.org>
AuthorDate: Mon Jun 24 15:01:02 2019 +0200

    single thread exit code for mod_rivet 3.2
---
 src/mod_rivet_ng/apache_config.c         | 54 +++++++++++++++++---------------
 src/mod_rivet_ng/mod_rivet.c             |  2 --
 src/mod_rivet_ng/mod_rivet.h             | 42 ++++++++++++++-----------
 src/mod_rivet_ng/mod_rivet_common.c      | 43 ++++++++++++++++++++++---
 src/mod_rivet_ng/mod_rivet_common.h      |  6 ++--
 src/mod_rivet_ng/mod_rivet_generator.c   | 18 +++--------
 src/mod_rivet_ng/mod_rivet_generator.h   |  4 +--
 src/mod_rivet_ng/rivetCore.c             |  2 +-
 src/mod_rivet_ng/rivet_lazy_mpm.c        | 14 ++++-----
 src/mod_rivet_ng/rivet_prefork_mpm.c     | 12 ++++---
 src/mod_rivet_ng/rivet_worker_mpm.c      | 48 ++++++++++++++--------------
 src/mod_rivet_ng/worker_prefork_common.c | 18 +++++------
 12 files changed, 146 insertions(+), 117 deletions(-)

diff --git a/src/mod_rivet_ng/apache_config.c b/src/mod_rivet_ng/apache_config.c
index e82472d..da34b38 100644
--- a/src/mod_rivet_ng/apache_config.c
+++ b/src/mod_rivet_ng/apache_config.c
@@ -15,8 +15,6 @@
    limitations under the License.
 */
 
-/* $Id$ */
-
 /* Rivet config */
 #ifdef HAVE_CONFIG_H
 #include <rivet_config.h>
@@ -221,13 +219,14 @@ Rivet_CopyConfig( rivet_server_conf *oldrsc, rivet_server_conf *newrsc )
     newrsc->after_every_script = oldrsc->after_every_script;
     //newrsc->user_scripts_updated = oldrsc->user_scripts_updated;
     //newrsc->rivet_default_error_script = oldrsc->rivet_default_error_script;
-    newrsc->default_cache_size = oldrsc->default_cache_size;
-    newrsc->upload_max = oldrsc->upload_max;
+    newrsc->default_cache_size  = oldrsc->default_cache_size;
+    newrsc->upload_max          = oldrsc->upload_max;
     newrsc->upload_files_to_var = oldrsc->upload_files_to_var;
     newrsc->separate_virtual_interps = oldrsc->separate_virtual_interps;
     newrsc->export_rivet_ns = oldrsc->export_rivet_ns;
     newrsc->import_rivet_ns = oldrsc->import_rivet_ns;
     newrsc->honor_header_only_reqs = oldrsc->honor_header_only_reqs;
+    newrsc->single_thread_exit = oldrsc->single_thread_exit;
     newrsc->separate_channels = oldrsc->separate_channels;
     newrsc->server_name = oldrsc->server_name;
     newrsc->upload_dir = oldrsc->upload_dir;
@@ -237,7 +236,6 @@ Rivet_CopyConfig( rivet_server_conf *oldrsc, rivet_server_conf *newrsc )
     newrsc->idx = oldrsc->idx;
     newrsc->path = oldrsc->path;
     newrsc->mpm_bridge = oldrsc->mpm_bridge;
-    //newrsc->user_conf = oldrsc->user_conf;
     newrsc->user_scripts_status = oldrsc->user_scripts_status;
 }
 
@@ -409,13 +407,13 @@ Rivet_MergeConfig(apr_pool_t *p, void *basev, void *overridesv)
 
     rsc->separate_virtual_interps = base->separate_virtual_interps;
     rsc->honor_header_only_reqs = base->honor_header_only_reqs;
+    rsc->single_thread_exit = base->single_thread_exit;
     rsc->separate_channels = base->separate_channels;
     rsc->import_rivet_ns = base->import_rivet_ns;
     rsc->export_rivet_ns = base->export_rivet_ns;
     rsc->mpm_bridge = base->mpm_bridge;
     rsc->upload_max = base->upload_max;
     rsc->upload_dir = base->upload_dir;
-    
 
     RIVET_CONF_SELECT(rsc,base,overrides,upload_dir)
     RIVET_CONF_SELECT(rsc,base,overrides,rivet_server_vars)
@@ -449,7 +447,7 @@ Rivet_CreateConfig(apr_pool_t *p, server_rec *s )
     rsc->rivet_child_init_script    = NULL;
     rsc->rivet_child_exit_script    = NULL;
     rsc->rivet_before_script        = NULL;
-    //rsc->request_handler            = "::Rivet::request_handling";
+    //rsc->request_handler          = "::Rivet::request_handling";
     rsc->request_handler            = NULL;
 
     rsc->rivet_after_script         = NULL;
@@ -468,6 +466,7 @@ Rivet_CreateConfig(apr_pool_t *p, server_rec *s )
     rsc->export_rivet_ns            = RIVET_NAMESPACE_EXPORT;
     rsc->import_rivet_ns            = RIVET_NAMESPACE_IMPORT;
     rsc->honor_header_only_reqs     = RIVET_HEAD_REQUESTS;
+    rsc->single_thread_exit         = 0;
     rsc->separate_channels          = RIVET_SEPARATE_CHANNELS;
     rsc->upload_dir                 = RIVET_UPLOAD_DIR;
     rsc->server_name                = NULL;
@@ -617,6 +616,7 @@ Rivet_DirConf(cmd_parms *cmd,void *vrdc,const char *var,const char *val)
  *  RivetServerConf SeparateVirtualInterps <yes|no>
  *  RivetServerConf HonorHeaderOnlyRequests <yes|no> (2008-06-20: mm)
  *  RivetServerConf MpmBridge <path-to-mpm-bridge>|<bridge-label> (2015-12-14: mm)
+ *  RivetServerConf SingleThreadExit <On|Off> (2019-05-23: mm)
  */
 
 const char *
@@ -632,31 +632,33 @@ Rivet_ServerConf(cmd_parms *cmd,void *dummy,const char *var,const char *val)
         return "Rivet Error: RivetServerConf requires two arguments";
     }
 
-    if ( STREQU ( var, "CacheSize" ) ) {
+    if (STREQU (var,"CacheSize")) {
         rsc->default_cache_size = strtol( val, NULL, 10 );
-    } else if ( STREQU ( var, "UploadDirectory" ) ) {
+    } else if (STREQU (var,"UploadDirectory")) {
         rsc->upload_dir = val;
-    } else if ( STREQU ( var, "UploadMaxSize" ) ) {
-        rsc->upload_max = strtol( val, NULL, 10 );
-    } else if ( STREQU ( var, "UploadFilesToVar" ) ) {
-        Tcl_GetBoolean (NULL, val, &rsc->upload_files_to_var);
-    } else if ( STREQU ( var, "SeparateVirtualInterps" ) ) {
-        Tcl_GetBoolean (NULL, val, &rsc->separate_virtual_interps);
-    } else if ( STREQU ( var, "HonorHeaderOnlyRequests" ) ) {
-        Tcl_GetBoolean (NULL, val, &rsc->honor_header_only_reqs);
-    } else if ( STREQU ( var, "SeparateChannels" ) ) {
-        Tcl_GetBoolean (NULL, val, &rsc->separate_channels);
-    } else if ( STREQU ( var, "MpmBridge" ) ) {
+    } else if (STREQU (var,"UploadMaxSize")) {
+        rsc->upload_max = strtol(val,NULL,10);
+    } else if (STREQU (var,"UploadFilesToVar")) {
+        Tcl_GetBoolean (NULL,val,&rsc->upload_files_to_var);
+    } else if (STREQU (var,"SeparateVirtualInterps")) {
+        Tcl_GetBoolean (NULL,val,&rsc->separate_virtual_interps);
+    } else if (STREQU (var,"HonorHeaderOnlyRequests")) {
+        Tcl_GetBoolean (NULL,val,&rsc->honor_header_only_reqs);
+    } else if (STREQU (var,"SingleThreadExit")) {
+        Tcl_GetBoolean (NULL,val,&rsc->single_thread_exit);
+    } else if (STREQU (var,"SeparateChannels")) {
+        Tcl_GetBoolean (NULL,val,&rsc->separate_channels);
+    } else if (STREQU (var,"MpmBridge")) {
         rsc->mpm_bridge = val;
-    } else if ( STREQU (var, "ImportRivetNS")) {
-        Tcl_GetBoolean (NULL,val, &rsc->import_rivet_ns);
-    } else if ( STREQU (var,"ExportRivetNS")) {
-        Tcl_GetBoolean (NULL, val, &rsc->export_rivet_ns);
+    } else if (STREQU (var,"ImportRivetNS")) {
+        Tcl_GetBoolean (NULL,val,&rsc->import_rivet_ns);
+    } else if (STREQU (var,"ExportRivetNS")) {
+        Tcl_GetBoolean (NULL,val,&rsc->export_rivet_ns);
     } else {
-        string = Rivet_SetScript( cmd->pool, rsc, var, val);
+        string = Rivet_SetScript(cmd->pool,rsc,var,val);
     }
 
-    if (string != NULL) apr_table_set( rsc->rivet_server_vars, var, string );
+    if (string != NULL) apr_table_set(rsc->rivet_server_vars, var, string);
     return(NULL);
 }
 
diff --git a/src/mod_rivet_ng/mod_rivet.c b/src/mod_rivet_ng/mod_rivet.c
index 6cb94a5..c6ffb60 100644
--- a/src/mod_rivet_ng/mod_rivet.c
+++ b/src/mod_rivet_ng/mod_rivet.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/mod_rivet.h b/src/mod_rivet_ng/mod_rivet.h
index a3633a5..16ffa87 100644
--- a/src/mod_rivet_ng/mod_rivet.h
+++ b/src/mod_rivet_ng/mod_rivet.h
@@ -19,8 +19,6 @@
     under the License.
 */
 
-/* $Id$ */
-
 #ifndef __mod_rivet_h__
 #define __mod_rivet_h__
 
@@ -39,13 +37,13 @@
 
 /*
  * Petasis 16 Dec 2018: This causes the symbol to be exported also from MPMs...
-
-  APLOG_USE_MODULE(rivet);
-
-  PLEASE: do not use any of APLOG_USE_MODULE, AP_DECLARE_MODULE,
-  AP_MODULE_DECLARE_DATA in this header file!
- 
-*/
+ *
+ * APLOG_USE_MODULE(rivet);
+ *
+ *  PLEASE: do not use any of APLOG_USE_MODULE, AP_DECLARE_MODULE,
+ *  AP_MODULE_DECLARE_DATA in this header file!
+ *
+ */
 
 /* init.tcl file relative to the server root directory */
 
@@ -95,10 +93,10 @@
 
 /*
  * Petasis 10 Aug 2017: This causes the symbol to be exported also from MPMs...
-
-   module AP_MODULE_DECLARE_DATA rivet_module;
- 
-*/
+ *
+ *  module AP_MODULE_DECLARE_DATA rivet_module;
+ *
+ */
 
 typedef struct _rivet_server_conf {
 
@@ -127,6 +125,9 @@ typedef struct _rivet_server_conf {
     int             upload_files_to_var;
     int             separate_virtual_interps;
     int             honor_header_only_reqs;
+    int             single_thread_exit;     /* Allow bridges to exit a single thread instead of
+                                             * forcing a whole process */
+
     int             separate_channels;      /* when true a vhosts get their private channel */
     int             export_rivet_ns;        /* export the ::rivet namespace commands        */
     int             import_rivet_ns;        /* import into the global namespace the
@@ -136,10 +137,10 @@ typedef struct _rivet_server_conf {
     apr_table_t*    rivet_server_vars;
     apr_table_t*    rivet_dir_vars;
     apr_table_t*    rivet_user_vars;
-    int             idx;                /* server record index (to be used for the interps db)      */
-    char*           path;               /* copy of the path field of a cmd_parms structure:         
-                                         * should enable us to tell if a conf record comes from a
-                                         * Directory section */
+    int             idx;                /* server record index (to be used for the interps db)          */
+    char*           path;               /* copy of the path field of a cmd_parms structure:             *
+                                         * should enable us to tell if a conf record comes from a       *
+                                         * Directory section                                            */
     const char*     mpm_bridge;         /* MPM bridge. if not null the module will try to load the      * 
                                          * file name in this field. The string should be either a full  *
                                          * path to a file name, or a string from which a file name will *
@@ -182,7 +183,7 @@ typedef void                    (RivetBridge_ThreadInit)    (apr_pool_t* pPool,s
 typedef int                     (RivetBridge_Request)       (request_rec*,rivet_req_ctype);
 typedef apr_status_t            (RivetBridge_Finalize)      (void*);
 typedef rivet_thread_interp*    (RivetBridge_Master_Interp) (void);
-typedef int                     (RivetBridge_Exit_Handler)  (int);
+typedef int                     (RivetBridge_Exit_Handler)  (rivet_thread_private*);
 typedef rivet_thread_interp*    (RivetBridge_Thread_Interp) (rivet_thread_private*,rivet_server_conf *,rivet_thread_interp*);
 
 typedef struct _mpm_bridge_table {
@@ -313,6 +314,11 @@ Tcl_Obj* Rivet_CurrentServerRec (Tcl_Interp* interp, server_rec* s);
         Tcl_IncrRefCount(running_script->objscript);\
     }
 
+#define RIVET_SCRIPT_DISPOSE(running_scripts,script_name) \
+    if (running_scripts->script_name != NULL) {\
+        Tcl_DecrRefCount(running_scripts->script_name);\
+    }
+
 #define RIVET_MPM_BRIDGE_TABLE         bridge_jump_table
 #define RIVET_MPM_BRIDGE_FUNCTION(fun) module_globals->bridge_jump_table->fun
 
diff --git a/src/mod_rivet_ng/mod_rivet_common.c b/src/mod_rivet_ng/mod_rivet_common.c
index 7c3b8a8..f7931d7 100644
--- a/src/mod_rivet_ng/mod_rivet_common.c
+++ b/src/mod_rivet_ng/mod_rivet_common.c
@@ -21,8 +21,6 @@
     under the License.
 */
 
-/* $Id$ */
-
 #include <httpd.h>
 #include <apr_strings.h>
 #include <apr_env.h>
@@ -102,8 +100,7 @@ Rivet_ReadFile (apr_pool_t* pool,char* filename,
     return 0;
 }
 
-/*
- *-----------------------------------------------------------------------------
+/*-----------------------------------------------------------------------------
  * Rivet_CreateTclInterp --
  *
  * Arguments:
@@ -184,6 +181,44 @@ running_scripts* Rivet_RunningScripts ( apr_pool_t* pool,
 }
 
 /*
+ *  -- Rivet_ReleaseRunningScripts 
+ *
+ */
+
+void Rivet_ReleaseRunningScripts (running_scripts* scripts)
+{
+    RIVET_SCRIPT_DISPOSE(scripts,rivet_before_script);
+    RIVET_SCRIPT_DISPOSE(scripts,rivet_after_script);
+    RIVET_SCRIPT_DISPOSE(scripts,rivet_error_script);
+    RIVET_SCRIPT_DISPOSE(scripts,rivet_abort_script);
+    RIVET_SCRIPT_DISPOSE(scripts,after_every_script);
+    RIVET_SCRIPT_DISPOSE(scripts,request_processing);
+}
+
+/*
+ * -- Rivet_ReleasePerDirScripts
+ *
+ */
+
+void Rivet_ReleasePerDirScripts(rivet_thread_interp* rivet_interp)
+{
+    apr_hash_t*         ht = rivet_interp->per_dir_scripts;
+    apr_hash_index_t*   hi;
+    Tcl_Obj*            script;
+    apr_pool_t*         p = rivet_interp->pool;
+
+    for (hi = apr_hash_first(p,ht); hi; hi = apr_hash_next(hi))
+    {
+        apr_hash_this(hi, NULL, NULL, (void*)(&script));
+        Tcl_DecrRefCount(script);
+    }
+
+    apr_hash_clear(ht);
+
+}
+
+
+/*
  *---------------------------------------------------------------------
  *
  * Rivet_PerInterpInit --
diff --git a/src/mod_rivet_ng/mod_rivet_common.h b/src/mod_rivet_ng/mod_rivet_common.h
index e074ff6..e1a1314 100644
--- a/src/mod_rivet_ng/mod_rivet_common.h
+++ b/src/mod_rivet_ng/mod_rivet_common.h
@@ -19,11 +19,12 @@
     under the License.
 */
 
-#ifndef _MOD_RIVET_COMMON_
-#define _MOD_RIVET_COMMON_
+#ifndef __mod_rivet_common__
+#define __mod_rivet_common__
 
 EXTERN running_scripts* Rivet_RunningScripts (apr_pool_t* pool,running_scripts* scripts,rivet_server_conf* rivet_conf);
 EXTERN void Rivet_PerInterpInit(rivet_thread_interp* interp_obj,rivet_thread_private* private, server_rec *s, apr_pool_t *p);
+EXTERN void Rivet_ReleaseRunningScripts (running_scripts* scripts);
 EXTERN void Rivet_CreateCache (apr_pool_t *p, rivet_thread_interp* interp_obj);
 EXTERN rivet_thread_interp* Rivet_NewVHostInterp(apr_pool_t *pool,server_rec* s);
 EXTERN void Rivet_ProcessorCleanup (void *data);
@@ -37,5 +38,6 @@ EXTERN rivet_thread_private* Rivet_ExecutionThreadInit (void);
 EXTERN rivet_thread_private* Rivet_SetupTclPanicProc (void);
 EXTERN void Rivet_ReleaseRivetChannel (Tcl_Interp* interp, Tcl_Channel* channel);
 EXTERN int Rivet_ReadFile (apr_pool_t* pool,char* filename,char** buffer,int* nbytes);
+EXTERN void Rivet_ReleasePerDirScripts(rivet_thread_interp* rivet_interp);
 
 #endif
diff --git a/src/mod_rivet_ng/mod_rivet_generator.c b/src/mod_rivet_ng/mod_rivet_generator.c
index d11d57b..5adae3a 100644
--- a/src/mod_rivet_ng/mod_rivet_generator.c
+++ b/src/mod_rivet_ng/mod_rivet_generator.c
@@ -19,8 +19,6 @@
     under the License.
 */
 
-/* $Id$ */
-
 #include <httpd.h>
 #include <tcl.h>
 #include <apr_strings.h>
@@ -113,7 +111,7 @@ Rivet_ReleaseScripts (running_scripts* scripts)
 #define USE_APACHE_RSC
 
 DLLEXPORT int
-Rivet_SendContent(rivet_thread_private *private,request_rec* r)
+Rivet_SendContent(rivet_thread_private *private)
 {
     int                     errstatus;
     int                     retval;
@@ -121,14 +119,6 @@ Rivet_SendContent(rivet_thread_private *private,request_rec* r)
     rivet_thread_interp*    interp_obj;
     Tcl_Channel*            running_channel;
 
-#ifdef USE_APACHE_RSC
-    //rivet_server_conf    *rsc = NULL;
-#else
-    //rivet_server_conf    *rdc;
-#endif
-
-    private->r = r;
-
     /* Set the global request req to know what we are dealing with in
      * case we have to call the PanicProc. */
 
@@ -146,7 +136,7 @@ Rivet_SendContent(rivet_thread_private *private,request_rec* r)
 
     interp_obj = RIVET_PEEK_INTERP(private,private->running_conf);
     private->running = interp_obj->scripts;
-    running_channel = interp_obj->channel;
+    running_channel  = interp_obj->channel;
 
     if (private->r->per_dir_config)
     {
@@ -345,9 +335,9 @@ sendcleanup:
     {
         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->exit_status);
+        RIVET_MPM_BRIDGE_CALL(exit_handler,private);
         //Tcl_Exit(private->exit_status);
-        exit(private->exit_status);
+        //exit(private->exit_status);
     }
 
     /* We now reset the status to prepare the child process for another request */
diff --git a/src/mod_rivet_ng/mod_rivet_generator.h b/src/mod_rivet_ng/mod_rivet_generator.h
index 788acf3..00de5e0 100644
--- a/src/mod_rivet_ng/mod_rivet_generator.h
+++ b/src/mod_rivet_ng/mod_rivet_generator.h
@@ -19,8 +19,6 @@
     under the License.
 */
 
-/* $Id$ */
-
 #ifndef __mod_rivet_generator_h__
 #define __mod_rivet_generator_h__
 
@@ -29,6 +27,6 @@
 extern int Rivet_CheckType (request_rec* r);
 extern int Rivet_ParseExecFile (rivet_thread_private* req, char* filename, int toplevel);
 extern int Rivet_ParseExecString (rivet_thread_private* req, Tcl_Obj* inbuf);
-extern int Rivet_SendContent (rivet_thread_private* private,request_rec* r);
+extern int Rivet_SendContent (rivet_thread_private* private);
 
 #endif
diff --git a/src/mod_rivet_ng/rivetCore.c b/src/mod_rivet_ng/rivetCore.c
index 38aef69..e8c3dfd 100644
--- a/src/mod_rivet_ng/rivetCore.c
+++ b/src/mod_rivet_ng/rivetCore.c
@@ -1455,7 +1455,7 @@ TCL_CMD_HEADER( Rivet_ExitCmd )
     private->abort_code = Tcl_NewDictObj();
 
     /* The private->abort_code ref count is decremented before 
-     * request processing terminates*/
+     * request processing terminates */
 
     Tcl_IncrRefCount(private->abort_code);
 
diff --git a/src/mod_rivet_ng/rivet_lazy_mpm.c b/src/mod_rivet_ng/rivet_lazy_mpm.c
index d406f55..9c7f15b 100644
--- a/src/mod_rivet_ng/rivet_lazy_mpm.c
+++ b/src/mod_rivet_ng/rivet_lazy_mpm.c
@@ -19,8 +19,6 @@
     under the License.
  */
 
-/* $Id$ */
-
 #include <httpd.h>
 #include <http_request.h>
 #include <ap_compat.h>
@@ -219,8 +217,9 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
 
         private->req_cnt++;
         private->ctype = w->ctype;
+        private->r = w->r;
 
-        w->ap_sts = Rivet_SendContent(private,w->r);
+        w->ap_sts = Rivet_SendContent(private);
 
         if (module_globals->mpm->server_shutdown) continue;
 
@@ -466,11 +465,8 @@ apr_status_t Lazy_MPM_Finalize (void* data)
     return APR_SUCCESS;
 }
 
-int Lazy_MPM_ExitHandler(int code)
+int Lazy_MPM_ExitHandler(rivet_thread_private* private)
 {
-    rivet_thread_private*   private;
-
-    RIVET_PRIVATE_DATA_NOT_NULL(rivet_thread_key,private)
 
     /* This is not strictly necessary, because this command will 
      * eventually terminate the whole processes */
@@ -498,10 +494,12 @@ int Lazy_MPM_ExitHandler(int code)
     if (module_globals->mpm->exit_command == 0)
     {
         module_globals->mpm->exit_command = 1;
-        module_globals->mpm->exit_command_status = code;
+        module_globals->mpm->exit_command_status = private->exit_status;
     }
     apr_thread_mutex_unlock(module_globals->mpm->mutex);
 
+    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() */
diff --git a/src/mod_rivet_ng/rivet_prefork_mpm.c b/src/mod_rivet_ng/rivet_prefork_mpm.c
index d14ec04..ad252db 100644
--- a/src/mod_rivet_ng/rivet_prefork_mpm.c
+++ b/src/mod_rivet_ng/rivet_prefork_mpm.c
@@ -127,8 +127,9 @@ int Prefork_MPM_Request (request_rec* r,rivet_req_ctype ctype)
 
     private->ctype = ctype;
     private->req_cnt++;
+    private->r = r;
 
-    return Rivet_SendContent(private,r);
+    return Rivet_SendContent(private);
 }
 
 rivet_thread_interp* MPM_MasterInterp(server_rec* server)
@@ -173,11 +174,14 @@ rivet_thread_interp* MPM_MasterInterp(server_rec* server)
  *  the thread running the Tcl script will exit 
  */
 
-int Prefork_MPM_ExitHandler(int code)
+int Prefork_MPM_ExitHandler(rivet_thread_private* private)
 {
-    Tcl_Exit(code);
+    Tcl_Exit(private->exit_status);
 
-    /* it will never get here */
+    /* actually we'll never get here but we return
+     * the Tcl return code anyway to silence the 
+     * compilation warning
+     */
     return TCL_OK;
 }
 
diff --git a/src/mod_rivet_ng/rivet_worker_mpm.c b/src/mod_rivet_ng/rivet_worker_mpm.c
index 0f94202..729b4b3 100644
--- a/src/mod_rivet_ng/rivet_worker_mpm.c
+++ b/src/mod_rivet_ng/rivet_worker_mpm.c
@@ -19,8 +19,6 @@
     under the License.
  */
 
-/* $Id$*/
-
 #include <httpd.h>
 #include <math.h>
 #include <tcl.h>
@@ -52,7 +50,7 @@
 extern DLLIMPORT mod_rivet_globals* module_globals;
 extern DLLIMPORT apr_threadkey_t*   rivet_thread_key;
 
-apr_threadkey_t*        handler_thread_key;
+// apr_threadkey_t* handler_thread_key;
 
 #ifdef RIVET_NO_HAVE_ROUND
 int round(double d) { return (int)(d + 0.5); }
@@ -170,7 +168,7 @@ void Worker_Bridge_Shutdown (void)
 }
 
 /*
- * -- request_processor_ng
+ * -- request_processor
  */
 
 static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
@@ -209,13 +207,12 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
     thread_obj = apr_pcalloc(private->pool,sizeof(handler_private));
     ap_assert(apr_thread_cond_create(&(thread_obj->cond), private->pool) == APR_SUCCESS);
     ap_assert(apr_thread_mutex_create(&(thread_obj->mutex),APR_THREAD_MUTEX_UNNESTED,private->pool) 
-                                                                          == APR_SUCCESS);
+                                                                         == APR_SUCCESS);
 
     thread_obj->status = idle;
-
     apr_thread_mutex_unlock(module_globals->mpm->job_mutex); /* unlock job initialization stage */
 
-        /* eventually we increment the number of active threads */
+    /* eventually we increment the number of active threads */
 
     apr_atomic_inc32(module_globals->mpm->threads_count);
 
@@ -255,14 +252,14 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
 
         private->ctype = thread_obj->ctype;
         private->req_cnt++;
+        private->r = thread_obj->r;
 
-        HTTP_REQUESTS_PROC(thread_obj->code = Rivet_SendContent(private,thread_obj->r));
+        HTTP_REQUESTS_PROC(thread_obj->code = Rivet_SendContent(private));
 
         thread_obj->status = done;
-        if (private->thread_exit) thread_obj->status = child_exit;
+        // if (private->thread_exit) thread_obj->status = child_exit;
 
         apr_thread_cond_signal(thread_obj->cond);
-
         while (thread_obj->status != idle)
         {
             apr_thread_cond_wait(thread_obj->cond,thread_obj->mutex);
@@ -272,11 +269,11 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
     } while (private->ext->keep_going > 0);
 
     apr_thread_mutex_unlock(thread_obj->mutex);
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, module_globals->server, "processor thread orderly exit");
+    ap_log_error(APLOG_MARK,APLOG_DEBUG,0,module_globals->server,"processor thread orderly exit");
 
-    /* We don't clean up the thread resources anymore, if the thread exits the whole process terminates
-     * As long as Tcl can't safely delete interpreters this is the way things must be done */
-    // Rivet_ProcessorCleanup(private);
+    /* We reestablish the single thread and interpreter cleanup */
+    
+    Rivet_ProcessorCleanup(private);
 
     apr_thread_mutex_lock(module_globals->mpm->job_mutex);
     *(apr_thread_t **) apr_array_push(module_globals->mpm->exiting) = thd;
@@ -495,7 +492,7 @@ void Worker_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
 
     /* This is the thread key for the framework thread calling the content generation callback */
 
-    ap_assert (apr_threadkey_private_create(&handler_thread_key,NULL,pool) == APR_SUCCESS);
+    // ap_assert (apr_threadkey_private_create(&handler_thread_key,NULL,pool) == APR_SUCCESS);
 
     /* This bridge keeps an array of the ids of threads about to exit. This array is protected by
      * the mutex module_globals->job_mutex and signals through module_globals->job_cond
@@ -513,8 +510,9 @@ void Worker_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
         exit(1);
     }
 
-    /* In order to set up some workload balancing let's 
-     * query apache for some configuration parameters of the worker MPM 
+    /* In order to set up some workload balancing let's
+     * query apache some configuration parameters of
+     * the worker MPM 
      */
 
     if (ap_mpm_query(AP_MPMQ_MAX_THREADS,&module_globals->mpm->max_threads) != APR_SUCCESS)
@@ -570,8 +568,8 @@ apr_status_t Worker_RequestPrivateCleanup (void *client_data)
                  MODNAME ": request thread private data released");
 
     /* we have to invalidate the data pointer */
+    // apr_threadkey_private_set (NULL,handler_thread_key);
 
-    apr_threadkey_private_set (NULL,handler_thread_key);
     return APR_SUCCESS;
 }
 
@@ -732,12 +730,8 @@ rivet_thread_interp* MPM_MasterInterp(server_rec* s)
  *  the thread running the Tcl script will exit 
  */
 
-int Worker_MPM_ExitHandler(int code)
+int Worker_MPM_ExitHandler(rivet_thread_private* private)
 {
-    rivet_thread_private*   private;
-
-    RIVET_PRIVATE_DATA_NOT_NULL(rivet_thread_key,private)
-
     /* This is not strictly necessary, because this command will 
      * eventually terminate the whole processes */
 
@@ -746,11 +740,15 @@ int Worker_MPM_ExitHandler(int code)
     private->ext->keep_going = 0;
 
     module_globals->mpm->exit_command = 1;
-    module_globals->mpm->exit_command_status = code;
+    module_globals->mpm->exit_command_status = private->exit_status;
+
+    /* 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() */
- 
+
     Worker_MPM_Finalize (private->r->server);
 
     return TCL_OK;
diff --git a/src/mod_rivet_ng/worker_prefork_common.c b/src/mod_rivet_ng/worker_prefork_common.c
index a4a0a56..17b2dac 100644
--- a/src/mod_rivet_ng/worker_prefork_common.c
+++ b/src/mod_rivet_ng/worker_prefork_common.c
@@ -303,13 +303,14 @@ void Rivet_ProcessorCleanup (void *data)
 
         Tcl_DeleteInterp(private->ext->interps[i]->interp);
 
-       /* TODO: in view of restoring the ability of single Tcl interpreter deletion
-        * we must also consider to release the per-dir scripts hash table
-        * and the Tcl objects storing request handlers (this probably requires
-        * request handlers object to be instantiated by calling Tcl_DuplicateObj when
-        * needed TODO
-        */
-  
+        /* Release interpreter scripts */
+
+        Rivet_ReleaseRunningScripts(private->ext->interps[i]->scripts);
+
+        /* Release scripts defined within <Directory...></Directory> conf blocks */
+
+        Rivet_ReleasePerDirScripts(private->ext->interps[i]);
+
         /* if separate_virtual_interps == 0 we are running the same interpreter
          * instance for each vhost, thus we can jump out of this loop after 
          * the first cycle as the only real intepreter object we have is stored
@@ -318,7 +319,4 @@ void Rivet_ProcessorCleanup (void *data)
 
     } while ((++i < module_globals->vhosts_count) && rsc->separate_virtual_interps);
 
-    //Tcl_DecrRefCount(private->request_init);
-    //Tcl_DecrRefCount(private->request_cleanup);
-    apr_pool_destroy(private->pool);
 }


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