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:25 UTC

[tcl-rivet] branch single-thread-exit created (now ca4eb94)

This is an automated email from the ASF dual-hosted git repository.

mxmanghi pushed a change to branch single-thread-exit
in repository https://gitbox.apache.org/repos/asf/tcl-rivet.git.


      at ca4eb94  single thread exit code for mod_rivet 3.2

This branch includes the following new commits:

     new ca4eb94  single thread exit code for mod_rivet 3.2

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



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


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

Posted by mx...@apache.org.
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