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