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 2020/10/01 23:33:45 UTC

[tcl-rivet] 07/07: merging master into quattuor, reorganizing internal database and adding new debugging function

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

commit 395b4129a2c9b765a3e92b80f0fa066a2d0aaa89
Author: Massimo Manghi <mx...@apache.org>
AuthorDate: Fri Oct 2 01:32:55 2020 +0200

    merging master into quattuor, reorganizing internal database and adding new debugging function
---
 ChangeLog                                |  28 +++++-
 configure.ac                             |  28 +++++-
 doc/xml/directives.xml                   | 103 +++++++++++---------
 src/mod_rivet_ng/apache_config.c         |  37 ++++----
 src/mod_rivet_ng/mod_rivet.c             | 127 ++++++++++++++-----------
 src/mod_rivet_ng/mod_rivet.h             | 126 ++++++++++++++-----------
 src/mod_rivet_ng/mod_rivet_cache.c       |  76 ++++++++++++---
 src/mod_rivet_ng/mod_rivet_cache.h       |   6 +-
 src/mod_rivet_ng/mod_rivet_common.c      | 100 ++++++++++----------
 src/mod_rivet_ng/mod_rivet_common.h      |   4 +-
 src/mod_rivet_ng/rivetCore.c             | 155 +++++++++++++++++++++++++------
 src/mod_rivet_ng/rivetInspect.c          |  12 +--
 src/mod_rivet_ng/rivet_lazy_mpm.c        | 101 ++++++++++----------
 src/mod_rivet_ng/rivet_prefork_mpm.c     |  44 +++++++--
 src/mod_rivet_ng/rivet_worker_mpm.c      |  10 +-
 src/mod_rivet_ng/worker_prefork_common.c |  13 +--
 src/rivet.h                              |   4 +-
 17 files changed, 626 insertions(+), 348 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 1b81e09..bbaa408 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,29 @@
+2020-10-01 Massimo Manghi <mx...@apache.org>
+	* src/mod_rivet_ng/rivet_prefork_mpm.c: Fixed trivial bug in checking the
+	rivet cache size
+	* configure.ac: add macro to define preprocessor symbol	RIVET_DEBUG_CODE
+
+2020-09-29 Massimo Manghi <mx...@apache.org>
+	* src/mod_rivet_ng/mod_rivet.[c|h]:
+	* src/mod_rivet_ng/rivet_[prefork|worker|lazy]_mpm.c:
+	* src/mod_rivet_ng/worker_prefork_common.c:
+	* src/mod_rivet_ng/mod_rivet_commit.c:
+	* src/mod_rivet_ng/apache_config.[c|h]: moving also rivet_server_init
+	out of the server configuration and into the module_globals
+
 2020-09-28 Massimo Manghi <mx...@apache.org>
-    * src/mod_rivet_ng/TclWebapache.c: 
-    * src/mod_rivet_ng/TclWeb.c: 
-    * src/mod_rivet_ng/rivetCore.c: integrating development from uploadcmdfix
+	* src/mod_rivet_ng/TclWebapache.c: 
+	* src/mod_rivet_ng/TclWeb.c: 
+	* src/mod_rivet_ng/rivetCore.c: integrating development from uploadcmdfix
+	* src/mod_rivet_ng/mod_rivet.[c|h]:
+	* src/mod_rivet_ng/rivet_[prefork|worker|lazy]_mpm.c:
+	* src/mod_rivet_ng/worker_prefork_common.c:
+	* src/mod_rivet_ng/mod_rivet_commit.c:
+	* src/mod_rivet_ng/apache_config.[c|h]: moving real global setting out
+	of the server configuration record into the module_globals structure,
+	because their global in the first place
+	* doc/xml/directives.xml: extended revision of the directive
+	scope documentation
 
 2020-09-27 Massimo Manghi <mx...@apache.org>
 	* rivet/packages/formbroker/formbroker.tcl: add method form_exists to check for registration
diff --git a/configure.ac b/configure.ac
index 1f5c279..43a9885 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,8 +6,6 @@ dnl
 dnl You need at least autoconf 2.59
 dnl
 #
-# RCS: @(#) $Id$
-
 #-----------------------------------------------------------------------
 # Sample configure.in for Tcl Extensions.  The only places you should
 # need to modify this file are marked by the string __CHANGE__
@@ -573,7 +571,6 @@ AC_DEFUN([RIVET_TCL_LIB],[
     AC_MSG_RESULT([$with_rivet_target_dir])
 ])
 
-
 # DISPLAY_RIVET_VERSION
 #
 # --enable-version-display=[yes|no] (default: no)
@@ -700,6 +697,30 @@ AC_DEFUN([HTTP_REQUESTS_MUTEX],[
     fi
 ])
 
+# -- RIVET_DEBUG_BUILD
+#
+# Defining a symbol for conditional inclusion of code for debugging purposes
+#
+# Default: no
+#
+
+AC_DEFUN([BUILD_DEBUG_CODE],[
+    AC_ARG_ENABLE(
+        rivet_debug_build,
+        [  --enable-rivet-debug-build Includes optional debugging code],
+        [ rivet_debug_build=$enable_rivet_debug_build ],
+        [ rivet_debug_build="no" ]
+    )
+
+    AC_MSG_CHECKING([if we are building mod_rivet for debugging])
+    if test "$rivet_debug_build" = "yes"; then
+        AC_MSG_RESULT([yes])
+        AC_DEFINE(DEBUG_BUILD,1,[we are building mod_rivet with optional code])
+    else
+        AC_MSG_RESULT([no, ordinary build])
+    fi
+])
+
 # RIVET_COMMANDS_EXPORT (--enable-rivet-commands-export).
 # Enable export of commands in Rivet's namespace. Definining this symbols
 # sets the boolean configuration variable rivet_commands_export 
@@ -836,6 +857,7 @@ RIVET_CORE_CMDS
 RIVET_CHANNEL
 SINGLE_WORKER_TCL_THREAD
 HTTP_REQUESTS_MUTEX
+BUILD_DEBUG_CODE
 AC_HEADER_STDBOOL
 
 # Let's separate the point version from the major and minor version
diff --git a/doc/xml/directives.xml b/doc/xml/directives.xml
index 38113fc..9f707aa 100644
--- a/doc/xml/directives.xml
+++ b/doc/xml/directives.xml
@@ -61,31 +61,35 @@
 					any special request handler should explicitly read this script from the configuration
 					using ::rivet::inspect and evaluate it (see <xref linkend="request">request processing</xref>)</td>
 				</tr>
-				<tr><td>AfterScript</td><td>X</td><td>X</td><td>X</td><td>X</td><td>Special request handler developers
-				should read this script from the configuration calling ::rivet::inspect and evaluate it</td></tr>
+				<tr><td>AfterScript</td><td>X</td><td>X</td><td>X</td><td>X</td><td>Special request handler scripts
+				should read it from the configuration calling ::rivet::inspect and evaluate it</td></tr>
 				<tr><td>AfterEveryScript</td><td>X</td><td>X</td><td>X</td><td>X</td><td>See notes for the AfterScript directive</td></tr>
 				<tr><td>BeforeScript</td><td>X</td><td>X</td><td>X</td><td>X</td>
 					 <td>See notes for the AfterScript directive</td></tr>
-				<tr><td>CacheSize</td><td></td><td></td><td>X</td><td></td><td></td></tr>
+				<tr><td>CacheSize</td><td></td><td></td><td>X</td><td>X</td><td></td></tr>
 				<tr><td>ChildExitScript</td><td></td><td></td><td>X</td><td>X</td><td></td></tr>
 				<tr><td>ChildInitScript</td><td></td><td></td><td>X</td><td>X</td><td></td></tr>
 				<tr><td>ErrorScript</td><td>X</td><td>X</td><td>X</td><td>X</td>
-					<td>Rivet provides a default error handler. In case you are developing your own request
-					handling procedure you need to call that handler yourself or develop a new.
-					See notes for the AbortScript and AfterScript directives</td></tr>
-				<tr><td>ExportRivetNS</td><td></td><td></td><td>X</td><td></td><td></td></tr>
+					<td>Rivet provides a default error handler. In case you are writing your own request
+					handling procedure you need to call this error handler yourself or develop your
+					application specific error handler to be integrated into the RequestHandler script.
+					See also the notes for the AbortScript and AfterScript directives</td></tr>
+				<tr><td>ExportRivetNS</td><td></td><td></td><td>X</td><td>X</td><td>It can be set in a virtual host
+				configuration if SeparateVirtualInterps is On, otherwise this directive can be safely used at the global level only</td></tr>
 				<tr><td>GlobalInitScript</td><td></td><td></td><td>X</td><td></td>
 				    <td>effective only when SeparateVirtualInterps is Off (default)</td></tr>
-				<tr><td>ImportRivetNS</td><td></td><td></td><td>X</td><td></td><td>global setting</td></tr>
-				<tr><td>HonorHeaderOnlyRequests</td><td></td><td></td><td>X</td><td></td><td>global setting</td></tr>
-				<tr><td>MpmBridge</td><td></td><td></td><td>X</td><td></td><td>global setting</td></tr>
+				<tr><td>ImportRivetNS</td><td></td><td></td><td>X</td><td>X</td><td>It can be set in a virtual host
+				configuration if SeparateVirtualInterps is On, otherwise this directive can be safely used at the global level only</td></tr>
+				<tr><td>HonorHeaderOnlyRequests</td><td></td><td></td><td>X</td><td>X</td><td></td></tr>
+				<tr><td>MpmBridge</td><td></td><td></td><td>X</td><td></td><td>global only</td></tr>
 				<tr><td>RequestHandler</td><td></td><td></td><td>X</td><td>X</td><td></td></tr>
-				<tr><td>SeparateChannels</td><td></td><td></td><td>X</td><td></td><td>global setting</td></tr> 
-				<tr><td>SeparateVirtualInterps</td><td></td><td></td><td>X</td><td></td><td>global setting</td></tr> 
-				<tr><td>ServerInitScript</td><td></td><td></td><td>X</td><td></td><td></td></tr>
-				<tr><td>SingleThreadExit</td><td></td><td></td><td>X</td><td></td><td>global setting</td></tr>
-				<tr><td>UploadDirectory</td><td></td><td>X</td><td>X</td><td>X</td><td></td></tr> 
-				<tr><td>UploadFilesToVar</td><td></td><td></td><td>X</td><td></td><td></td></tr> 
+				<tr><td>SeparateChannels</td><td></td><td></td><td>X</td><td></td><td>global only (DEPRECATED: will be
+				replaced in future versions of Rivet)</td></tr> 
+				<tr><td>SeparateVirtualInterps</td><td></td><td></td><td>X</td><td></td><td>global only</td></tr> 
+				<tr><td>ServerInitScript</td><td></td><td></td><td>X</td><td></td><td>global only</td></tr>
+				<tr><td>SingleThreadExit</td><td></td><td></td><td>X</td><td></td><td>global only</td></tr>
+				<tr><td>UploadDirectory</td><td>X</td><td>X</td><td>X</td><td>X</td><td></td></tr> 
+				<tr><td>UploadFilesToVar</td><td></td><td></td><td>X</td><td>X</td><td></td></tr> 
 				<tr><td>UploadMaxSize</td><td></td><td></td><td>X</td><td>X</td><td></td></tr>
 			</tbody>
 		</table>
@@ -292,8 +296,8 @@
 	    		<listitem>
 					<para>
 						Rivet commands are created within the ::rivet namespace. Setting
-						this option you tell mod_rivet to place the whole command set on
-						the export list of namespace, enabling your scripts to import
+						this option mod_rivet places the whole command set on
+						the export list of the ::rivet namespace, enabling your scripts to import
 						them in a different namespace.
 					</para>
 					<para>This option is, by nature, only available at the global level</para>
@@ -318,7 +322,7 @@
 					  response. If the real header has to be examined (e.g. 
 					  for debugging) you can turn this options on. 
 					</para>
-					<para>This option is, by nature, only available at the global level</para>
+					<para>This option is only available at the global level</para>
 	      	</listitem>
 	    	</varlistentry>
 
@@ -335,17 +339,14 @@
 	    		<listitem>
 					<para>
 						Rivet commands are created within the ::rivet namespace. Setting
-						this option you tell mod_rivet to place the whole command set on
-						the export list of namespace (implicitly forcing also ExportRivetNS)
-						and then importing the commands on the namespace export list into the 
-						global namespace
+						this option mod_rivet is told to place the whole command set on
+						the export list of the ::rivet namespace (implicitly forcing also ExportRivetNS)
+						and then importing the commands into the global namespace
 					</para>
-					
 					<note>
 						This option is provided only for compatibility with existing code that assumes
-						mod_rivet commands to reside in the global namespace. It's utterly discouraged to
-						use it and it could be removed in future versions of Rivet
-						This option is, by nature, only available at the global level
+						mod_rivet commands to reside in the global namespace it could be removed in
+						future versions of Rivet. This option is only available at the global level
 					</note>
 	      	</listitem>
 	    	</varlistentry>
@@ -360,17 +361,18 @@
 	      	<listitem>
 					<para>
 						This global only option tells mod_rivet which MPM bridge has
-						to be loaded. The string argument is interpreted
-						first as a name of an MPM bridge and it's interpolated in the
-						string
+						to be loaded. The module attempt to interpolate the argument value
 						<programlisting>bridge = apr_pstrcat(pool,RIVET_DIR,"/mpm/rivet_",rsc->mpm_bridge,"_mpm.so",NULL);</programlisting>
 						Where RIVET_DIR is the location of the rivet libraries whose definition
-						is controlled by the configuration argument <term>--with-rivet-target-dir=DIR</term>.
+						is controlled by the configure switch <command>--with-rivet-target-dir=DIR</command>.
 						For example 
 						<programlisting>RivetServerConf MpmBridge lazy</programlisting> will cause the
-						rivet_lazy_mpm.so library module to be loaded. If such library does not exists
-						mod_rivet tries to check if such definition is the fully qualified path to 
-						such MPM bridge. If this fails the module causes the web server to stop with an error.
+						rivet_lazy_mpm.so library module to be loaded.
+					</para>
+					<para>
+						If such library does not exists mod_rivet tries to check if such definition is actually
+						the fully qualified path to such MPM bridge. If this fails the module causes the web server to stop
+						with an error.
 					</para>
 				</listitem>
 	    	</varlistentry>
@@ -507,16 +509,29 @@
    			</term>
    			<listitem>
 		   		<para>
-		   			Rivet shadows the Tcl <command>exit</command> command with the
-		   			<command>::rivet::exit</command> in order to
-		   			prevent abrupt interruption of execution of a child process when
-		   			multiple thread are running. By default the worker bridge notifies
-		   			all the threads running Tcl interpreters to exit before calling Tcl_Exit.
-		   			If this option is set a single thread terminates executing any ChildExitScript 
-		   			and eventually it's replaced accordingly to
-		   			the thread management policy implemented by the bridge. 
-		   			With the prefork bridge this options reproduces the ordinary
-		   			<command>exit</command> command behavior.
+						The Tcl <command>exit</command> command has a simple implementation that
+						eventually calls Tcl_Exit (which in turn calls stdlib's exit) that forces
+						the immediate deletion of all threads in a process. This behavior would be
+		   			unacceptable with the worker MPM and worker bridge which are fundamentally
+		   			threaded. 
+		   			Therefore Rivet shadows the Tcl <command>exit</command> command with
+		   			<command>::rivet::exit</command> which calls a designated function in
+		   			the running bridge. The prefork bridge simply prepares the child process
+		   			to terminate, whereas the worker bridge is behavior controlled by this option.
+		   			<orderedlist>
+		   				<listitem>If SingleThreadExit is set (default) each thread behaves
+		   				individually and terminates after running the ChildExitScript and deleting 
+		   				its Tcl interpreters</listitem>
+		   				<listitem>If SingleThreadExit is <command>No</command> the worker bridge notifies all threads
+		   				to exit and then calls Tcl_Exit</listitem>
+		   			</orderedlist>
+		   			The latter option might be useful in cases where an application is using
+		   			an improperly developed Tcl extension which might cause a child process to crash when
+		   			calling Tcl_DeleteInterp.
+					</para>
+					<para>
+						The default is <command>No</command> for the prefork bridge (loaded by default if the server
+						runs the prefork MPM) and <command>true</command> for the worker and lazy bridges
 		   		</para>
    			</listitem>
 			</varlistentry>
diff --git a/src/mod_rivet_ng/apache_config.c b/src/mod_rivet_ng/apache_config.c
index 467d47d..5f6fa23 100644
--- a/src/mod_rivet_ng/apache_config.c
+++ b/src/mod_rivet_ng/apache_config.c
@@ -1,6 +1,7 @@
 /* apache_config.c -- configuration functions for apache 2.x */
 
-/* Copyright 2000-2005 The Apache Software Foundation
+/* 
+   Copyright 2002-2020 The Apache Tcl Team
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -15,8 +16,6 @@
    limitations under the License.
 */
 
-/* $Id$ */
-
 /* Rivet config */
 #ifdef HAVE_CONFIG_H
 #include <rivet_config.h>
@@ -224,12 +223,12 @@ Rivet_CopyConfig( rivet_server_conf *oldrsc, rivet_server_conf *newrsc )
     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->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->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;
     newrsc->rivet_server_vars = oldrsc->rivet_server_vars;
@@ -237,7 +236,7 @@ Rivet_CopyConfig( rivet_server_conf *oldrsc, rivet_server_conf *newrsc )
     newrsc->rivet_user_vars = oldrsc->rivet_user_vars;
     newrsc->idx = oldrsc->idx;
     newrsc->path = oldrsc->path;
-    newrsc->mpm_bridge = oldrsc->mpm_bridge;
+    //newrsc->mpm_bridge = oldrsc->mpm_bridge;
     newrsc->user_scripts_status = oldrsc->user_scripts_status;
 }
 
@@ -407,14 +406,14 @@ Rivet_MergeConfig(apr_pool_t *p, void *basev, void *overridesv)
     RIVET_CONF_SELECT(rsc,base,overrides,after_every_script)
     RIVET_CONF_SELECT(rsc,base,overrides,default_cache_size);
 
-    rsc->separate_virtual_interps = base->separate_virtual_interps;
+    //rsc->separate_virtual_interps = base->separate_virtual_interps;
     rsc->honor_header_only_reqs = base->honor_header_only_reqs;
     rsc->upload_files_to_var = base->upload_files_to_var;
-    rsc->single_thread_exit = base->single_thread_exit;
-    rsc->separate_channels = base->separate_channels;
+    //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->mpm_bridge = base->mpm_bridge;
     rsc->upload_max = base->upload_max;
     rsc->upload_dir = base->upload_dir;
     
@@ -466,15 +465,15 @@ Rivet_CreateConfig(apr_pool_t *p, server_rec *s )
     rsc->default_cache_size         = -1;
     rsc->upload_max                 = RIVET_MAX_POST;
     rsc->upload_files_to_var        = RIVET_UPLOAD_FILES_TO_VAR;
-    rsc->separate_virtual_interps   = RIVET_SEPARATE_VIRTUAL_INTERPS;
+    //rsc->separate_virtual_interps   = RIVET_SEPARATE_VIRTUAL_INTERPS;
     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->single_thread_exit         = 0;
+    //rsc->separate_channels          = RIVET_SEPARATE_CHANNELS;
     rsc->upload_dir                 = RIVET_UPLOAD_DIR;
     rsc->server_name                = NULL;
-    rsc->mpm_bridge                 = NULL;
+    //rsc->mpm_bridge                 = NULL;
 
     rsc->rivet_server_vars          = (apr_table_t *) apr_table_make ( p, 4 );
     rsc->rivet_dir_vars             = (apr_table_t *) apr_table_make ( p, 4 );
@@ -645,15 +644,15 @@ Rivet_ServerConf(cmd_parms *cmd,void *dummy,const char *var,const char *val)
     } 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);
+        Tcl_GetBoolean (NULL,val,&module_globals->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);
+        Tcl_GetBoolean (NULL,val,&module_globals->single_thread_exit);
     } else if (STREQU (var,"SeparateChannels")) {
-        Tcl_GetBoolean (NULL,val,&rsc->separate_channels);
+        Tcl_GetBoolean (NULL,val,&module_globals->separate_channels);
     } else if (STREQU (var,"MpmBridge")) {
-        rsc->mpm_bridge = val;
+        module_globals->mpm_bridge = val;
     } else if (STREQU (var,"ImportRivetNS")) {
         Tcl_GetBoolean (NULL,val,&rsc->import_rivet_ns);
     } else if (STREQU (var,"ExportRivetNS")) {
diff --git a/src/mod_rivet_ng/mod_rivet.c b/src/mod_rivet_ng/mod_rivet.c
index c67dd63..e3a114b 100644
--- a/src/mod_rivet_ng/mod_rivet.c
+++ b/src/mod_rivet_ng/mod_rivet.c
@@ -101,15 +101,13 @@ DLLEXPORT module		        rivet_module;
 */
 
 static char*
-Rivet_SeekMPMBridge (apr_pool_t* pool,server_rec* server)
+Rivet_SeekMPMBridge (apr_pool_t* pool)
 {
     char*   mpm_prefork_bridge = "rivet_prefork_mpm.so";
     char*   mpm_worker_bridge  = "rivet_worker_mpm.so";
     char*   mpm_bridge_path;
     int     ap_mpm_result;
 
-    rivet_server_conf* rsc = RIVET_SERVER_CONF( server->module_config );
-
     /* With the env variable RIVET_MPM_BRIDGE we have the chance to tell mod_rivet 
        what bridge custom implementation we want to be loaded */
 
@@ -120,24 +118,24 @@ Rivet_SeekMPMBridge (apr_pool_t* pool,server_rec* server)
 
     /* we now look into the configuration record */
 
-    if (rsc->mpm_bridge != NULL)
+    if (module_globals->mpm_bridge != NULL)
     {
         apr_finfo_t finfo;
         char*       proposed_bridge;
 
-        proposed_bridge = apr_pstrcat(pool,RIVET_MPM_BRIDGE_COMPOSE(rsc->mpm_bridge),NULL);
+        proposed_bridge = apr_pstrcat(pool,RIVET_MPM_BRIDGE_COMPOSE(module_globals->mpm_bridge),NULL);
         if (apr_stat(&finfo,proposed_bridge,APR_FINFO_MIN,pool) == APR_SUCCESS)
         {
             mpm_bridge_path = proposed_bridge;
         } 
-        else if (apr_stat(&finfo,rsc->mpm_bridge,APR_FINFO_MIN,pool) == APR_SUCCESS)
+        else if (apr_stat(&finfo,module_globals->mpm_bridge,APR_FINFO_MIN,pool) == APR_SUCCESS)
         {
-            mpm_bridge_path = apr_pstrdup(pool,rsc->mpm_bridge);
+            mpm_bridge_path = apr_pstrdup(pool,module_globals->mpm_bridge);
         }
         else
-        {
-            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server, 
-                         MODNAME ": MPM bridge %s not found", rsc->mpm_bridge); 
+        {   
+            ap_log_perror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, pool, 
+                         MODNAME ": MPM bridge %s not found", module_globals->mpm_bridge); 
             exit(1);   
         }
 
@@ -169,60 +167,56 @@ Rivet_SeekMPMBridge (apr_pool_t* pool,server_rec* server)
             mpm_bridge_path = apr_pstrdup(pool,mpm_worker_bridge);
         }
         mpm_bridge_path = apr_pstrcat(pool,RIVET_DIR,"/mpm/",mpm_bridge_path,NULL);
+
     }
     return mpm_bridge_path;
 }
 
 /* 
-* -- Rivet_CreateModuleGlobals
-*
-* module globals (mod_rivet_globals) allocation and initialization
-* 
-*/
+ * -- Rivet_CreateModuleGlobals
+ *
+ * module globals (mod_rivet_globals) allocation and initialization.
+ * As of 3.2 the procedure fills the structure fields that can be set
+ * during the pre_config stage of the server initialization
+ * 
+ */
 
 static mod_rivet_globals* 
-Rivet_CreateModuleGlobals (apr_pool_t* pool, server_rec* server)
+Rivet_CreateModuleGlobals (apr_pool_t* pool)
 {
     mod_rivet_globals*  mod_rivet_g;
-
-    mod_rivet_g = apr_palloc(pool,sizeof(mod_rivet_globals));
+   
+    mod_rivet_g = apr_pcalloc(pool,sizeof(mod_rivet_globals));
+    mod_rivet_g->single_thread_exit       = SINGLE_THREAD_EXIT_UNDEF;
+    mod_rivet_g->separate_virtual_interps = RIVET_SEPARATE_VIRTUAL_INTERPS;
+    mod_rivet_g->separate_channels        = RIVET_SEPARATE_CHANNELS;
     if (apr_pool_create(&mod_rivet_g->pool, NULL) != APR_SUCCESS) 
     {
-        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server, 
-                     MODNAME ": could not initialize rivet module global pool");
+        ap_log_perror(APLOG_MARK,APLOG_ERR,APR_EGENERAL,pool,
+                      MODNAME ": could not initialize rivet module global pool");
         exit(1);
     }
 
-    /* This mutex should protect the process wide pool */
-
-    //apr_thread_mutex_create(&mod_rivet_g->pool_mutex, APR_THREAD_MUTEX_UNNESTED, pool);
-
-    /* establishing the name of the bridge to be loaded */
-
-    mod_rivet_g->rivet_mpm_bridge = Rivet_SeekMPMBridge(pool,server);
-
     /* read the default request handler code */
 
     if (Rivet_ReadFile(pool,TCL_HANDLER_FILE,
                             &mod_rivet_g->default_handler,
                             &mod_rivet_g->default_handler_size) > 0)
     {
-        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server, 
+        ap_log_perror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, pool, 
                      MODNAME ": could not read rivet default handler");
         exit(1);
     }
 
-    mod_rivet_g->server = server;
-
     return mod_rivet_g;
 }
 
 /*
-* -- Rivet_Exit_Handler
-*
-* 
-*
-*/
+ * -- Rivet_Exit_Handler
+ *
+ * 
+ *
+ */
 
 int Rivet_Exit_Handler(int code)
 {
@@ -322,9 +316,9 @@ Rivet_RunServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, ser
              * created an interpreter so far we create one
              */
 
-            if ((interp_obj == NULL) || vhost_rsc->separate_virtual_interps) 
+            if ((interp_obj == NULL) || module_globals->separate_virtual_interps) 
             {
-                interp_obj = Rivet_NewVHostInterp(private,s);
+                interp_obj = Rivet_NewVHostInterp(private,vhost_rsc->default_cache_size);
 
                 /* We initialize the interpreter and we won't 
                  * register a channel with it because
@@ -407,16 +401,22 @@ Rivet_ServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server
 		apr_pool_userdata_set((const void *)1, userdata_key,
                               apr_pool_cleanup_null, server->process->pool);
 
-        ap_log_error(APLOG_MARK,APLOG_INFO,0,server,
+        ap_log_error(APLOG_MARK,APLOG_DEBUG,0,server,
                      "first post_config run: not initializing Tcl stuff");
 
         return OK; /* This would be the first time through */
-	}	
+	}
 	
-    /* Everything revolves around this structure: module_globals. The structure 
-     * is allocated and the MPM bridge name is established */
+    /* Everything revolves around this structure: module_globals */
+
+    /* the module global structure is allocated and the MPM bridge name established */
 
-    module_globals = Rivet_CreateModuleGlobals (pPool,server);
+    // module_globals = Rivet_CreateModuleGlobals (pPool,server);
+
+    /* We can proceed initializing the globals with information stored in the module configuration */
+
+    module_globals->rivet_mpm_bridge = Rivet_SeekMPMBridge(pPool);
+    module_globals->server           = server;
 
     /* The bridge is loaded and the jump table sought */
 
@@ -425,7 +425,7 @@ Rivet_ServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server
         apr_status_t            rv;
         apr_dso_handle_sym_t    func = NULL;
 
-        ap_log_error(APLOG_MARK,APLOG_DEBUG,0,server,
+        ap_log_perror(APLOG_MARK,APLOG_DEBUG,APR_EGENERAL,pTemp,
                      "MPM bridge loaded: %s",module_globals->rivet_mpm_bridge);
 
         rv = apr_dso_sym(&func,dso_handle,"bridge_jump_table");
@@ -448,7 +448,7 @@ Rivet_ServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server
         ap_assert(RIVET_MPM_BRIDGE_FUNCTION(request_processor) != NULL);
         ap_assert(RIVET_MPM_BRIDGE_FUNCTION(thread_interp) != NULL);
 
-        //apr_thread_mutex_create(&module_globals->pool_mutex, APR_THREAD_MUTEX_UNNESTED, pPool);
+        apr_thread_mutex_create(&module_globals->pool_mutex, APR_THREAD_MUTEX_UNNESTED, pPool);
 
     }
     else
@@ -488,8 +488,12 @@ static void Rivet_ChildInit (apr_pool_t *pChild, server_rec *server)
     rivet_server_conf*  root_server_conf;
     server_rec*         s;
 
-    /* This code is run once per child process. In a threaded Tcl builds the forking 
-     * of a child process most likely has not preserved the thread where the Tcl 
+    /* the thread key used to access to Tcl threads private data */
+
+    ap_assert (apr_threadkey_private_create (&rivet_thread_key, NULL, pChild) == APR_SUCCESS);
+
+    /* This code is run once per child process. The forking 
+     * of a child process doesn't preserve the thread where the Tcl 
      * notifier runs. The Notifier should have been restarted by one the 
      * pthread_atfork callbacks (setup in Tcl >= 8.5.14 and Tcl >= 8.6.1). In
      * case pthread_atfork is not supported we unconditionally call Tcl_InitNotifier
@@ -500,13 +504,24 @@ static void Rivet_ChildInit (apr_pool_t *pChild, server_rec *server)
     Tcl_InitNotifier();
 #endif
 
-    /* for any non-prefork bridge the module globals are to be created here */
+    /* We can rely on the existence of module_globals only we are
+     * running the prefork MPM, otherwise the pointer is NULL and
+     * the structure need to be filled
+     */
 
     if (module_globals == NULL)
     {
-        module_globals = Rivet_CreateModuleGlobals(pChild,server);
+        module_globals = Rivet_CreateModuleGlobals(pChild);
+        module_globals->rivet_mpm_bridge = Rivet_SeekMPMBridge(pChild);
+        module_globals->server = server;
     }
 
+    /* This mutex should protect the process wide pool from concurrent access by 
+     * different threads
+     */
+
+    apr_thread_mutex_create(&module_globals->pool_mutex, APR_THREAD_MUTEX_UNNESTED, pChild);
+
     /* Once we have established a pool with the same lifetime of the child process we
      * process all the configured server records assigning an integer as unique key 
      * to each of them 
@@ -524,11 +539,10 @@ static void Rivet_ChildInit (apr_pool_t *pChild, server_rec *server)
          * was called. We really need a separate one for each server,
          * so we go ahead and create one here, if necessary. */
 
-        if (s != server && myrsc == root_server_conf) 
-        {
+        if (s != server && myrsc == root_server_conf) {
             myrsc = RIVET_NEW_CONF(pChild);
             ap_set_module_config(s->module_config, &rivet_module, myrsc);
-            Rivet_CopyConfig(root_server_conf,myrsc);
+            Rivet_CopyConfig( root_server_conf, myrsc );
         }
 
         myrsc->idx = idx++;
@@ -553,6 +567,14 @@ static int Rivet_Handler (request_rec *r)
     return (*RIVET_MPM_BRIDGE_FUNCTION(request_processor))(r,ctype);
 }
 
+static int Rivet_InitGlobals (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp)
+{
+    /* the module global structure is allocated and the MPM bridge name established */
+
+    module_globals = Rivet_CreateModuleGlobals (pPool);
+    return OK;
+}
+
 /*
  * -- rivet_register_hooks: mod_rivet basic setup.
  *
@@ -561,6 +583,7 @@ static int Rivet_Handler (request_rec *r)
 
 static void rivet_register_hooks(apr_pool_t *p)
 {
+    ap_hook_pre_config  (Rivet_InitGlobals,NULL, NULL, APR_HOOK_LAST);
     ap_hook_post_config (Rivet_ServerInit, NULL, NULL, APR_HOOK_LAST);
     ap_hook_handler     (Rivet_Handler,    NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_child_init  (Rivet_ChildInit,  NULL, NULL, APR_HOOK_LAST);
diff --git a/src/mod_rivet_ng/mod_rivet.h b/src/mod_rivet_ng/mod_rivet.h
index 04de062..2dbcf2a 100644
--- a/src/mod_rivet_ng/mod_rivet.h
+++ b/src/mod_rivet_ng/mod_rivet.h
@@ -35,17 +35,15 @@
 #include <rivet_config.h>
 #endif
 
-#include "rivet_types.h"
-
 /*
  * 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 */
 
@@ -116,36 +114,29 @@ typedef struct _rivet_server_conf {
     char*       rivet_before_script;        /* script run before each page      */
     char*       rivet_after_script;         /*            after                 */
 
-    /* ------------------------------------------------------------------------ */
+    /* --------------------------------------------------------------------------- */
 
     /* This flag is used with the above directives. If any of them have changed, it gets set. */
 
-    unsigned int    user_scripts_status;
-
-    int             default_cache_size;
-    int             upload_max;
-    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
-                                               exported ::rivet commands                    */
-    char*           server_name;
-    const char*     upload_dir;
-    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 */
-    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 *
-                                         * be composed using the pattern 'rivet_(mpm_bridge)_mpm.so     */
+    unsigned int user_scripts_status;
+
+    int          default_cache_size;
+    int          upload_max;
+    int          upload_files_to_var;
+    int          honor_header_only_reqs;
+
+    int          export_rivet_ns;        /* export the ::rivet namespace commands        */
+    int          import_rivet_ns;        /* import into the global namespace the
+                                            exported ::rivet commands                    */
+    char*        server_name;
+    const char*  upload_dir;
+    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                                      */
 } rivet_server_conf;
 
 #define TCL_INTERPS 1
@@ -204,20 +195,32 @@ typedef struct _mpm_bridge_table {
 typedef struct mpm_bridge_status mpm_bridge_status;
 
 typedef struct _mod_rivet_globals {
-    apr_pool_t*             pool;               
-    char*                   rivet_mpm_bridge;       /* name of the MPM bridge                   */
-    server_rec*             server;                 /* default host server_rec obj              */
-    int                     ap_child_shutdown;      /* shutdown inited by the child pool cleanup */
-    int                     vhosts_count;           /* Number of configured virtual host including 
-                                                     * the root server thus it's supposed to be >= 1 */
-	char*				    default_handler;		/* Default request handler code             */
-	int					    default_handler_size;	/* Size of the default_handler buffer       */
-    rivet_thread_interp**   server_interps;         /* server and prefork MPM interpreter       */
-    /* apr_thread_mutex_t*   pool_mutex;  */        /* threads commmon pool mutex               */
-    rivet_bridge_table*     bridge_jump_table;      /* Jump table to bridge specific procedures */
-    mpm_bridge_status*      mpm;                    /* bridge private control structure         */
+    apr_pool_t*         pool;               
+    char*               rivet_mpm_bridge;       /* name of the MPM bridge                   */
+    server_rec*         server;                 /* default host server_rec obj              */
+    int                 ap_child_shutdown;      /* shutdown inited by the child pool cleanup */
+    int                 vhosts_count;           /* Number of configured virtual host including   *
+                                                 * the root server thus it's supposed to be >= 1 */
+    char*               default_handler;		/* Default request handler code             */
+    int                 default_handler_size;	/* Size of the default_handler buffer       */
+    rivet_thread_interp** server_interps;       /* server and prefork MPM interpreter       */
+    apr_thread_mutex_t* pool_mutex;             /* threads commmon pool mutex               */
+    rivet_bridge_table* bridge_jump_table;      /* Jump table to bridge specific procedures */
+    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 be composed using */
+                                                /* the pattern 'rivet_(mpm_bridge)_mpm.so   */
+    mpm_bridge_status*  mpm;                    /* bridge private control structure         */
+    int                 single_thread_exit;     /* With a threaded bridge allow a single    */
+                                                /* thread to exit instead of forcing the    */
+                                                /* whole process to terminate               */
+    int                 separate_virtual_interps; 
+                                                /* Virtual host have their own interpreter  */
+    int                 separate_channels;      /* when true a vhosts get their private channel */
 #ifdef RIVET_SERIALIZE_HTTP_REQUESTS
-    apr_thread_mutex_t*     req_mutex;
+    apr_thread_mutex_t* req_mutex;
 #endif
 } mod_rivet_globals;
 
@@ -248,12 +251,25 @@ 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);
 
+/*
+ * Petasis, 04/08/2017: I think the following is wrong, as both "functions" are
+ * defined through preprocessor definitions in http_config.h. At least under
+ * windows, they do not exist as functions in libhttpd.lib.
+ *
+#ifdef ap_get_module_config
+#undef ap_get_module_config
+#endif
+#ifdef ap_set_module_config
+#undef ap_set_module_config
+#endif
+*/
+
 #define RIVET_SERVER_CONF(module) (rivet_server_conf *)ap_get_module_config(module, &rivet_module)
 #define RIVET_NEW_CONF(p)         (rivet_server_conf *)apr_pcalloc(p, sizeof(rivet_server_conf))
 
@@ -281,6 +297,12 @@ Tcl_Obj* Rivet_CurrentServerRec (Tcl_Interp* interp, server_rec* s);
 #define ABORTPAGE_CODE              "ABORTPAGE"
 #define THREAD_EXIT_CODE            "THREAD_EXIT"
 
+/* Configuration defaults */
+
+#define SINGLE_THREAD_EXIT_UNDEF   -1    /* pre config undefined value for single 
+                                            thread exit flag in the module globals
+                                            structure */
+
 #define TCL_MAX_CHANNEL_BUFFER_SIZE (1024*1024)
 #define MODNAME                     "mod_rivet"
 
diff --git a/src/mod_rivet_ng/mod_rivet_cache.c b/src/mod_rivet_ng/mod_rivet_cache.c
index 192378f..151c8ce 100644
--- a/src/mod_rivet_ng/mod_rivet_cache.c
+++ b/src/mod_rivet_ng/mod_rivet_cache.c
@@ -18,9 +18,8 @@
     under the License.
 */
 
-/* $Id: */
-
 #include <apr_strings.h>
+#include <mpm_common.h>
 
 #include "mod_rivet.h"
 
@@ -34,6 +33,23 @@
 
 extern mod_rivet_globals* module_globals;
 
+
+/*
+ * -- RivetCache_DefaultSize
+ *
+ * Basic determination of a default size for the Rivet cache
+ *
+ */
+
+int RivetCache_DefaultSize (void)
+{
+    if (ap_max_requests_per_child != 0) {
+        return  (ap_max_requests_per_child / 5);
+    } else {
+        return 50;
+    }
+}
+
 /*
  * -- RivetCache_Create 
  *
@@ -127,11 +143,23 @@ void RivetCache_Cleanup (rivet_thread_private* private,rivet_thread_interp* rive
 
         ct++;
     }
-    apr_pool_clear(rivet_interp->pool);
+    apr_pool_destroy(rivet_interp->pool);
     
-    rivet_interp->objCacheList = apr_pcalloc (rivet_interp->pool,(signed)(rivet_interp->cache_size*sizeof(char *)));
-    rivet_interp->cache_free = rivet_interp->cache_size;
+    /* let's recreate the cache list */
 
+    if (apr_pool_create(&rivet_interp->pool, private->pool) != APR_SUCCESS)
+    {
+        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, module_globals->server, 
+                     MODNAME ": could not recreate cache private pool. Cache disabled");
+        rivet_interp->cache_free = rivet_interp->cache_size = 0;
+    }
+    else
+    {
+        rivet_interp->objCacheList = apr_pcalloc (rivet_interp->pool, 
+                                                (signed)(rivet_interp->cache_size*sizeof(char *)));
+        rivet_interp->cache_free = rivet_interp->cache_size;
+    }
+    
 }
 
 /* 
@@ -160,27 +188,49 @@ char* RivetCache_MakeKey (apr_pool_t*   pool,
 /*
  * -- RivetCache_EntryLookup
  *
- * Cache entry lookiup. A hash table lookup key is created and an entry
+ * Cache entry lookup. A hash table lookup key is created and an entry
  * searched in the cache. If an entry is not found the function returns NULL
  *
  * Arguments:
- *      char*                hashKey    - key to the cache
- *      rivet_thread_interp* interp_obj - interpreter object
+ *      rivet_thread_interp* rivet_interp - interpreter object
+ *      char*                hashKey      - key to the cache entry
  *
  * Results:
- *      Tcl_HashEntry*       entry object
+ *      Tcl_HashEntry*       entry object - NULL if the entry for hashKey is not
+ *                                          existing
  *
  * Side Effects:
  *
  */
 
-Tcl_HashEntry* RivetCache_EntryLookup (rivet_thread_interp* rivet_interp,char* hashKey,int* isNew)
+Tcl_HashEntry* RivetCache_EntryLookup (rivet_thread_interp* rivet_interp,char* hashKey)
 {
-    Tcl_HashEntry*  entry = NULL;
+    return Tcl_FindHashEntry(rivet_interp->objCache, hashKey);
+}
 
-    entry = Tcl_CreateHashEntry(rivet_interp->objCache, hashKey, isNew);
-    return entry;
+/*
+ * -- RivetCache_CreateEntry
+ *
+ * Cache entry lookup. A hash table lookup key is created and an entry
+ * searched in the cache. If an entry is not found the function returns NULL
+ *
+ * Arguments:
+ *      rivet_thread_interp* rivet_interp - interpreter object
+ *      char*                hashKey      - key to the cache entry
+ *      int*                 isNew        - pointer to an integer. If the
+ *                                          entry create didn't exists isNew
+ *                                          is set to 1
+ *
+ * Results:
+ *      Tcl_HashEntry*       entry object
+ *
+ * Side Effects:
+ *
+ */
 
+Tcl_HashEntry* RivetCache_CreateEntry (rivet_thread_interp* rivet_interp,char* hashKey,int* isNew)
+{
+    return Tcl_CreateHashEntry(rivet_interp->objCache, hashKey, isNew);
 }
 
 /*
diff --git a/src/mod_rivet_ng/mod_rivet_cache.h b/src/mod_rivet_ng/mod_rivet_cache.h
index d30283a..8f86f6e 100644
--- a/src/mod_rivet_ng/mod_rivet_cache.h
+++ b/src/mod_rivet_ng/mod_rivet_cache.h
@@ -21,17 +21,19 @@
 #ifndef __mod_rivet_cache_h__
 #define __mod_rivet_cache_h__
 
+EXTERN int   RivetCache_DefaultSize (void);
 EXTERN void  RivetCache_Create  (rivet_thread_interp* interp_obj);
-EXTERN void  RivetCache_Destroy (rivet_thread_private* private,rivet_thread_interp* rivet_interp);
 EXTERN void  RivetCache_Cleanup (rivet_thread_private* private,rivet_thread_interp* rivet_interp);
 EXTERN char* RivetCache_MakeKey (apr_pool_t* pool, char*         filename,
                                                    time_t        ctime, 
                                                    time_t        mtime,
                                                    unsigned int  user_conf,
                                                    int           toplevel);
-EXTERN Tcl_HashEntry* RivetCache_EntryLookup (rivet_thread_interp* rivet_interp,char* hashKey,int* isNew);
+EXTERN Tcl_HashEntry* RivetCache_EntryLookup (rivet_thread_interp* rivet_interp,char* hashKey);
+EXTERN Tcl_HashEntry* RivetCache_CreateEntry (rivet_thread_interp* rivet_interp,char* hashKey,int* isNew);
 EXTERN Tcl_Obj* RivetCache_FetchScript (Tcl_HashEntry* entry);
 EXTERN int RivetCache_StoreScript(rivet_thread_interp* rivet_interp, Tcl_HashEntry* entry, Tcl_Obj* script);
 EXTERN void RivetCache_DeleteEntry (Tcl_HashEntry *entry);
+EXTERN void RivetCache_Destroy (rivet_thread_private* private,rivet_thread_interp* rivet_interp);
 
 #endif /* __mod_rivet_cache_h__ */
diff --git a/src/mod_rivet_ng/mod_rivet_common.c b/src/mod_rivet_ng/mod_rivet_common.c
index 59d3ff4..6bf2de2 100644
--- a/src/mod_rivet_ng/mod_rivet_common.c
+++ b/src/mod_rivet_ng/mod_rivet_common.c
@@ -24,10 +24,9 @@
 #include <httpd.h>
 #include <apr_strings.h>
 #include <apr_env.h>
-#include <ap_mpm.h>
 #include <apr_file_io.h>
 #include <apr_file_info.h>
-#include <mpm_common.h>
+#include <ap_mpm.h>
 
 #include "mod_rivet.h"
 #include "rivetChannel.h"
@@ -36,7 +35,6 @@
 #include "rivet.h"
 #include "apache_config.h"
 
-
 /* as long as we need to emulate ap_chdir_file we need to include unistd.h */
 #ifdef RIVET_HAVE_UNISTD_H
 #include <unistd.h>
@@ -130,8 +128,7 @@ Rivet_ReadFile (apr_pool_t* pool,char* filename,char** buffer,int* nbytes)
     return 0;
 }
 
-/*
- *-----------------------------------------------------------------------------
+/*-----------------------------------------------------------------------------
  * Rivet_CreateTclInterp --
  *
  * Arguments:
@@ -146,7 +143,7 @@ Rivet_ReadFile (apr_pool_t* pool,char* filename,char** buffer,int* nbytes)
  */
 
 static Tcl_Interp* 
-Rivet_CreateTclInterp (server_rec* s)
+Rivet_CreateTclInterp (apr_pool_t* pool)
 {
     Tcl_Interp* interp;
 
@@ -156,14 +153,14 @@ Rivet_CreateTclInterp (server_rec* s)
 
     if (interp == NULL)
     {
-        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+        ap_log_perror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, pool,
                      MODNAME ": Error in Tcl_CreateInterp, aborting\n");
         exit(1);
     }
 
     if (Tcl_Init(interp) == TCL_ERROR)
     {
-        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+        ap_log_perror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, pool,
                      MODNAME ": Error in Tcl_Init: %s, aborting\n",
                      Tcl_GetStringResult(interp));
         exit(1);
@@ -194,20 +191,14 @@ running_scripts* Rivet_RunningScripts ( apr_pool_t* pool,
     {
 		char* request_handler;
 		int	  handler_size;
-
-		//ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, module_globals->server, 
-        //             MODNAME ": reading request handler %s",rivet_conf->request_handler);
-
+			
 		ap_assert(Rivet_ReadFile(pool,rivet_conf->request_handler,
 		                        &request_handler,&handler_size) == 0);
 
-        scripts->request_processing = Tcl_NewStringObj(request_handler,handler_size);
+        scripts->request_processing = 
+				 Tcl_NewStringObj(request_handler,handler_size);
 
     } else {
-
-		//ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, module_globals->server, 
-        //             MODNAME ": reading default request handler %s",module_globals->default_handler);
-
         scripts->request_processing = 
 				 Tcl_NewStringObj(module_globals->default_handler,
                                   module_globals->default_handler_size);
@@ -232,6 +223,27 @@ void Rivet_ReleaseRunningScripts (running_scripts* scripts)
     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);
+}
+
 
 /*
  *---------------------------------------------------------------------
@@ -355,53 +367,39 @@ void Rivet_PerInterpInit(rivet_thread_interp* interp_obj,
   *
   */
 
-rivet_thread_interp* Rivet_NewVHostInterp(rivet_thread_private* private,server_rec* server)
+rivet_thread_interp* Rivet_NewVHostInterp (rivet_thread_private* private,int default_cache_size)
 {
     rivet_thread_interp*    interp_obj = apr_pcalloc(private->pool,sizeof(rivet_thread_interp));
-    rivet_server_conf*      rsc;
-
-    /* The cache size is global so we take it from here */
-    
-    rsc = RIVET_SERVER_CONF (server->module_config);
+    apr_status_t            apr_sts;
 
     /* This calls needs the root server_rec just for logging purposes */
 
-    interp_obj->interp = Rivet_CreateTclInterp(server); 
-    
-    /* We establish the cache size */
-
-    if (rsc->default_cache_size < 0) {
-        if (ap_max_requests_per_child != 0) {
-            interp_obj->cache_size = ap_max_requests_per_child / 5;
-        } else {
-            interp_obj->cache_size = 50;    // Arbitrary number
-        }
-    } else if (rsc->default_cache_size > 0) {
-        interp_obj->cache_size = rsc->default_cache_size;
-    }
-
-    if (interp_obj->cache_size > 0) {
-        interp_obj->cache_free = interp_obj->cache_size;
-    }
+    interp_obj->interp = Rivet_CreateTclInterp(private->pool); 
 
-    /* we now create memory for the cache as subpool of the thread private pool */
- 
-    if (apr_pool_create(&interp_obj->pool, private->pool) != APR_SUCCESS)
+    /* we now create memory from the cache pool as subpool of the thread private pool */
+    
+    apr_sts = apr_pool_create(&interp_obj->pool, private->pool);
+    if (apr_sts != APR_SUCCESS)
     {
-        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server, 
+        ap_log_perror(APLOG_MARK, APLOG_ERR, apr_sts, private->pool, 
                      MODNAME ": could not initialize cache private pool");
         return NULL;
     }
 
-    ap_assert(interp_obj->pool != private->pool);
+    if (default_cache_size < 0) {
+        interp_obj->cache_size = RivetCache_DefaultSize();
+    } else if (default_cache_size > 0) {
+        interp_obj->cache_size = default_cache_size;
+    }
+
+    interp_obj->cache_free = interp_obj->cache_size;
 
-    /* Initialize cache structures */
+    // Initialize cache structures
 
     if (interp_obj->cache_size) {
         RivetCache_Create(interp_obj); 
     }
 
-    interp_obj->channel         = NULL;
     interp_obj->flags           = 0;
     interp_obj->scripts         = (running_scripts *) apr_pcalloc(private->pool,sizeof(running_scripts));
     interp_obj->per_dir_scripts = apr_hash_make(private->pool); 
@@ -415,11 +413,11 @@ rivet_thread_interp* Rivet_NewVHostInterp(rivet_thread_private* private,server_r
  *
  * -- Rivet_CreateRivetChannel
  *
- * Creates a channel 
+ * Creates a channel and registers with to the interpreter
  *
  *  Arguments:
  *
- *     - apr_pool_t* pPool: a pointer to an APR memory pool
+ *     - apr_pool_t*        pPool: a pointer to an APR memory pool
  *
  *  Returned value:
  *
@@ -449,13 +447,11 @@ Rivet_CreateRivetChannel(apr_pool_t* pPool, apr_threadkey_t* rivet_thread_key)
      * programmer does a "flush stdout" or the page is completed.
      */
 
-    Tcl_SetChannelBufferSize (*outchannel,TCL_MAX_CHANNEL_BUFFER_SIZE);
+    Tcl_SetChannelBufferSize (*outchannel, TCL_MAX_CHANNEL_BUFFER_SIZE);
 
     return outchannel;
 }
 
-
-
 /*-----------------------------------------------------------------------------
  *
  * -- Rivet_ReleaseRivetChannel
diff --git a/src/mod_rivet_ng/mod_rivet_common.h b/src/mod_rivet_ng/mod_rivet_common.h
index 27a6d68..dc698bb 100644
--- a/src/mod_rivet_ng/mod_rivet_common.h
+++ b/src/mod_rivet_ng/mod_rivet_common.h
@@ -28,14 +28,14 @@ EXTERN void                 Rivet_PerInterpInit (rivet_thread_interp* interp_obj
                                                 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 (rivet_thread_private* private,server_rec* s);
+EXTERN rivet_thread_interp* Rivet_NewVHostInterp (rivet_thread_private* private,int default_cache_size);
 EXTERN int                  Rivet_chdir_file (const char *file);
 EXTERN void                 Rivet_CleanupRequest (request_rec *r);
 EXTERN void                 Rivet_InitServerVariables (Tcl_Interp *interp, apr_pool_t *pool);
 EXTERN void                 Rivet_Panic TCL_VARARGS_DEF (CONST char *, arg1);
 EXTERN Tcl_Channel*         Rivet_CreateRivetChannel (apr_pool_t* pPool, apr_threadkey_t* rivet_thread_key);
 EXTERN rivet_thread_private* Rivet_CreatePrivateData (apr_pool_t* pool, bool create_request_obj);
-//EXTERN rivet_thread_private* Rivet_ExecutionThreadInit (void);
+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);
diff --git a/src/mod_rivet_ng/rivetCore.c b/src/mod_rivet_ng/rivetCore.c
index 5dc9a1b..3c115b1 100644
--- a/src/mod_rivet_ng/rivetCore.c
+++ b/src/mod_rivet_ng/rivetCore.c
@@ -202,7 +202,7 @@ TCL_CMD_HEADER( Rivet_MakeURL )
 TCL_CMD_HEADER( Rivet_Parse )
 {
     rivet_thread_private*   private;
-    char*                   filename;
+    char*                   filename = 0;
     apr_status_t            stat_s;
     apr_finfo_t             finfo_b;
     char*                   cache_key;
@@ -210,7 +210,6 @@ TCL_CMD_HEADER( Rivet_Parse )
     Tcl_HashEntry*          entry  = NULL;
     Tcl_Obj*                script = NULL;
     int                     result;
-    int                     isNew;
 
     THREAD_PRIVATE_DATA(private)
     CHECK_REQUEST_REC(private,"::rivet::parse")
@@ -242,12 +241,12 @@ TCL_CMD_HEADER( Rivet_Parse )
             /* we parse and compose the script ourselves before passing it to Tcl_EvalObjEx */
 
             Tcl_IncrRefCount(outbuf);
-            Tcl_AppendToObj(outbuf,"puts -nonewline \"", -1);
+            Tcl_AppendToObj(outbuf, "puts -nonewline \"", -1);
 
             /* If we are not inside a <? ?> section, add the closing ". */
             if (Rivet_Parser(outbuf, script) == 0)
             {
-                Tcl_AppendToObj(outbuf,"\"\n", 2);
+                Tcl_AppendToObj(outbuf, "\"\n", 2);
             } 
 
             Tcl_AppendToObj(outbuf,"\n",-1);
@@ -285,14 +284,14 @@ TCL_CMD_HEADER( Rivet_Parse )
     /* */
 
     cache_key = 
-        RivetCache_MakeKey (private->pool,filename,
+        RivetCache_MakeKey( private->pool,filename,
                             finfo_b.ctime,finfo_b.mtime,
                             IS_USER_CONF(private->running_conf),0);
 
     rivet_interp = RIVET_PEEK_INTERP(private,private->running_conf);
-    entry = RivetCache_EntryLookup (rivet_interp,cache_key,&isNew);
+    entry = RivetCache_EntryLookup (rivet_interp,cache_key);
 
-    if (isNew)
+    if (entry == NULL)
     {
         script = Tcl_NewObj();
         Tcl_IncrRefCount(script);
@@ -301,16 +300,37 @@ TCL_CMD_HEADER( Rivet_Parse )
         if (result != TCL_OK)
         {
             Tcl_AddErrorInfo(interp,apr_pstrcat(private->pool,"Could not read file ",filename,NULL));
+            Tcl_DecrRefCount(script);
             return result;
         }
-        
-        RivetCache_StoreScript(rivet_interp,entry,script);
+
+        if (rivet_interp->cache_free > 0)
+        {
+            int isNew;
+            Tcl_HashEntry* entry;
+
+            entry = RivetCache_CreateEntry (rivet_interp,cache_key,&isNew);
+            ap_assert(isNew == 1);
+            RivetCache_StoreScript(rivet_interp,entry,script);
+        }
+        else if ((rivet_interp->flags & RIVET_CACHE_FULL) == 0)
+        {
+            rivet_interp->flags |= RIVET_CACHE_FULL;
+            ap_log_error (APLOG_MARK, APLOG_NOTICE, APR_EGENERAL, private->r->server,"%s %s (%s),",
+                                                                  "Rivet cache full when parsing ",
+                                                                  private->r->filename,
+                                                                  private->r->server->server_hostname);
+        }
+
+        result = Tcl_EvalObjEx(interp,script,0);
         Tcl_DecrRefCount(script);
+        return result;
+               
     } else {
         script = RivetCache_FetchScript(entry);
+        return Tcl_EvalObjEx(interp,script,0); 
     }
 
-    return Tcl_EvalObjEx(interp,script,0); 
 }
 
 /*
@@ -1017,6 +1037,7 @@ TCL_CMD_HEADER( Rivet_ApacheTable )
     return TCL_OK;
 }
 
+
 /*
  *-----------------------------------------------------------------------------
  *
@@ -1425,7 +1446,7 @@ TCL_CMD_HEADER( Rivet_EnvCmd )
  *
  *      - non threaded MPMs: the child process exits for good
  *      - threaded MPMs: the child process exits after all Tcl threads
- *        are told to exit
+ *      are told to exit
  *
  *-----------------------------------------------------------------------------
  */
@@ -1433,7 +1454,7 @@ TCL_CMD_HEADER( Rivet_EnvCmd )
 TCL_CMD_HEADER( Rivet_ExitCmd )
 {
     int value;
-    rivet_thread_private* private;
+    rivet_thread_private*   private;
     char* errorMessage = "page generation interrupted by exit command";
 
     if ((objc != 1) && (objc != 2)) {
@@ -1859,7 +1880,6 @@ TCL_CMD_HEADER( Rivet_UrlScript )
     unsigned int         user_conf; 
     time_t               ctime;
     time_t               mtime;
-    int                  isNew;
 
     THREAD_PRIVATE_DATA(private)
     CHECK_REQUEST_REC(private,"::rivet::url_script")
@@ -1871,8 +1891,8 @@ TCL_CMD_HEADER( Rivet_UrlScript )
     mtime = private->r->finfo.mtime;
     cache_key = RivetCache_MakeKey(private->pool,private->r->filename,ctime,mtime,user_conf,1);
 
-    entry = RivetCache_EntryLookup (rivet_interp,cache_key,&isNew);
-    if (isNew)
+    entry = RivetCache_EntryLookup (rivet_interp,cache_key);
+    if (entry == NULL)
     {
         Tcl_Interp*     interp;
         
@@ -1880,7 +1900,6 @@ TCL_CMD_HEADER( Rivet_UrlScript )
 
         script = Tcl_NewObj();
         Tcl_IncrRefCount(script);
-
         /*
          * We check whether we are dealing with a pure Tcl script or a Rivet template.
          * Actually this check is done only if we are processing a toplevel file, every nested
@@ -1898,23 +1917,41 @@ TCL_CMD_HEADER( Rivet_UrlScript )
 
         }
 
-        if (result != TCL_OK)
+        if (result == TCL_OK)
         {
-            // Hash cleanup
-            RivetCache_DeleteEntry(entry);
+            /* let's check the cache for free entries */
 
-            Tcl_DecrRefCount(script);
-            return result;
+            if (rivet_interp->cache_free > 0)
+            {
+                int isNew;
+                Tcl_HashEntry* entry;
+
+                entry = RivetCache_CreateEntry (rivet_interp,cache_key,&isNew);
+    
+                /* Sanity check: we are here for this reason */
+
+                ap_assert(isNew == 1);
+            
+                /* we proceed storing the script in the cache */
+
+                RivetCache_StoreScript(rivet_interp,entry,script);
+            }
+            else if ((rivet_interp->flags & RIVET_CACHE_FULL) == 0)
+            {
+                rivet_interp->flags |= RIVET_CACHE_FULL;
+                ap_log_error (APLOG_MARK, APLOG_NOTICE, APR_EGENERAL,private->r->server,"%s %s (%s),",
+                                                                      "Rivet cache full when serving ",
+                                                                      private->r->filename,
+                                                                      private->r->server->server_hostname);
+            }
         }
+        Tcl_SetObjResult(rivet_interp->interp, script);
+        Tcl_DecrRefCount(script);
 
-        RivetCache_StoreScript(rivet_interp,entry,script);
-    }
-    else
-    {
-        script = RivetCache_FetchScript(entry);
+    } else {
+        Tcl_SetObjResult(rivet_interp->interp,RivetCache_FetchScript(entry));
     }
 
-    Tcl_SetObjResult(rivet_interp->interp, script);
     return TCL_OK;
 }
 
@@ -1997,6 +2034,64 @@ TCL_CMD_HEADER( Rivet_GetThreadId )
     Tcl_SetObjResult(interp,Tcl_NewStringObj(buff,strlen(buff)));
     return TCL_OK;
 }
+
+#ifdef RIVET_DEBUG_BUILD
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Rivet_CacheContent --
+ *
+ *      Dumping in a list the cache content. For debugging purposes.
+ *      This command will be placed within conditional compilation and
+ *      documented within the 'Rivet Internals' section of the manual
+ *
+ * Results:
+ *      
+ *      a Tcl list of the keys in the interpreter cache
+ *
+ * Side Effects:
+ *
+ *      none
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+TCL_CMD_HEADER( Rivet_CacheContent )
+{
+    Tcl_Obj*                entry_list;
+    rivet_thread_private*   private;
+    rivet_thread_interp*    rivet_interp;
+    int                     ep;
+    THREAD_PRIVATE_DATA(private)
+    CHECK_REQUEST_REC(private,"::rivet::cache_content")
+
+    rivet_interp = RIVET_PEEK_INTERP(private,private->running_conf);
+    interp = rivet_interp->interp;
+    
+    entry_list = Tcl_NewObj();
+    Tcl_IncrRefCount(entry_list);
+
+    ep = rivet_interp->cache_size - 1;
+    
+    while ((ep >= 0) && (rivet_interp->objCacheList[ep]))
+    {
+        int tcl_status;
+
+        tcl_status = Tcl_ListObjAppendElement(interp,entry_list,Tcl_NewStringObj(rivet_interp->objCacheList[ep],-1));
+
+        if (tcl_status != TCL_OK) {
+            return tcl_status;
+        }
+
+        ep--;
+    }
+    Tcl_SetObjResult(interp,entry_list);
+    Tcl_DecrRefCount(entry_list);
+    return TCL_OK;
+}
+
+#endif /* RIVET_DEBUG_BUILD */
+
 /*
  *-----------------------------------------------------------------------------
  *
@@ -2041,7 +2136,11 @@ Rivet_InitCore(rivet_thread_interp* interp_obj,rivet_thread_private* private)
     RIVET_OBJ_CMD ("exit",Rivet_ExitCmd,private);
     RIVET_OBJ_CMD ("url_script",Rivet_UrlScript,private);
     RIVET_OBJ_CMD ("thread_id",Rivet_GetThreadId,private);
-
+    
+#ifdef RIVET_DEBUG_BUILD
+    /* code compiled conditionally for debugging */
+    RIVET_OBJ_CMD ("cache_content",Rivet_CacheContent,private);
+#endif
 #ifdef TESTPANIC
     RIVET_OBJ_CMD ("testpanic",TestpanicCmd,private);
 #endif
diff --git a/src/mod_rivet_ng/rivetInspect.c b/src/mod_rivet_ng/rivetInspect.c
index 7a4c231..92d454c 100644
--- a/src/mod_rivet_ng/rivetInspect.c
+++ b/src/mod_rivet_ng/rivetInspect.c
@@ -21,8 +21,6 @@
    limitations under the License.
 */
 
-/* $Id: */
-
 #include <tcl.h>
 #include <string.h>
 #include <apr_errno.h>
@@ -86,10 +84,11 @@ enum confIndices {
                     request_handler,
                     export_rivet_ns,
                     import_rivet_ns,
-                    single_thread_exit,
                     conf_index_terminator 
 };
 
+extern mod_rivet_globals* module_globals;
+
 /* 
  * -- Rivet_ReadConfParameter
  *
@@ -141,15 +140,14 @@ Rivet_ReadConfParameter ( Tcl_Interp*        interp,
         case abort_script:              string_value = rsc->rivet_abort_script; break;
         case error_script:              string_value = rsc->rivet_error_script; break;
         case upload_directory:          string_value = (char *)rsc->upload_dir; break;
-        case mpm_bridge:                string_value = (char *)rsc->mpm_bridge; break;
+        case mpm_bridge:                string_value = (char *)module_globals->mpm_bridge; break;
         case upload_max:                int_value = Tcl_NewIntObj(rsc->upload_max); break;
         case upload_files_to_var:       int_value = Tcl_NewIntObj(rsc->upload_files_to_var); break;
-        case separate_virtual_interps:  int_value = Tcl_NewIntObj(rsc->separate_virtual_interps); break;
-        case separate_channels:         int_value = Tcl_NewIntObj(rsc->separate_channels); break;
+        case separate_virtual_interps:  int_value = Tcl_NewIntObj(module_globals->separate_virtual_interps); break;
+        case separate_channels:         int_value = Tcl_NewIntObj(module_globals->separate_channels); break;
         case honor_header_only_requests: int_value = Tcl_NewIntObj(rsc->honor_header_only_reqs); break;
         case export_rivet_ns:           int_value = Tcl_NewIntObj(rsc->export_rivet_ns); break;
         case import_rivet_ns:           int_value = Tcl_NewIntObj(rsc->import_rivet_ns); break;
-        case single_thread_exit:        int_value = Tcl_NewIntObj(rsc->single_thread_exit); break;
         default: return NULL;
     }
 
diff --git a/src/mod_rivet_ng/rivet_lazy_mpm.c b/src/mod_rivet_ng/rivet_lazy_mpm.c
index e889880..5145c45 100644
--- a/src/mod_rivet_ng/rivet_lazy_mpm.c
+++ b/src/mod_rivet_ng/rivet_lazy_mpm.c
@@ -34,9 +34,9 @@
 #include "rivetChannel.h"
 #include "apache_config.h"
 
-DLLIMPORT mod_rivet_globals* module_globals;
-DLLIMPORT apr_threadkey_t*   rivet_thread_key;
-module rivet_module;
+extern DLLIMPORT mod_rivet_globals*   module_globals;
+extern DLLIMPORT apr_threadkey_t*     rivet_thread_key;
+extern DLLIMPORT module rivet_module;
 
 enum
 {
@@ -58,7 +58,7 @@ typedef struct lazy_tcl_worker {
     request_rec*        r;
     int                 ctype;
     int                 ap_sts;
-    rivet_server_conf*  conf;               /* rivet_server_conf* record            */
+    rivet_server_conf*  conf;               /* rivet_server_conf* record                */
 } lazy_tcl_worker;
 
 /* virtual host thread queue descriptor */
@@ -73,8 +73,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;
@@ -157,12 +155,7 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
 
     /* Rivet_ExecutionThreadInit creates and returns the thread private data. */
 
-    private = Rivet_CreatePrivateData(apr_thread_pool_get(thd),true);
-    ap_assert(private != NULL);
-
-    //private->channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
-
-    Rivet_SetupTclPanicProc();
+    private = Rivet_ExecutionThreadInit();
 
     /* A bridge creates and stores in private->ext its own thread private
      * data. The lazy bridge is no exception. We just need a flag controlling 
@@ -171,7 +164,7 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
     private->ext = apr_pcalloc(private->pool,sizeof(mpm_bridge_specific));
     private->ext->keep_going = 1;
 
-    private->ext->interp = Rivet_NewVHostInterp(private,w->server);
+    private->ext->interp = Rivet_NewVHostInterp(private,rsc->default_cache_size);
     //RIVET_POKE_INTERP(private,rsc,Rivet_NewVHostInterp(private,w->server));
     private->ext->interp->channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
 
@@ -260,7 +253,7 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
 
     /* If single thread exit is enabled we delete the Tcl interp */
 
-    if (!rsc->single_thread_exit) 
+    if (!module_globals->single_thread_exit) 
     {
         Tcl_DeleteInterp(private->ext->interp->interp);
     }
@@ -283,7 +276,7 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
 
 static lazy_tcl_worker* create_worker (apr_pool_t* pool,server_rec* server)
 {
-    lazy_tcl_worker*    w;
+    lazy_tcl_worker* w;
 
     w = apr_pcalloc(pool,sizeof(lazy_tcl_worker));
 
@@ -409,7 +402,9 @@ int LazyBridge_Request (request_rec* r,rivet_req_ctype ctype)
     }
 
     apr_thread_mutex_unlock(mutex);
-    
+
+    /* Locking the thread descriptor structure mutex */    
+
     apr_thread_mutex_lock(w->mutex);
     w->r        = r;
     w->ctype    = ctype;
@@ -437,20 +432,28 @@ int LazyBridge_Request (request_rec* r,rivet_req_ctype ctype)
  */
 
 rivet_thread_interp* LazyBridge_Interp (rivet_thread_private* private,
-                                        rivet_server_conf*    conf,
-                                        rivet_thread_interp*  interp)
+                                      rivet_server_conf*    conf,
+                                      rivet_thread_interp*  interp)
 {
     if (interp != NULL) { private->ext->interp = interp; }
 
     return private->ext->interp;
 }
 
+/*
+ * -- LazyBridge_Finalize
+ *
+ * Bridge thread and resources shutdown
+ *
+ */
+
 apr_status_t LazyBridge_Finalize (void* data)
 {
     int idx;
     server_rec* server = (server_rec*) data;
-    rivet_server_conf* conf = RIVET_SERVER_CONF(((server_rec*) data)->module_config);
+    rivet_server_conf* conf = RIVET_SERVER_CONF(server->module_config);
    
+    module_globals->mpm->server_shutdown = 1;
     for (idx = 0; idx < module_globals->vhosts_count; idx++)
     {
         int try;
@@ -516,50 +519,46 @@ int LazyBridge_ExitHandler(rivet_thread_private* private)
 
     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)
+    if (!module_globals->single_thread_exit)
     {
-        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() */
+        /* 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() */
      
-        module_globals->mpm->server_shutdown = 1;
         LazyBridge_Finalize(private->r->server);
 
-    }
+    } 
 
     return TCL_OK;
 }
 
+/*
+ *  -- LazyBridge_ServerInit
+ *
+ * Bridge server wide inizialization:
+ *
+ *  We set the default value of the flag single_thread_exit 
+ *  stored in the module globals
+ *
+ */
+
+int LazyBridge_ServerInit (apr_pool_t* pPool,apr_pool_t* pLog,apr_pool_t* pTemp,server_rec* s)
+{
+    if (module_globals->single_thread_exit == SINGLE_THREAD_EXIT_UNDEF)
+    {
+        module_globals->single_thread_exit = 1;
+    }
+    return OK;
+}
+
+/* Table of bridge control functions */
+
 DLLEXPORT
 RIVET_MPM_BRIDGE {
-    NULL,
+    LazyBridge_ServerInit,
     LazyBridge_ChildInit,
     LazyBridge_Request,
     LazyBridge_Finalize,
     LazyBridge_ExitHandler,
-    LazyBridge_Interp,
-    false
+    LazyBridge_Interp
 };
diff --git a/src/mod_rivet_ng/rivet_prefork_mpm.c b/src/mod_rivet_ng/rivet_prefork_mpm.c
index 983f23d..c023b2e 100644
--- a/src/mod_rivet_ng/rivet_prefork_mpm.c
+++ b/src/mod_rivet_ng/rivet_prefork_mpm.c
@@ -17,14 +17,16 @@
     KIND, either express or implied.  See the License for the
     specific language governing permissions and limitations
     under the License.
-*/
+ */
 
 #include <apr_strings.h>
 
 #include "mod_rivet.h"
 #include "mod_rivet_common.h"
 #include "mod_rivet_generator.h"
+#include "mod_rivet_cache.h"
 #include "httpd.h"
+#include "rivetChannel.h"
 #include "apache_config.h"
 #include "rivet.h"
 #include "rivetCore.h"
@@ -36,6 +38,13 @@ module           rivet_module;
 
 extern TclWebRequest* TclWeb_NewRequestObject (apr_pool_t *p);
 
+/*
+ *  -- PreforkBridge_ServerInit
+ *
+ * Bridge server wide inizialization:
+ *
+ */
+
 int PreforkBridge_ServerInit (apr_pool_t *pPool, 
                                apr_pool_t *pLog,
                                apr_pool_t *pTemp, server_rec *server)
@@ -55,10 +64,26 @@ int PreforkBridge_ServerInit (apr_pool_t *pPool,
 
     if (server_interps[server_idx] == NULL)
     {
-        server_interps[server_idx] = Rivet_NewVHostInterp(private,server);
+        server_interps[server_idx] = Rivet_NewVHostInterp(private,rsc->default_cache_size);
         Rivet_PerInterpInit(server_interps[server_idx],private,server,pPool);
     }
 
+    /* Whether single_thread_exit is 1 or 0 doesn't make any difference for
+     * the prefork bridge, we set the default value anyway in case it hadn't been
+     * set already in the configuration */
+
+    if (module_globals->single_thread_exit == SINGLE_THREAD_EXIT_UNDEF)
+    {
+        module_globals->single_thread_exit = 0;
+    }
+
+    /* The root interpreter is created without a rivet cache (that wouldn't make sense
+     * in that context. We create the cache now */
+
+    if (module_globals->server_interps[server_idx]->cache_size) {
+        RivetCache_Create(module_globals->server_interps[server_idx]); 
+    }
+
    /*
     * Looping through all the server records and creating (or assigning
     * when no virtual host interpreters are required) interpreters
@@ -80,13 +105,13 @@ int PreforkBridge_ServerInit (apr_pool_t *pPool,
 
         if (server_interps[idx] == NULL)
         {
-            if (rsc->separate_virtual_interps == 0)
+            if (module_globals->separate_virtual_interps == 0)
             {
                 server_interps[idx] = server_interps[server_idx];
             }
             else
             {
-                server_interps[idx] = Rivet_NewVHostInterp(private,s);
+                server_interps[idx] = Rivet_NewVHostInterp(private,rsc->default_cache_size);
                 Rivet_PerInterpInit(server_interps[idx],private,s,pPool);
             }
         }
@@ -279,19 +304,24 @@ int PreforkBridge_ExitHandler(rivet_thread_private* private)
 {
     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;
 }
 
 rivet_thread_interp* PreforkBridge_Interp (rivet_thread_private* private,
-                                            rivet_server_conf*    conf,
-                                            rivet_thread_interp*  interp)
+                                         rivet_server_conf*    conf,
+                                         rivet_thread_interp*  interp)
 {
     if (interp != NULL) { private->ext->interps[conf->idx] = interp; }
 
     return private->ext->interps[conf->idx];   
 }
 
+/* Table of bridge control functions */
+
 DLLEXPORT
 RIVET_MPM_BRIDGE {
     PreforkBridge_ServerInit,
diff --git a/src/mod_rivet_ng/rivet_worker_mpm.c b/src/mod_rivet_ng/rivet_worker_mpm.c
index 5b710cf..5eed91d 100644
--- a/src/mod_rivet_ng/rivet_worker_mpm.c
+++ b/src/mod_rivet_ng/rivet_worker_mpm.c
@@ -240,10 +240,10 @@ static void Worker_CreateInterps (rivet_thread_private* private,rivet_thread_int
         
         server_conf = RIVET_SERVER_CONF(s->module_config);
 
-        if ((s == server) || (server_conf->separate_virtual_interps))
+        if ((s == server) || (module_globals->separate_virtual_interps))
         {
 
-            interp_obj = Rivet_NewVHostInterp(private,s);
+            interp_obj = Rivet_NewVHostInterp(private,server_conf->default_cache_size);
             Rivet_PerInterpInit(interp_obj,private,s,private->pool);
             if (s == server) { root_interp = interp_obj; }
 
@@ -381,9 +381,9 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, module_globals->server, "processor thread orderly exit");
 
     {
-        rivet_server_conf* rsc = RIVET_SERVER_CONF(module_globals->server->module_config);
+        //rivet_server_conf* rsc = RIVET_SERVER_CONF(module_globals->server->module_config);
 
-        if (rsc->single_thread_exit)
+        if (module_globals->single_thread_exit)
         {
             //Rivet_ProcessorCleanup(private);
         }
@@ -826,7 +826,7 @@ int Worker_Bridge_ExitHandler(rivet_thread_private* private)
     //module_globals->mpm->exit_command = 1;
     //module_globals->mpm->exit_command_status = private->exit_status;
 
-    if (!private->running_conf->single_thread_exit)
+    if (!module_globals->single_thread_exit)
     {
         module_globals->mpm->skip_thread_on_exit = 1;
 
diff --git a/src/mod_rivet_ng/worker_prefork_common.c b/src/mod_rivet_ng/worker_prefork_common.c
index 7972430..2dea7c4 100644
--- a/src/mod_rivet_ng/worker_prefork_common.c
+++ b/src/mod_rivet_ng/worker_prefork_common.c
@@ -86,8 +86,8 @@ rivet_thread_private* Rivet_SetupInterps (rivet_thread_private* private)
         interp_obj = private->ext->interps[rsc->idx];
 
         if ((s != root_server) &&
-            root_server_conf->separate_channels && 
-            root_server_conf->separate_virtual_interps)
+            module_globals->separate_channels && 
+            module_globals->separate_virtual_interps)
         {
             channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
         } 
@@ -114,7 +114,7 @@ rivet_thread_private* Rivet_SetupInterps (rivet_thread_private* private)
 
         function = rsc->rivet_child_init_script;
         if (function && 
-            (s == root_server || root_server_conf->separate_virtual_interps || function != parentfunction))
+            (s == root_server || module_globals->separate_virtual_interps || function != parentfunction))
         {
             char*       errmsg = MODNAME ": Error in Child init script: %s";
             Tcl_Interp* interp = interp_obj->interp;
@@ -166,7 +166,7 @@ rivet_thread_private* Rivet_SetupInterps (rivet_thread_private* private)
 
 void Rivet_ProcessorCleanup (rivet_thread_private* private)
 {
-    rivet_server_conf*      rsc = RIVET_SERVER_CONF(module_globals->server->module_config);
+    //rivet_server_conf*      rsc = RIVET_SERVER_CONF(module_globals->server->module_config);
     server_rec*             s;
     server_rec*             server;
 
@@ -194,14 +194,14 @@ void Rivet_ProcessorCleanup (rivet_thread_private* private)
     {
         int i = 0;
 
-        if ((i == 0) || rsc->separate_virtual_interps)
+        if ((i == 0) || module_globals->separate_virtual_interps)
         {
             RivetCache_Destroy(private,private->ext->interps[i]);
             Tcl_DeleteInterp(private->ext->interps[i]->interp);
             Rivet_ReleaseRivetChannel(private->ext->interps[i]->interp,private->ext->interps[i]->channel);
         }
 
-        if ((i > 0) && rsc->separate_channels) 
+        if ((i > 0) && module_globals->separate_channels) 
             Rivet_ReleaseRivetChannel(private->ext->interps[i]->interp,private->ext->interps[i]->channel);
 
         Rivet_ReleaseRunningScripts(private->ext->interps[i]->scripts);
@@ -209,3 +209,4 @@ void Rivet_ProcessorCleanup (rivet_thread_private* private)
         i++;
     } 
 }
+
diff --git a/src/rivet.h b/src/rivet.h
index 63fde97..ddbc522 100644
--- a/src/rivet.h
+++ b/src/rivet.h
@@ -116,7 +116,7 @@ EXTERN int Rivet_InitWWW(Tcl_Interp *interp);
     interp_obj = interps[rsc->idx]; \
     for (s = server; s != NULL; s = s->next) { \
         aFunction (s, interp_obj); \
-        if (rsc->separate_virtual_interps == 0) { break; } \
+        if (module_globals->separate_virtual_interps == 0) { break; } \
     } \
 }
 
@@ -130,7 +130,7 @@ EXTERN int Rivet_InitWWW(Tcl_Interp *interp);
     interp_obj = interps[rsc->idx]; \
     for (s = server; s != NULL; s = s->next) { \
         aFunction (s, interp_obj, __VA_ARGS__ ); \
-        if (rsc->separate_virtual_interps == 0) { break; } \
+        if (module_globals->separate_virtual_interps == 0) { break; } \
     } \
 }
 


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