You are viewing a plain text version of this content. The canonical link for it is here.
Posted to site-cvs@tcl.apache.org by mx...@apache.org on 2015/12/26 01:22:11 UTC
svn commit: r1721698 - in /tcl/rivet/trunk: ./ doc/xml/ src/ src/mod_rivet/
Author: mxmanghi
Date: Sat Dec 26 00:22:11 2015
New Revision: 1721698
URL: http://svn.apache.org/viewvc?rev=1721698&view=rev
Log:
* src/mod_rivet/worker_prefork_common.c: functions common to both the prefork
and worker bridges, but not general enough bur rather specific to the worker
model adopted by them
* src/mod_rivet/rivet_lazy_mpm.c: further development, now capable of serving
rivet requests, but needs to be completed.
* src/mod_rivet/mod_rivet_common.c: more stuff moved from mod_rivet to this file
* src/mod_rivet/mod_rivet.h: new data organization with bridge specific thread
private data
* src/mod_rivet/Tclwebapache.c: API changed from Tclwebreq pointers to
thread private data that is supposed to store most of the thread environment
Added:
tcl/rivet/trunk/src/mod_rivet/rivetCore.h
tcl/rivet/trunk/src/mod_rivet/worker_prefork_common.c
Modified:
tcl/rivet/trunk/ChangeLog
tcl/rivet/trunk/doc/xml/internals.xml
tcl/rivet/trunk/src/Makefile.am
tcl/rivet/trunk/src/TclWeb.h
tcl/rivet/trunk/src/mod_rivet/TclWebapache.c
tcl/rivet/trunk/src/mod_rivet/mod_rivet.c
tcl/rivet/trunk/src/mod_rivet/mod_rivet.h
tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.c
tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.h
tcl/rivet/trunk/src/mod_rivet/rivetCore.c
tcl/rivet/trunk/src/mod_rivet/rivet_lazy_mpm.c
tcl/rivet/trunk/src/mod_rivet/rivet_prefork_mpm.c
tcl/rivet/trunk/src/mod_rivet/rivet_worker_mpm.c
tcl/rivet/trunk/src/rivet.h
Modified: tcl/rivet/trunk/ChangeLog
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/ChangeLog?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/ChangeLog (original)
+++ tcl/rivet/trunk/ChangeLog Sat Dec 26 00:22:11 2015
@@ -1,3 +1,15 @@
+2015-12-26 Massimo Manghi <mx...@apache.org>
+ * src/mod_rivet/worker_prefork_common.c: functions common to both the prefork
+ and worker bridges, but not general enough bur rather specific to the worker
+ model adopted by them
+ * src/mod_rivet/rivet_lazy_mpm.c: further development, now capable of serving
+ rivet requests, but needs to be completed.
+ * src/mod_rivet/mod_rivet_common.c: more stuff moved from mod_rivet to this file
+ * src/mod_rivet/mod_rivet.h: new data organization with bridge specific thread
+ private data
+ * src/mod_rivet/Tclwebapache.c: API changed from Tclwebreq pointers to
+ thread private data that is supposed to store most of the thread environment
+
2015-12-22 Massimo Manghi <mx...@apache.org>
* src/mod_rivet/rivet_lazy_mpm.c: taking a snapshot of the current development
as this code proved to be quite robust when stressed using 'ab'
Modified: tcl/rivet/trunk/doc/xml/internals.xml
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/doc/xml/internals.xml?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/doc/xml/internals.xml (original)
+++ tcl/rivet/trunk/doc/xml/internals.xml Sat Dec 26 00:22:11 2015
@@ -107,9 +107,10 @@
interpreters to orderly exit. This pointer can be NULL if the bridge
has no special need when a child process must exit.
</listitem>
- <listitem><emphasis>mpm_master_interp</emphasis>: This pointer must
- be assigned with a valid function returning the child process master
- interpreter descriptor. The master interpreter should be either the only
+ <listitem><emphasis>mpm_master_interp</emphasis>: This function
+ is mainly existing to allow fork capable bridges to reuturn
+ the child process master interpreter descriptor.
+ In general the master interpreter should be either the only
interpreter descriptor pointer of the child process (when
<command>SeparateVirtualInterps</command> is off (default)) or one of
the virtual host interpreter pointers. The current implementation of
Modified: tcl/rivet/trunk/src/Makefile.am
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/Makefile.am?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/Makefile.am (original)
+++ tcl/rivet/trunk/src/Makefile.am Sat Dec 26 00:22:11 2015
@@ -56,12 +56,12 @@ mod_rivet_la_CPPFLAGS = -I@rivet_core@ -
lib_libmpmdir = @RIVET_TCL_TARGET@/mpm
lib_libmpm_LTLIBRARIES = rivet_worker_mpm.la rivet_prefork_mpm.la rivet_lazy_mpm.la
-rivet_worker_mpm_la_SOURCES = @rivet_core@/rivet_worker_mpm.c
+rivet_worker_mpm_la_SOURCES = @rivet_core@/rivet_worker_mpm.c @rivet_core@/worker_prefork_common.c
rivet_worker_mpm_la_LDFLAGS = @TCL_STUB_LIB_SPEC@ @APXS_LDFLAGS@ -module -avoid-version
rivet_worker_mpm_la_LIBADD = @APXS_LIBS@
rivet_worker_mpm_la_CPPFLAGS = @apache_include@ -I@rivet_core@ @TCL_INCLUDES@ @APXS_CPPFLAGS@ @APXS_INCLUDES@ @APR_CPPFLAGS@ @APR_INCLUDES@ @APU_INCLUDES@ -I@apache_request@ -I@RIVET_BASE_INCLUDE@
-rivet_prefork_mpm_la_SOURCES = @rivet_core@/rivet_prefork_mpm.c
+rivet_prefork_mpm_la_SOURCES = @rivet_core@/rivet_prefork_mpm.c @rivet_core@/worker_prefork_common.c
rivet_prefork_mpm_la_LDFLAGS = @TCL_STUB_LIB_SPEC@ @APXS_LDFLAGS@ -module -avoid-version
rivet_prefork_mpm_la_LIBADD = @APXS_LIBS@
rivet_prefork_mpm_la_CPPFLAGS = @apache_include@ -I@rivet_core@ @TCL_INCLUDES@ @APXS_CPPFLAGS@ @APXS_INCLUDES@ @APR_CPPFLAGS@ @APR_INCLUDES@ @APU_INCLUDES@ -I@apache_request@ -I@RIVET_BASE_INCLUDE@
Modified: tcl/rivet/trunk/src/TclWeb.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/TclWeb.h?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/TclWeb.h (original)
+++ tcl/rivet/trunk/src/TclWeb.h Sat Dec 26 00:22:11 2015
@@ -110,9 +110,9 @@ int TclWeb_GetVarNames(Tcl_Obj *result,
int TclWeb_GetAllVars(Tcl_Obj *result, int source, TclWebRequest *req);
-int TclWeb_GetEnvVars(Tcl_Obj *envvar, TclWebRequest *req);
+int TclWeb_GetEnvVars(Tcl_Obj *envvar, rivet_thread_private *p);
-int TclWeb_GetHeaderVars(Tcl_Obj *headersvar, TclWebRequest *req);
+int TclWeb_GetHeaderVars(Tcl_Obj *headersvar, rivet_thread_private *p);
/*
*-----------------------------------------------------------------------------
@@ -255,7 +255,7 @@ char *TclWeb_StringToUtf(char *in, TclWe
Tcl_Obj * TclWeb_StringToUtfToObj(char *in, TclWebRequest *req);
-char *TclWeb_GetEnvVar( TclWebRequest *req, char * );
+char *TclWeb_GetEnvVar(rivet_thread_private *,char *);
char *TclWeb_GetVirtualFile( TclWebRequest *req, char *virtualname );
Modified: tcl/rivet/trunk/src/mod_rivet/TclWebapache.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/TclWebapache.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/TclWebapache.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/TclWebapache.c Sat Dec 26 00:22:11 2015
@@ -40,7 +40,7 @@
#include "TclWeb.h"
extern module rivet_module;
-extern apr_threadkey_t* rivet_thread_key;
+extern mod_rivet_globals* module_globals;
#define TCLWEBPOOL req->req->pool
#define BUFSZ 4096
@@ -435,11 +435,11 @@ TclWeb_VarNumber(Tcl_Obj *result, int so
apr_table_elts(req->apachereq->parms);
if (source == VAR_SRC_QUERYSTRING) {
- Tcl_SetIntObj(result, req->apachereq->nargs);
+ Tcl_SetIntObj(result, req->apachereq->nargs);
} else if (source == VAR_SRC_POST) {
- Tcl_SetIntObj(result, parmsarray->nelts - req->apachereq->nargs);
+ Tcl_SetIntObj(result, parmsarray->nelts - req->apachereq->nargs);
} else {
- Tcl_SetIntObj(result, parmsarray->nelts);
+ Tcl_SetIntObj(result, parmsarray->nelts);
}
return TCL_OK;
@@ -450,21 +450,25 @@ TclWeb_VarNumber(Tcl_Obj *result, int so
* have already done so, we don't need to do it again.
*/
static void
-TclWeb_InitEnvVars( TclWebRequest *req )
+TclWeb_InitEnvVars (rivet_thread_private* private)
{
- rivet_server_conf *rsc;
- apr_table_t *table = req->req->subprocess_env;
+ //rivet_server_conf *rsc;
char *timefmt = DEFAULT_TIME_FORMAT;
char *t;
- apr_time_t date = req->req->request_time;
+ apr_time_t date;
#ifndef WIN32
struct passwd *pw;
#endif /* ndef WIN32 */
- rivet_thread_private* private;
+ TclWebRequest *req;
+ apr_table_t *table;
+
+ req = private->req;
+ table = req->req->subprocess_env;
+ date = req->req->request_time;
if( req->environment_set ) return;
- rsc = RIVET_SERVER_CONF( req->req->server->module_config );
+ //rsc = RIVET_SERVER_CONF( req->req->server->module_config );
/* Retrieve cgi variables. */
ap_add_cgi_vars( req->req );
@@ -508,17 +512,16 @@ TclWeb_InitEnvVars( TclWebRequest *req )
/* Here we create some variables with Rivet internal information. */
- ap_assert (apr_threadkey_private_get ((void **)&private,rivet_thread_key) == APR_SUCCESS);
apr_table_set (table, "RIVET_CACHE_FREE",
- (char*) apr_psprintf (TCLWEBPOOL, "%d",private->interps[rsc->idx]->cache_free));
+ (char*) apr_psprintf (TCLWEBPOOL, "%d",RIVET_PEEK_INTERP(private,private->running_conf)->cache_free));
apr_table_set (table, "RIVET_CACHE_SIZE",
- (char*) apr_psprintf (TCLWEBPOOL, "%d",private->interps[rsc->idx]->cache_size));
+ (char*) apr_psprintf (TCLWEBPOOL, "%d",RIVET_PEEK_INTERP(private,private->running_conf)->cache_size));
req->environment_set = 1;
}
int
-TclWeb_GetEnvVars(Tcl_Obj *envvar, TclWebRequest *req)
+TclWeb_GetEnvVars(Tcl_Obj *envvar,rivet_thread_private* private)
{
int i;
@@ -526,9 +529,12 @@ TclWeb_GetEnvVars(Tcl_Obj *envvar, TclWe
apr_table_entry_t *env;
Tcl_Obj *key;
Tcl_Obj *val;
+ TclWebRequest *req;
+
- TclWeb_InitEnvVars( req );
+ TclWeb_InitEnvVars(private);
+ req = private->req;
Tcl_IncrRefCount(envvar);
/* Transfer Apache internal CGI variables to TCL request namespace. */
env_arr = (apr_array_header_t *) apr_table_elts(req->req->subprocess_env);
@@ -563,16 +569,18 @@ TclWeb_GetEnvVars(Tcl_Obj *envvar, TclWe
}
int
-TclWeb_GetHeaderVars(Tcl_Obj *headersvar, TclWebRequest *req)
+TclWeb_GetHeaderVars(Tcl_Obj *headersvar,rivet_thread_private* private)
{
int i;
-
+ TclWebRequest *req;
apr_array_header_t *hdrs_arr;
apr_table_entry_t *hdrs;
Tcl_Obj *key;
Tcl_Obj *val;
- TclWeb_InitEnvVars( req );
+ req = private->req;
+
+ TclWeb_InitEnvVars(private);
Tcl_IncrRefCount(headersvar);
/* Transfer client request headers to TCL request namespace. */
@@ -580,19 +588,19 @@ TclWeb_GetHeaderVars(Tcl_Obj *headersvar
hdrs = (apr_table_entry_t *) hdrs_arr->elts;
for (i = 0; i < hdrs_arr->nelts; ++i)
{
- if (!hdrs[i].key)
- continue;
+ if (!hdrs[i].key)
+ continue;
- key = TclWeb_StringToUtfToObj(hdrs[i].key, req);
- val = TclWeb_StringToUtfToObj(hdrs[i].val, req);
- Tcl_IncrRefCount(key);
- Tcl_IncrRefCount(val);
+ key = TclWeb_StringToUtfToObj(hdrs[i].key, req);
+ val = TclWeb_StringToUtfToObj(hdrs[i].val, req);
+ Tcl_IncrRefCount(key);
+ Tcl_IncrRefCount(val);
- /* See comment in TclWeb_GetEnvVars concerning Bug 48963*/
+ /* See comment in TclWeb_GetEnvVars concerning Bug 48963*/
Tcl_ObjSetVar2(req->interp, headersvar, key, val, 0);
- Tcl_DecrRefCount(key);
- Tcl_DecrRefCount(val);
+ Tcl_DecrRefCount(key);
+ Tcl_DecrRefCount(val);
}
/* Transfer Apache internal CGI variables to TCL request namespace. */
@@ -767,11 +775,13 @@ int TclWeb_UploadNames(Tcl_Obj *names, T
}
char *
-TclWeb_GetEnvVar( TclWebRequest *req, char *key )
+TclWeb_GetEnvVar(rivet_thread_private* private,char *key)
{
char *val;
+ TclWebRequest *req;
- TclWeb_InitEnvVars( req );
+ req = private->req;
+ TclWeb_InitEnvVars(private);
/* Check to see if it's a header variable first. */
val = (char *)apr_table_get( req->req->headers_in, key );
Modified: tcl/rivet/trunk/src/mod_rivet/mod_rivet.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/mod_rivet.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/mod_rivet.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/mod_rivet.c Sat Dec 26 00:22:11 2015
@@ -59,6 +59,7 @@
#include "rivet.h"
#include "mod_rivet_common.h"
#include "rivetParser.h"
+#include "rivetCore.h"
rivet_interp_globals interp_globals;
@@ -66,9 +67,6 @@ extern Tcl_ChannelType RivetChan;
apr_threadkey_t* rivet_thread_key = NULL;
mod_rivet_globals* module_globals = NULL;
-void Rivet_PerInterpInit (rivet_thread_interp* interp,
- rivet_thread_private* private,
- server_rec *s, apr_pool_t *p );
static int Rivet_ExecuteAndCheck (rivet_thread_private *private, Tcl_Obj *tcl_script_obj);
int Rivet_InitCore (Tcl_Interp *interp,rivet_thread_private* p);
@@ -114,29 +112,6 @@ Rivet_PrintErrorMessage (Tcl_Interp* int
Tcl_DecrRefCount(errormsg);
}
-
-/*----------------------------------------------------------------------------
- * -- Rivet_RunningScripts
- *
- *
- *
- *-----------------------------------------------------------------------------
- */
-
-static running_scripts*
-Rivet_RunningScripts ( apr_pool_t* pool,
- running_scripts* scripts,
- rivet_server_conf* rivet_conf)
-{
- RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_before_script);
- RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_after_script);
- RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_error_script);
- RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_abort_script);
- RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,after_every_script);
-
- return scripts;
-}
-
/*-----------------------------------------------------------------------------
* -- Rivet_ReleaseScript
*
@@ -157,286 +132,6 @@ Rivet_ReleaseScripts (running_scripts* s
}
/*
- *-----------------------------------------------------------------------------
- * Rivet_CreateCache --
- *
- * Arguments:
- * rsc: pointer to a server_rec structure
- *
- * Results:
- * None
- *
- * Side Effects:
- *
- *-----------------------------------------------------------------------------
- */
-
-static void Rivet_CreateCache (apr_pool_t *p, rivet_thread_interp* interp_obj)
-{
- interp_obj->objCacheList = apr_pcalloc(p, (signed)((interp_obj->cache_size)*sizeof(char *)));
- interp_obj->objCache = apr_pcalloc(p, sizeof(Tcl_HashTable));
- Tcl_InitHashTable(interp_obj->objCache, TCL_STRING_KEYS);
-}
-
-/*
- * Rivet_DuplicateVhostInterp
- *
- *
- */
-
-static rivet_thread_interp*
-Rivet_DuplicateVHostInterp(apr_pool_t* pool, rivet_thread_interp* source_obj)
-{
- rivet_thread_interp* interp_obj = apr_pcalloc(pool,sizeof(rivet_thread_interp));
-
- interp_obj->interp = source_obj->interp;
- interp_obj->channel = source_obj->channel;
- interp_obj->cache_free = source_obj->cache_free;
- interp_obj->cache_size = source_obj->cache_size;
-
- /* TODO: decouple cache by creating a new cache object */
-
- if (interp_obj->cache_size) {
- Rivet_CreateCache(pool,interp_obj);
- }
-
- interp_obj->pool = source_obj->pool;
- interp_obj->scripts = (running_scripts *) apr_pcalloc(pool,sizeof(running_scripts));
- interp_obj->per_dir_scripts = apr_hash_make(pool);
- interp_obj->flags = source_obj->flags;
- return interp_obj;
-}
-
- /* XXX: the pool passed to Rivet_NewVHostInterp must be the private pool of
- * a rivet_thread_private object
- */
-
-rivet_thread_interp* Rivet_NewVHostInterp(apr_pool_t *pool)
-{
- extern int ap_max_requests_per_child;
- rivet_thread_interp* interp_obj = apr_pcalloc(pool,sizeof(rivet_thread_interp));
- rivet_server_conf* rsc;
-
- /* The cache size is global so we take it from here */
-
- rsc = RIVET_SERVER_CONF (module_globals->server->module_config);
-
- /* This calls needs the root server_rec just for logging purposes*/
-
- interp_obj->interp = Rivet_CreateTclInterp(module_globals->server);
-
- /* We now read from the pointers to the cache_size and cache_free conf parameters
- * for compatibility with mod_rivet current version, but these values must become
- * integers not pointers
- */
-
- 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;
- }
-
- /* we now create memory from the cache pool as subpool of the thread private pool */
-
- if (apr_pool_create(&interp_obj->pool, pool) != APR_SUCCESS)
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, module_globals->server,
- MODNAME ": could not initialize cache private pool");
- return NULL;
- }
-
- // Initialize cache structures
-
- if (interp_obj->cache_size) {
- Rivet_CreateCache(pool,interp_obj);
- }
-
- interp_obj->flags = 0;
-
- interp_obj->scripts = (running_scripts *) apr_pcalloc(pool,sizeof(running_scripts));
- interp_obj->per_dir_scripts = apr_hash_make(pool);
-
- return interp_obj;
-}
-
-/* -- Rivet_VirtualHostsInterps
- *
- * The server_rec chain is walked through and server configurations is read to
- * set up the thread private configuration and interpreters database
- *
- * Arguments:
- *
- * rivet_thread_private* private;
- *
- * Returned value:
- *
- * a new rivet_thread_private object
- *
- * Side effects:
- *
- * GlobalInitScript and ChildInitScript are run at this stage
- *
- */
-
-rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private)
-{
- server_rec* s;
- server_rec* root_server = module_globals->server;
- rivet_server_conf* root_server_conf;
- rivet_server_conf* myrsc;
- rivet_thread_interp* root_interp;
- void* parentfunction; /* this is topmost initialization script */
- void* function;
-
- root_server_conf = RIVET_SERVER_CONF (root_server->module_config);
-
- root_interp = (*RIVET_MPM_BRIDGE_FUNCTION(mpm_master_interp))();
-
- /* we must assume the module was able to create the root interprter otherwise
- * it's just a null module. I try to have also this case to develop experimental
- * bridges without the Tcl stuff
- */
-
- //if (root_interp == NULL) return private;
-
- ap_assert (root_interp != NULL);
-
- /* Using the root interpreter we evaluate the global initialization script, if any */
-
- if (root_server_conf->rivet_global_init_script != NULL) {
- Tcl_Obj* global_tcl_script;
-
- global_tcl_script = Tcl_NewStringObj(root_server_conf->rivet_global_init_script,-1);
- Tcl_IncrRefCount(global_tcl_script);
- if (Tcl_EvalObjEx(root_interp->interp, global_tcl_script, 0) != TCL_OK)
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, module_globals->server,
- MODNAME ": Error running GlobalInitScript '%s': %s",
- root_server_conf->rivet_global_init_script,
- Tcl_GetVar(root_interp->interp, "errorInfo", 0));
- } else {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, module_globals->server,
- MODNAME ": GlobalInitScript '%s' successful",
- root_server_conf->rivet_global_init_script);
- }
- Tcl_DecrRefCount(global_tcl_script);
- }
-
- /* then we proceed assigning/creating the interpreters for the
- * virtual hosts known to the server
- */
-
- parentfunction = root_server_conf->rivet_child_init_script;
-
- for (s = root_server; s != NULL; s = s->next)
- {
- rivet_thread_interp* rivet_interp;
-
- myrsc = RIVET_SERVER_CONF(s->module_config);
-
- /* by default we assign the root_interpreter as
- * interpreter of the virtual host. In case of separate
- * virtual interpreters we create new ones for each
- * virtual host
- */
-
- rivet_interp = root_interp;
-
- if (s == root_server)
- {
- Tcl_RegisterChannel(rivet_interp->interp,*rivet_interp->channel);
- }
- else
- {
- if (root_server_conf->separate_virtual_interps)
- {
- rivet_interp = Rivet_NewVHostInterp(private->pool);
- if (myrsc->separate_channels)
- {
- rivet_interp->channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
- Tcl_RegisterChannel(rivet_interp->interp,*rivet_interp->channel);
- }
- else
- {
- rivet_interp->channel = private->channel;
- }
- }
- else
- {
- rivet_interp = Rivet_DuplicateVHostInterp(private->pool,root_interp);
- }
- }
-
- /* interpreter base running scripts definition and initialization */
-
- rivet_interp->scripts = Rivet_RunningScripts (private->pool,rivet_interp->scripts,myrsc);
-
- private->interps[myrsc->idx] = rivet_interp;
-
- /* Basic Rivet packages and libraries are loaded here */
-
- if ((rivet_interp->flags & RIVET_INTERP_INITIALIZED) == 0)
- {
- Rivet_PerInterpInit(rivet_interp, private, root_server, private->pool);
- }
-
- /* TODO: check if it's absolutely necessary to lock the pool_mutex in order
- * to allocate from the module global pool
- */
-
- /* this stuff must be allocated from the module global pool which
- * has the child process' same lifespan
- */
-
- apr_thread_mutex_lock(module_globals->pool_mutex);
- myrsc->server_name = (char*) apr_pstrdup (private->pool, s->server_hostname);
- apr_thread_mutex_unlock(module_globals->pool_mutex);
-
- /* when configured a child init script gets evaluated */
-
- function = myrsc->rivet_child_init_script;
- if (function &&
- (s == root_server || root_server_conf->separate_virtual_interps || function != parentfunction))
- {
- char* errmsg = MODNAME ": Error in Child init script: %s";
- Tcl_Interp* interp = rivet_interp->interp;
- Tcl_Obj* tcl_child_init = Tcl_NewStringObj(function,-1);
-
- Tcl_IncrRefCount(tcl_child_init);
- Tcl_Preserve (interp);
-
- /* There is a lot of passing around of pointers among various record
- * objects. We should understand if this is all that necessary.
- * Here we assign the server_rec pointer to the interpreter which
- * is wrong, because without separate interpreters it doens't make
- * any sense. TODO
- */
-
- if (Tcl_EvalObjEx(interp,tcl_child_init, 0) != TCL_OK) {
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server,
- errmsg, function);
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server,
- "errorCode: %s", Tcl_GetVar(interp, "errorCode", 0));
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server,
- "errorInfo: %s", Tcl_GetVar(interp, "errorInfo", 0));
- }
- Tcl_Release (interp);
- Tcl_DecrRefCount(tcl_child_init);
- }
- }
- return private;
-}
-
-
-/*
* -- Rivet_SendContent
*
* Set things up to execute a Tcl script or parse a rvt template, prepare
@@ -478,7 +173,7 @@ Rivet_SendContent(rivet_thread_private *
/* the interp index in the private data can not be changed by a config merge */
- interp_obj = private->interps[private->running_conf->idx];
+ interp_obj = RIVET_PEEK_INTERP(private,private->running_conf);
private->running = interp_obj->scripts;
running_channel = interp_obj->channel;
@@ -662,7 +357,7 @@ Rivet_SendContent(rivet_thread_private *
//if (Tcl_EvalObjEx(interp_obj->interp,private->running->after_every_script,0) == TCL_ERROR)
if (Rivet_ExecuteAndCheck(private,private->running->after_every_script) == TCL_ERROR)
{
- Rivet_PrintErrorMessage(private->interps[private->running_conf->idx]->interp,
+ Rivet_PrintErrorMessage(RIVET_PEEK_INTERP(private,private->running_conf)->interp,
"<b>Rivet AfterEveryScript failed</b>");
}
}
@@ -791,7 +486,7 @@ static int
Rivet_RunAbortScript (rivet_thread_private *private)
{
int retcode = TCL_OK;
- Tcl_Interp* interp = private->interps[private->running_conf->idx]->interp;
+ Tcl_Interp* interp = RIVET_PEEK_INTERP(private,private->running_conf)->interp;
if (private->running->rivet_abort_script)
{
@@ -857,7 +552,7 @@ Rivet_ExecuteAndCheck(rivet_thread_priva
int tcl_result;
rivet_thread_interp* interp_obj;
- interp_obj = private->interps[private->running_conf->idx];
+ interp_obj = RIVET_PEEK_INTERP(private,private->running_conf);
//rivet_interp_globals *globals = Tcl_GetAssocData(interp_obj->interp, "rivet", NULL);
Tcl_Preserve (interp_obj->interp);
@@ -961,7 +656,7 @@ Rivet_ParseExecFile(rivet_thread_private
/* We have to fetch the interpreter data from the thread private environment */
- rivet_interp = private->interps[private->running_conf->idx];
+ rivet_interp = RIVET_PEEK_INTERP(private,private->running_conf);
interp = rivet_interp->interp;
/* If the user configuration has indeed been updated, I guess that
@@ -1217,140 +912,6 @@ Rivet_CreateTclInterp (server_rec* s)
return interp;
}
-/*
- *-----------------------------------------------------------------------------
- *
- * Rivet_PerInterpInit --
- *
- * Do the initialization that needs to happen for every
- * interpreter.
- *
- * Results:
- * None.
- *
- * Side Effects:
- * None.
- *
- *-----------------------------------------------------------------------------
- */
-void Rivet_PerInterpInit(rivet_thread_interp* interp_obj,rivet_thread_private* private, server_rec *s, apr_pool_t *p)
-{
- rivet_interp_globals* globals = NULL;
- Tcl_Obj* auto_path = NULL;
- Tcl_Obj* rivet_tcl = NULL;
- Tcl_Interp* interp = interp_obj->interp;
-
- ap_assert (interp != (Tcl_Interp *)NULL);
- Tcl_Preserve (interp);
-
- /* Set up interpreter associated data */
-
- globals = apr_pcalloc (p, sizeof(rivet_interp_globals));
- Tcl_SetAssocData (interp,"rivet",NULL,globals);
-
- /*
- * abort_page status variables in globals are set here and then
- * reset in Rivet_SendContent just before the request processing is
- * completed
- */
-
- /* Rivet commands namespace is created */
-
- globals->rivet_ns = Tcl_CreateNamespace (interp,RIVET_NS,NULL,
- (Tcl_NamespaceDeleteProc *)NULL);
- //globals->req = TclWeb_NewRequestObject (p);
- //globals->r = NULL;
- //globals->srec = s;
-
- /* Eval Rivet's init.tcl file to load in the Tcl-level commands. */
-
- /* We put in front the auto_path list the path to the directory where
- * init.tcl is located (provides package Rivet, previously RivetTcl)
- */
-
- auto_path = Tcl_GetVar2Ex(interp,"auto_path",NULL,TCL_GLOBAL_ONLY);
-
- rivet_tcl = Tcl_NewStringObj(RIVET_DIR,-1);
- Tcl_IncrRefCount(rivet_tcl);
-
- if (Tcl_IsShared(auto_path)) {
- auto_path = Tcl_DuplicateObj(auto_path);
- }
-
- if (Tcl_ListObjReplace(interp,auto_path,0,0,1,&rivet_tcl) == TCL_ERROR)
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
- MODNAME ": error setting auto_path: %s",
- Tcl_GetStringFromObj(auto_path,NULL));
- } else {
- Tcl_SetVar2Ex(interp,"auto_path",NULL,auto_path,TCL_GLOBAL_ONLY);
- }
-
- Tcl_DecrRefCount(rivet_tcl);
-
- /* Initialize the interpreter with Rivet's Tcl commands. */
-
- if (private == NULL)
- {
- /* reduced core for the server init interpreter */
-
- // RIVET_OBJ_CMD ("inspect",Rivet_InspectCmd,private);
-
- }
- else
- {
- /* full fledged rivet core */
-
- Rivet_InitCore(interp,private);
-
- }
-
- /* Create a global array with information about the server. */
- Rivet_InitServerVariables(interp, p );
-
- /* Loading into the interpreter commands in librivet.so */
- /* Tcl Bug #3216070 has been solved with 8.5.10 and commands shipped with
- * Rivetlib can be mapped at this stage
- */
-
- if (Tcl_PkgRequire(interp, RIVETLIB_TCL_PACKAGE, RIVET_VERSION, 1) == NULL)
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
- MODNAME ": Error loading rivetlib package: %s",
- Tcl_GetStringResult(interp) );
- exit(1);
- }
-
- /* If rivet is configured to export the ::rivet namespace commands we set the
- * array variable ::rivet::module_conf(export_namespace_commands) before calling init.tcl
- * This array will be unset after commands are exported.
- */
-
- Tcl_SetVar2Ex(interp,"module_conf","export_namespace_commands",Tcl_NewIntObj(RIVET_NAMESPACE_EXPORT),0);
- Tcl_SetVar2Ex(interp,"module_conf","import_rivet_commands",Tcl_NewIntObj(RIVET_NAMESPACE_IMPORT),0);
-
- /* Eval Rivet's init.tcl file to load in the Tcl-level commands. */
-
- /* Watch out! Calling Tcl_PkgRequire with a version number binds this module to
- * the Rivet package revision number in rivet/init.tcl
- *
- * RIVET_TCL_PACKAGE_VERSION is defined by configure.ac as the combination
- * "MAJOR_VERSION.MINOR_VERSION". We don't expect to change rivet/init.tcl
- * across patchlevel releases
- */
-
- if (Tcl_PkgRequire(interp, "Rivet", RIVET_INIT_VERSION, 1) == NULL)
- {
- ap_log_error (APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
- MODNAME ": init.tcl must be installed correctly for Apache Rivet to function: %s (%s)",
- Tcl_GetStringResult(interp), RIVET_DIR );
- exit(1);
- }
-
- Tcl_Release(interp);
- interp_obj->flags |= RIVET_INTERP_INITIALIZED;
-}
-
/*
* -- Rivet_RunServerInit
*
@@ -1541,7 +1102,6 @@ Rivet_ServerInit (apr_pool_t *pPool, apr
/* we require only mpm_request and mpm_master_interp to be defined */
ap_assert(RIVET_MPM_BRIDGE_FUNCTION(mpm_request) != NULL);
- ap_assert(RIVET_MPM_BRIDGE_FUNCTION(mpm_master_interp) != NULL);
apr_thread_mutex_create(&module_globals->pool_mutex, APR_THREAD_MUTEX_UNNESTED, pPool);
Modified: tcl/rivet/trunk/src/mod_rivet/mod_rivet.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/mod_rivet.h?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/mod_rivet.h (original)
+++ tcl/rivet/trunk/src/mod_rivet/mod_rivet.h Sat Dec 26 00:22:11 2015
@@ -156,14 +156,15 @@ typedef struct _rivet_thread_interp {
unsigned int flags; /* signals of various interp specific conditions */
} rivet_thread_interp;
+typedef struct _thread_worker_private rivet_thread_private;
+
typedef int (RivetBridge_ServerInit) (apr_pool_t*,apr_pool_t*,apr_pool_t*,server_rec*);
typedef void (RivetBridge_ChildInit) (apr_pool_t* pPool,server_rec* s);
typedef int (RivetBridge_Request) (request_rec*,rivet_req_ctype);
-typedef apr_status_t
- (RivetBridge_Finalize)(void*);
-typedef rivet_thread_interp*
- (RivetBridge_Master_Interp) (void);
+typedef apr_status_t (RivetBridge_Finalize)(void*);
+typedef rivet_thread_interp* (RivetBridge_Master_Interp) (void);
typedef int (RivetBridge_Exit_Handler) (int);
+typedef rivet_thread_interp* (RivetBridge_Thread_Interp)(rivet_thread_private*,rivet_server_conf *);
typedef struct _mpm_bridge_table {
RivetBridge_ServerInit *mpm_server_init;
@@ -172,6 +173,7 @@ typedef struct _mpm_bridge_table {
RivetBridge_Finalize *mpm_finalize;
RivetBridge_Master_Interp *mpm_master_interp;
RivetBridge_Exit_Handler *mpm_exit_handler;
+ RivetBridge_Thread_Interp *mpm_thread_interp;
} rivet_bridge_table;
/* we need also a place where to store module wide globals */
@@ -196,15 +198,13 @@ typedef struct _mod_rivet_globals {
#endif
} mod_rivet_globals;
+typedef struct mpm_bridge_specific mpm_bridge_specific;
+
typedef struct _thread_worker_private {
apr_pool_t* pool; /* threads private memory pool */
rivet_thread_interp** interps; /* database of virtual host interps */
Tcl_Channel* channel; /* the Tcl thread private channel */
int req_cnt; /* requests served by thread */
- int keep_going; /* thread loop controlling variable */
- /* the request_rec and TclWebRequest *
- * are copied here to be passed to a *
- * channel */
rivet_req_ctype ctype; /* */
request_rec* r; /* current request_rec */
TclWebRequest* req;
@@ -224,6 +224,7 @@ typedef struct _thread_worker_private {
apr_pool_t* rivet_panic_pool;
server_rec* rivet_panic_server_rec;
+ mpm_bridge_specific* ext; /* bridge specific extension */
} rivet_thread_private;
/* eventually we will transfer 'global' variables in here and 'de-globalize' them */
@@ -319,6 +320,8 @@ EXTERN Tcl_Interp* Rivet_CreateTclInterp
(*module_globals->bridge_jump_table->fun)(__VA_ARGS__);\
}
+#define RIVET_PEEK_INTERP (module_globals->bridge_jump_table->mpm_thread_interp)
+
#define RIVET_MPM_BRIDGE rivet_bridge_table bridge_jump_table =
#endif /* MOD_RIVET_H */
Modified: tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.c Sat Dec 26 00:22:11 2015
@@ -1,7 +1,6 @@
-/*
- mod_rivet_common.c - functions likely to be shared among
- different versions of mod_rivet.c
+/* -- mod_rivet_common.c - functions likely to be shared among different versions of mod_rivet.c */
+/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
@@ -35,10 +34,254 @@
#include "rivetParser.h"
#include "rivet.h"
#include "apache_config.h"
+#include "rivetCore.h"
extern apr_threadkey_t* rivet_thread_key;
extern mod_rivet_globals* module_globals;
+/*----------------------------------------------------------------------------
+ * -- Rivet_RunningScripts
+ *
+ *
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+running_scripts* Rivet_RunningScripts (apr_pool_t* pool,running_scripts* scripts,rivet_server_conf* rivet_conf)
+{
+ RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_before_script);
+ RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_after_script);
+ RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_error_script);
+ RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_abort_script);
+ RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,after_every_script);
+
+ return scripts;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Rivet_PerInterpInit --
+ *
+ * Do the initialization that needs to happen for every
+ * interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+void Rivet_PerInterpInit(rivet_thread_interp* interp_obj,rivet_thread_private* private, server_rec *s, apr_pool_t *p)
+{
+ rivet_interp_globals* globals = NULL;
+ Tcl_Obj* auto_path = NULL;
+ Tcl_Obj* rivet_tcl = NULL;
+ Tcl_Interp* interp = interp_obj->interp;
+
+ ap_assert (interp != (Tcl_Interp *)NULL);
+ Tcl_Preserve (interp);
+
+ /* Set up interpreter associated data */
+
+ globals = apr_pcalloc (p, sizeof(rivet_interp_globals));
+ Tcl_SetAssocData (interp,"rivet",NULL,globals);
+
+ /*
+ * abort_page status variables in globals are set here and then
+ * reset in Rivet_SendContent just before the request processing is
+ * completed
+ */
+
+ /* Rivet commands namespace is created */
+
+ globals->rivet_ns = Tcl_CreateNamespace (interp,RIVET_NS,NULL,
+ (Tcl_NamespaceDeleteProc *)NULL);
+ //globals->req = TclWeb_NewRequestObject (p);
+ //globals->r = NULL;
+ //globals->srec = s;
+
+ /* Eval Rivet's init.tcl file to load in the Tcl-level commands. */
+
+ /* We put in front the auto_path list the path to the directory where
+ * init.tcl is located (provides package Rivet, previously RivetTcl)
+ */
+
+ auto_path = Tcl_GetVar2Ex(interp,"auto_path",NULL,TCL_GLOBAL_ONLY);
+
+ rivet_tcl = Tcl_NewStringObj(RIVET_DIR,-1);
+ Tcl_IncrRefCount(rivet_tcl);
+
+ if (Tcl_IsShared(auto_path)) {
+ auto_path = Tcl_DuplicateObj(auto_path);
+ }
+
+ if (Tcl_ListObjReplace(interp,auto_path,0,0,1,&rivet_tcl) == TCL_ERROR)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+ MODNAME ": error setting auto_path: %s",
+ Tcl_GetStringFromObj(auto_path,NULL));
+ } else {
+ Tcl_SetVar2Ex(interp,"auto_path",NULL,auto_path,TCL_GLOBAL_ONLY);
+ }
+
+ Tcl_DecrRefCount(rivet_tcl);
+
+ /* Initialize the interpreter with Rivet's Tcl commands. */
+
+ if (private == NULL)
+ {
+ /* reduced core for the server init interpreter */
+
+ // RIVET_OBJ_CMD ("inspect",Rivet_InspectCmd,private);
+
+ }
+ else
+ {
+ /* full fledged rivet core */
+
+ Rivet_InitCore(interp,private);
+
+ }
+
+ /* Create a global array with information about the server. */
+ Rivet_InitServerVariables(interp, p );
+
+ /* Loading into the interpreter commands in librivet.so */
+ /* Tcl Bug #3216070 has been solved with 8.5.10 and commands shipped with
+ * Rivetlib can be mapped at this stage
+ */
+
+ if (Tcl_PkgRequire(interp, RIVETLIB_TCL_PACKAGE, RIVET_VERSION, 1) == NULL)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+ MODNAME ": Error loading rivetlib package: %s",
+ Tcl_GetStringResult(interp) );
+ exit(1);
+ }
+
+ /* If rivet is configured to export the ::rivet namespace commands we set the
+ * array variable ::rivet::module_conf(export_namespace_commands) before calling init.tcl
+ * This array will be unset after commands are exported.
+ */
+
+ Tcl_SetVar2Ex(interp,"module_conf","export_namespace_commands",Tcl_NewIntObj(RIVET_NAMESPACE_EXPORT),0);
+ Tcl_SetVar2Ex(interp,"module_conf","import_rivet_commands",Tcl_NewIntObj(RIVET_NAMESPACE_IMPORT),0);
+
+ /* Eval Rivet's init.tcl file to load in the Tcl-level commands. */
+
+ /* Watch out! Calling Tcl_PkgRequire with a version number binds this module to
+ * the Rivet package revision number in rivet/init.tcl
+ *
+ * RIVET_TCL_PACKAGE_VERSION is defined by configure.ac as the combination
+ * "MAJOR_VERSION.MINOR_VERSION". We don't expect to change rivet/init.tcl
+ * across patchlevel releases
+ */
+
+ if (Tcl_PkgRequire(interp, "Rivet", RIVET_INIT_VERSION, 1) == NULL)
+ {
+ ap_log_error (APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+ MODNAME ": init.tcl must be installed correctly for Apache Rivet to function: %s (%s)",
+ Tcl_GetStringResult(interp), RIVET_DIR );
+ exit(1);
+ }
+
+ Tcl_Release(interp);
+ interp_obj->flags |= RIVET_INTERP_INITIALIZED;
+}
+/*
+ * Rivet_CreateCache --
+ *
+ * Arguments:
+ * rsc: pointer to a server_rec structure
+ *
+ * Results:
+ * None
+ *
+ * Side Effects:
+ *
+ */
+
+void Rivet_CreateCache (apr_pool_t *p, rivet_thread_interp* interp_obj)
+{
+ interp_obj->objCacheList = apr_pcalloc(p, (signed)((interp_obj->cache_size)*sizeof(char *)));
+ interp_obj->objCache = apr_pcalloc(p, sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(interp_obj->objCache, TCL_STRING_KEYS);
+}
+
+ /* -- Rivet_NewVHostInterp
+ *
+ * Returns a new rivet_thread_interp object with a new Tcl interpreter
+ * configuration scripts and cache. The pool passed to Rivet_NewVHostInterp
+ *
+ * Arguments:
+ * apr_pool_t* pool: a memory pool, it must be the private pool of a
+ * rivet_thread_private object (thread private)
+ *
+ * Returned value:
+ * a rivet_thread_interp* record object
+ *
+ */
+
+rivet_thread_interp* Rivet_NewVHostInterp(apr_pool_t *pool)
+{
+ extern int ap_max_requests_per_child;
+ rivet_thread_interp* interp_obj = apr_pcalloc(pool,sizeof(rivet_thread_interp));
+ rivet_server_conf* rsc;
+
+ /* The cache size is global so we take it from here */
+
+ rsc = RIVET_SERVER_CONF (module_globals->server->module_config);
+
+ /* This calls needs the root server_rec just for logging purposes*/
+
+ interp_obj->interp = Rivet_CreateTclInterp(module_globals->server);
+
+ /* We now read from the pointers to the cache_size and cache_free conf parameters
+ * for compatibility with mod_rivet current version, but these values must become
+ * integers not pointers
+ */
+
+ 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;
+ }
+
+ /* we now create memory from the cache pool as subpool of the thread private pool */
+
+ if (apr_pool_create(&interp_obj->pool, pool) != APR_SUCCESS)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, module_globals->server,
+ MODNAME ": could not initialize cache private pool");
+ return NULL;
+ }
+
+ // Initialize cache structures
+
+ if (interp_obj->cache_size) {
+ Rivet_CreateCache(pool,interp_obj);
+ }
+
+ interp_obj->flags = 0;
+
+ interp_obj->scripts = (running_scripts *) apr_pcalloc(pool,sizeof(running_scripts));
+ interp_obj->per_dir_scripts = apr_hash_make(pool);
+
+ return interp_obj;
+}
+
+
/*
*-----------------------------------------------------------------------------
*
@@ -147,7 +390,6 @@ rivet_thread_private* Rivet_CreatePrivat
return NULL;
}
private->req_cnt = 0;
- private->keep_going = 1;
private->r = NULL;
private->req = TclWeb_NewRequestObject (private->pool);
private->page_aborting = 0;
@@ -159,14 +401,7 @@ rivet_thread_private* Rivet_CreatePrivat
Tcl_IncrRefCount(private->request_init);
Tcl_IncrRefCount(private->request_cleanup);
-
- /* We allocate the array for the interpreters database.
- * Data referenced in this database must be freed by the thread before exit
- */
-
- private->interps = apr_pcalloc(private->pool,module_globals->vhosts_count*sizeof(rivet_thread_interp));
apr_threadkey_private_set (private,rivet_thread_key);
-
return private;
}
@@ -484,87 +719,4 @@ Rivet_CheckType (request_rec *req)
return ctype;
}
-/*
- * -- Rivet_ProcessorCleanup
- *
- * Thread private data cleanup. This function is called by MPM bridges to
- * release data owned by private and pointed in the array of rivet_thread_interp
- * objects. It has to be called just before an agent, either thread or
- * process, exits.
- *
- * Arguments:
- *
- * data: pointer to a rivet_thread_private data structure.
- *
- * Returned value:
- *
- * none
- *
- * Side effects:
- *
- * resources stored in the array of rivet_thread_interp objects are released
- * and interpreters are deleted.
- *
- */
-
-void Rivet_ProcessorCleanup (void *data)
-{
- rivet_thread_private* private = (rivet_thread_private *) data;
- Tcl_HashSearch* searchCtx;
- Tcl_HashEntry* entry;
- int i;
- rivet_server_conf* rsc = RIVET_SERVER_CONF(module_globals->server->module_config);
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, module_globals->server,
- "Thread exiting after %d requests served (%d vhosts)",
- private->req_cnt,module_globals->vhosts_count);
-
- /* We are deleting the interpreters and release the thread channel.
- * Rivet channel is set as stdout channel of Tcl and as such is treated
- * by Tcl_UnregisterChannel is a special way. When its refCount reaches 1
- * the channel is released immediately by forcing the refCount to 0
- * (see Tcl source code: generic/TclIO.c). Unregistering for each interpreter
- * causes the process to segfault at least for certain Tcl versions.
- * We unset the channel as stdout to avoid this
- */
-
- Tcl_SetStdChannel(NULL,TCL_STDOUT);
-
- /* there must be always a root interpreter in the slot 0 of private->interps,
- so there is always need to run at least one cycle here */
-
- i = 0;
- do
- {
-
- /* cleaning the cache contents and deleting it */
-
- searchCtx = apr_pcalloc(private->pool,sizeof(Tcl_HashSearch));
- entry = Tcl_FirstHashEntry(private->interps[i]->objCache,searchCtx);
- while (entry)
- {
- Tcl_DecrRefCount(Tcl_GetHashValue(entry)); /* Let Tcl clear the mem allocated */
- Tcl_DeleteHashEntry(entry);
-
- entry = Tcl_NextHashEntry(searchCtx);
- }
-
- if ((i > 0) && rsc->separate_channels)
- Rivet_ReleaseRivetChannel(private->interps[i]->interp,private->channel);
-
- Tcl_DeleteInterp(private->interps[i]->interp);
-
- /* if separate_virtual_interps == 0 we are running the same interpreter
- * instance for each vhost, thus we can jump out of this loop after
- * the first cycle as the only real intepreter object we have is stored
- * in private->interps[0]
- */
-
- } while ((++i < module_globals->vhosts_count) && rsc->separate_virtual_interps);
-
- Tcl_DecrRefCount(private->request_init);
- Tcl_DecrRefCount(private->request_cleanup);
- apr_pool_destroy(private->pool);
-
-}
Modified: tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.h?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.h (original)
+++ tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.h Sat Dec 26 00:22:11 2015
@@ -21,7 +21,10 @@
#ifndef _MOD_RIVET_COMMON_
#define _MOD_RIVET_COMMON_
-
+EXTERN running_scripts* Rivet_RunningScripts (apr_pool_t* pool,running_scripts* scripts,rivet_server_conf* rivet_conf);
+EXTERN void Rivet_PerInterpInit(rivet_thread_interp* interp_obj,rivet_thread_private* private, server_rec *s, apr_pool_t *p);
+EXTERN void Rivet_CreateCache (apr_pool_t *p, rivet_thread_interp* interp_obj);
+EXTERN rivet_thread_interp* Rivet_NewVHostInterp(apr_pool_t *pool);
EXTERN void Rivet_ProcessorCleanup (void *data);
EXTERN int Rivet_chdir_file (const char *file);
EXTERN int Rivet_CheckType (request_rec* r);
Modified: tcl/rivet/trunk/src/mod_rivet/rivetCore.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/rivetCore.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/rivetCore.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/rivetCore.c Sat Dec 26 00:22:11 2015
@@ -60,6 +60,11 @@ extern apr_threadkey_t* rivet_thread_ke
#define POOL (private->r->pool)
+ /* define a convenience macro to cast the ClientData
+ * into the thread private data pointer */
+
+#define THREAD_PRIVATE_DATA(p) p = (rivet_thread_private *)clientData;
+
/*
* -- Rivet_NoRequestRec
*
@@ -122,7 +127,7 @@ TCL_CMD_HEADER( Rivet_MakeURL )
CHECK_REQUEST_REC(private,"::rivet::makeurl")
if (objc == 1)
{
- url_target_name = TclWeb_GetEnvVar (private->req,"SCRIPT_NAME");
+ url_target_name = TclWeb_GetEnvVar (private,"SCRIPT_NAME");
}
else
{
@@ -135,7 +140,7 @@ TCL_CMD_HEADER( Rivet_MakeURL )
if (url_target_name[0] != '/')
{
/* relative path */
- char* script_name = TclWeb_GetEnvVar (private->req,"SCRIPT_NAME");
+ char* script_name = TclWeb_GetEnvVar (private,"SCRIPT_NAME");
int script_name_l = strlen(script_name);
// regardless the reason for a SCRIPT_NAME being undefined we
@@ -498,7 +503,7 @@ TCL_CMD_HEADER( Rivet_LoadEnv )
ArrayObj = Tcl_NewStringObj( ENV_ARRAY_NAME, -1 );
}
- return TclWeb_GetEnvVars(ArrayObj,private->req);
+ return TclWeb_GetEnvVars(ArrayObj,private);
}
/*
@@ -537,7 +542,7 @@ TCL_CMD_HEADER ( Rivet_LoadHeaders )
ArrayObj = Tcl_NewStringObj( HEADERS_ARRAY_NAME, -1 );
}
- return TclWeb_GetHeaderVars(ArrayObj,private->req);
+ return TclWeb_GetHeaderVars(ArrayObj,private);
}
/* Tcl command to return a particular variable. */
@@ -1309,7 +1314,7 @@ TCL_CMD_HEADER( Rivet_EnvCmd )
key = Tcl_GetStringFromObj( objv[1], NULL );
- val = TclWeb_GetEnvVar( private->req, key );
+ val = TclWeb_GetEnvVar( private, key );
Tcl_SetObjResult(interp, Tcl_NewStringObj( val, -1 ) );
return TCL_OK;
Added: tcl/rivet/trunk/src/mod_rivet/rivetCore.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/rivetCore.h?rev=1721698&view=auto
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/rivetCore.h (added)
+++ tcl/rivet/trunk/src/mod_rivet/rivetCore.h Sat Dec 26 00:22:11 2015
@@ -0,0 +1,28 @@
+/* rivetCore.h -- Core commands which are compiled into mod_rivet itself */
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/* $Id: rivetCore.c 1718131 2015-12-05 22:58:33Z mxmanghi $ */
+
+#ifndef __rivetcore_h__
+#define __rivetcore_h__
+int Rivet_InitCore(Tcl_Interp *interp,rivet_thread_private* private);
+#endif
+
Modified: tcl/rivet/trunk/src/mod_rivet/rivet_lazy_mpm.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/rivet_lazy_mpm.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/rivet_lazy_mpm.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/rivet_lazy_mpm.c Sat Dec 26 00:22:11 2015
@@ -19,7 +19,7 @@
under the License.
*/
-/* $Id: */
+/* $Id$ */
#include <httpd.h>
#include <http_request.h>
@@ -39,7 +39,6 @@ extern mod_rivet_globals* module_globa
extern apr_threadkey_t* rivet_thread_key;
extern apr_threadkey_t* handler_thread_key;
-rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private);
rivet_thread_interp* Rivet_NewVHostInterp(apr_pool_t* pool);
enum
@@ -58,7 +57,7 @@ typedef struct lazy_tcl_worker {
apr_thread_cond_t* condition2;
int status;
apr_thread_t* thread_id;
- int idx;
+ server_rec* server;
request_rec* r;
int ctype;
int ap_sts;
@@ -67,7 +66,6 @@ typedef struct lazy_tcl_worker {
typedef struct vhost_iface {
apr_uint32_t* idle_threads_cnt; /* */
- //apr_queue_t* queue; /* available threads */
apr_thread_mutex_t* mutex;
apr_array_header_t* array; /* available threads */
} vhost;
@@ -81,6 +79,15 @@ typedef struct mpm_bridge_status {
vhost* vhosts;
} mpm_bridge_status;
+typedef struct mpm_bridge_specific {
+ rivet_thread_interp* interp; /* thread Tcl interpreter object */
+ rivet_server_conf* conf; /* rivet_server_conf* record */
+ int keep_going; /* thread loop controlling variable */
+ /* the request_rec and TclWebRequest *
+ * are copied here to be passed to a *
+ * channel */
+} mpm_bridge_specific;
+
#define DEFAULT_HEADER_TYPE "text/html"
#define BASIC_PAGE "<b>Lazy Bridge</b>"
@@ -89,38 +96,96 @@ typedef struct mpm_bridge_status {
static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
{
lazy_tcl_worker* w = (lazy_tcl_worker*) data;
+ rivet_thread_private* private;
+ void* function;
+ private = Rivet_CreatePrivateData();
+ if (private == NULL)
+ {
+ /* TODO: we have to log something here */
+ apr_thread_exit(thd,APR_SUCCESS);
+ }
+ private->channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
+ Rivet_SetupTclPanicProc ();
+
+ private->ext = apr_pcalloc(private->pool,sizeof(mpm_bridge_specific));
+ private->ext->keep_going = 1;
+ private->ext->interp = Rivet_NewVHostInterp(private->pool);
+ private->ext->interp->channel = private->channel;
+ private->ext->conf = RIVET_SERVER_CONF(w->server->module_config);
w->nreqs = 0;
+ Tcl_RegisterChannel(private->ext->interp->interp,*private->channel);
+
+ Rivet_PerInterpInit(private->ext->interp,private,module_globals->server,private->pool);
+
+ function = private->ext->conf->rivet_child_init_script;
+ if (function)
+ {
+ char* errmsg = "rivet_lazy_mpm.so: Error in thread initialization init script: %s";
+ Tcl_Obj* tcl_child_init = Tcl_NewStringObj(function,-1);
+ Tcl_Interp* interp = private->ext->interp->interp;
+
+ Tcl_IncrRefCount(tcl_child_init);
+
+ if (Tcl_EvalObjEx(interp,tcl_child_init, 0) != TCL_OK)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, w->server,
+ errmsg, function);
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, w->server,
+ "errorCode: %s", Tcl_GetVar(interp, "errorCode", 0));
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, w->server,
+ "errorInfo: %s", Tcl_GetVar(interp, "errorInfo", 0));
+ apr_thread_mutex_lock(w->mutex2);
+ w->status = done;
+ w->ap_sts = HTTP_INTERNAL_SERVER_ERROR;
+ apr_thread_cond_signal(w->condition2);
+ apr_thread_mutex_unlock(w->mutex2);
+
+ /* This is broken: there must be a way to tell the array of
+ * available threads this thread is about to exit, otherwise
+ * it would be impossible to implement the exit command in the
+ * way we did for prefork and worker bridges */
+
+ apr_thread_exit(thd,APR_SUCCESS);
+ return NULL;
+ }
+
+ Tcl_DecrRefCount(tcl_child_init);
+ }
+
do
{
- char* page;
+ //char* page;
+ int http_code;
+ int idx = private->ext->conf->idx;
apr_thread_mutex_lock(w->mutex1);
- //apr_queue_push(module_globals->mpm->vhosts[w->idx].queue,w);
- apr_atomic_inc32(module_globals->mpm->vhosts[w->idx].idle_threads_cnt);
+ apr_atomic_inc32(module_globals->mpm->vhosts[idx].idle_threads_cnt);
while (w->status != init) {
apr_thread_cond_wait(w->condition1,w->mutex1);
}
w->status = processing;
+ w->nreqs++;
apr_thread_mutex_unlock(w->mutex1);
- apr_atomic_dec32(module_globals->mpm->vhosts[w->idx].idle_threads_cnt);
+ apr_atomic_dec32(module_globals->mpm->vhosts[idx].idle_threads_cnt);
/* Content generation */
+ http_code = Rivet_SendContent(private,w->r);
+
+ /*
ap_set_content_type(w->r,apr_pstrdup(w->r->pool,DEFAULT_HEADER_TYPE));
ap_send_http_header(w->r);
- //ap_rwrite(apr_pstrdup(w->r->pool,BASIC_PAGE),strlen(BASIC_PAGE),w->r);
-
- page = apr_psprintf(w->r->pool,"%s: vh %d, idle threads: %d, nreqs: %d",BASIC_PAGE,w->idx,
- (int) apr_atomic_read32(module_globals->mpm->vhosts[w->idx].idle_threads_cnt),++(w->nreqs));
-
+ page = apr_psprintf(w->r->pool,"%s: vh %d, idle threads: %d, nreqs: %d",BASIC_PAGE,idx,
+ (int) apr_atomic_read32(module_globals->mpm->vhosts[idx].idle_threads_cnt),w->nreqs);
ap_rwrite(page,strlen(page),w->r);
ap_rflush(w->r);
+ */
apr_thread_mutex_lock(w->mutex2);
w->status = done;
- w->ap_sts = OK;
+ w->ap_sts = http_code;
apr_thread_cond_signal(w->condition2);
apr_thread_mutex_unlock(w->mutex2);
@@ -132,23 +197,23 @@ static void* APR_THREAD_FUNC request_pro
// rescheduling itself in the array of idle threads
- apr_thread_mutex_lock(module_globals->mpm->vhosts[w->idx].mutex);
- *(lazy_tcl_worker **) apr_array_push(module_globals->mpm->vhosts[w->idx].array) = w;
- apr_thread_mutex_unlock(module_globals->mpm->vhosts[w->idx].mutex);
+ apr_thread_mutex_lock(module_globals->mpm->vhosts[idx].mutex);
+ *(lazy_tcl_worker **) apr_array_push(module_globals->mpm->vhosts[idx].array) = w;
+ apr_thread_mutex_unlock(module_globals->mpm->vhosts[idx].mutex);
- } while (1);
+ } while (private->ext->keep_going);
return NULL;
}
-static lazy_tcl_worker* create_worker (apr_pool_t* pool,int idx)
+static lazy_tcl_worker* create_worker (apr_pool_t* pool,server_rec* server)
{
lazy_tcl_worker* w;
w = apr_pcalloc(pool,sizeof(lazy_tcl_worker));
w->status = idle;
- w->idx = idx;
+ w->server = server;
ap_assert(apr_thread_mutex_create(&w->mutex1,APR_THREAD_MUTEX_UNNESTED,pool) == APR_SUCCESS);
ap_assert(apr_thread_cond_create(&w->condition1, pool) == APR_SUCCESS);
ap_assert(apr_thread_mutex_create(&w->mutex2,APR_THREAD_MUTEX_UNNESTED,pool) == APR_SUCCESS);
@@ -161,28 +226,27 @@ static lazy_tcl_worker* create_worker (a
void Lazy_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
{
apr_status_t rv;
- int vh;
+ server_rec* s;
+ server_rec* root_server = module_globals->server;
module_globals->mpm = apr_pcalloc(pool,sizeof(mpm_bridge_status));
- //module_globals->mpm->vhosts = (vhost *) apr_pcalloc(pool,sizeof(vhost) * module_globals->vhosts_count);
-
rv = apr_thread_mutex_create(&module_globals->mpm->mutex,APR_THREAD_MUTEX_UNNESTED,pool);
ap_assert(rv == APR_SUCCESS);
rv = apr_thread_cond_create(&module_globals->mpm->condition, pool);
ap_assert(rv == APR_SUCCESS);
- /*
- apr_atomic_set32(module_globals->mpm->first_available,0);
- */
-
module_globals->mpm->vhosts = (vhost *) apr_pcalloc(pool,module_globals->vhosts_count * sizeof(vhost));
ap_assert(module_globals->mpm->vhosts != NULL);
- for (vh = 0; vh < module_globals->vhosts_count; vh++)
+ //for (vh = 0; vh < module_globals->vhosts_count; vh++)
+ for (s = root_server; s != NULL; s = s->next)
{
+ int vh;
apr_array_header_t* array;
+ rivet_server_conf* rsc = RIVET_SERVER_CONF(s->module_config);
+ vh = rsc->idx;
ap_assert(apr_thread_mutex_create(&module_globals->mpm->vhosts[vh].mutex,APR_THREAD_MUTEX_UNNESTED,pool) == APR_SUCCESS);
array = apr_array_make(pool,0,sizeof(void*));
ap_assert(array != NULL);
@@ -191,16 +255,11 @@ void Lazy_MPM_ChildInit (apr_pool_t* poo
//ap_assert(apr_queue_create(&module_globals->mpm->vhosts[vh].queue,MOD_RIVET_QUEUE_SIZE,pool) == APR_SUCCESS);
module_globals->mpm->vhosts[vh].idle_threads_cnt = (apr_uint32_t *) apr_pcalloc(pool,sizeof(apr_uint32_t));
apr_atomic_set32(module_globals->mpm->vhosts[vh].idle_threads_cnt,0);
-
- //create_worker(pool,vh);
- //create_worker(pool,vh);
}
}
int Lazy_MPM_Request (request_rec* r,rivet_req_ctype ctype)
{
- //void* v;
- //apr_status_t rv;
lazy_tcl_worker* w;
int ap_sts;
rivet_server_conf* conf = RIVET_SERVER_CONF(r->server->module_config);
@@ -219,7 +278,7 @@ int Lazy_MPM_Request (request_rec* r,riv
apr_thread_mutex_lock(mutex);
if (apr_is_empty_array(array))
{
- w = create_worker(module_globals->pool,conf->idx);
+ w = create_worker(module_globals->pool,r->server);
}
else
{
@@ -231,7 +290,6 @@ int Lazy_MPM_Request (request_rec* r,riv
w->r = r;
w->ctype = ctype;
w->status = init;
- w->idx = conf->idx;
apr_thread_cond_signal(w->condition1);
apr_thread_mutex_unlock(w->mutex1);
@@ -251,9 +309,10 @@ int Lazy_MPM_Request (request_rec* r,riv
return ap_sts;
}
-rivet_thread_interp* Lazy_MPM_MasterInterp(void)
+rivet_thread_interp* Lazy_MPM_Interp(rivet_thread_private *private,
+ rivet_server_conf* conf)
{
- return NULL;
+ return private->ext->interp;
}
RIVET_MPM_BRIDGE {
@@ -261,6 +320,7 @@ RIVET_MPM_BRIDGE {
Lazy_MPM_ChildInit,
Lazy_MPM_Request,
NULL,
- Lazy_MPM_MasterInterp,
- NULL
+ NULL,
+ NULL,
+ Lazy_MPM_Interp
};
Modified: tcl/rivet/trunk/src/mod_rivet/rivet_prefork_mpm.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/rivet_prefork_mpm.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/rivet_prefork_mpm.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/rivet_prefork_mpm.c Sat Dec 26 00:22:11 2015
@@ -29,14 +29,17 @@
#include "rivetChannel.h"
#include "apache_config.h"
#include "rivet.h"
+#include "rivetCore.h"
extern mod_rivet_globals* module_globals;
extern apr_threadkey_t* rivet_thread_key;
-int Rivet_InitCore (Tcl_Interp *interp,rivet_thread_private* p);
+rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private);
+rivet_thread_interp* Rivet_NewVHostInterp(apr_pool_t* pool);
-rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private);
-rivet_thread_interp* Rivet_NewVHostInterp(apr_pool_t* pool);
+/* typedef struct mpm_bridge_specific {
+ rivet_thread_interp** interps;
+} mpm_bridge_specific; */
/* -- Prefork_MPM_Finalize */
@@ -69,7 +72,9 @@ void Prefork_MPM_ChildInit (apr_pool_t*
*/
private = Rivet_CreatePrivateData();
-
+ //private->ext = apr_pcalloc(private->pool,sizeof(mpm_bridge_specific));
+ private->interps = apr_pcalloc(private->pool,module_globals->vhosts_count*sizeof(rivet_thread_interp));
+
Rivet_SetupTclPanicProc ();
ap_assert(private != NULL);
@@ -161,12 +166,18 @@ int Prefork_MPM_ExitHandler(int code)
return TCL_OK;
}
+rivet_thread_interp* Prefork_MPM_Interp(rivet_thread_private *private,rivet_server_conf* conf)
+{
+ return private->interps[conf->idx];
+}
+
RIVET_MPM_BRIDGE {
NULL,
Prefork_MPM_ChildInit,
Prefork_MPM_Request,
Prefork_MPM_Finalize,
Prefork_MPM_MasterInterp,
- Prefork_MPM_ExitHandler
+ Prefork_MPM_ExitHandler,
+ Prefork_MPM_Interp
};
Modified: tcl/rivet/trunk/src/mod_rivet/rivet_worker_mpm.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/rivet_worker_mpm.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/rivet_worker_mpm.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/rivet_worker_mpm.c Sat Dec 26 00:22:11 2015
@@ -76,6 +76,13 @@ typedef struct mpm_bridge_status {
#endif
} mpm_bridge_status;
+/* This object is thread specific */
+
+typedef struct mpm_bridge_specific {
+ int keep_going; /* thread loop controlling variable */
+} mpm_bridge_specific;
+
+
/* data private to the Apache callback handling the request */
typedef struct _handler_private
@@ -177,10 +184,15 @@ static void* APR_THREAD_FUNC request_pro
apr_thread_mutex_lock(module_globals->mpm->job_mutex);
private = Rivet_CreatePrivateData();
+ private->interps = apr_pcalloc(private->pool,module_globals->vhosts_count*sizeof(rivet_thread_interp));
+ private->ext = apr_pcalloc(private->pool,sizeof(mpm_bridge_specific));
+ private->ext->keep_going = 1;
+
if (private == NULL)
{
/* TODO: we have to log something here */
apr_thread_exit(thd,APR_SUCCESS);
+ return NULL;
}
private->channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
Rivet_SetupTclPanicProc ();
@@ -239,7 +251,7 @@ static void* APR_THREAD_FUNC request_pro
request_obj = (handler_private *) v;
if (request_obj->job_type == orderly_exit)
{
- private->keep_going = 0;
+ private->ext->keep_going = 0;
continue;
}
@@ -265,7 +277,7 @@ static void* APR_THREAD_FUNC request_pro
private->req_cnt++;
apr_atomic_dec32(module_globals->mpm->running_threads_count);
- } while (private->keep_going > 0);
+ } while (private->ext->keep_going > 0);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, module_globals->server, "processor thread orderly exit");
@@ -760,7 +772,7 @@ int Worker_MPM_ExitHandler(int code)
/* This will force the current thread to exit */
- private->keep_going = 0;
+ private->ext->keep_going = 0;
module_globals->mpm->exit_command = 1;
module_globals->mpm->exit_command_status = code;
@@ -772,11 +784,18 @@ int Worker_MPM_ExitHandler(int code)
return TCL_OK;
}
+rivet_thread_interp* Worker_MPM_Interp(rivet_thread_private *private,
+ rivet_server_conf *conf)
+{
+ return private->interps[conf->idx];
+}
+
RIVET_MPM_BRIDGE {
NULL,
Worker_MPM_ChildInit,
Worker_MPM_Request,
Worker_MPM_Finalize,
Worker_MPM_MasterInterp,
- Worker_MPM_ExitHandler
+ Worker_MPM_ExitHandler,
+ Worker_MPM_Interp
};
Added: tcl/rivet/trunk/src/mod_rivet/worker_prefork_common.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/worker_prefork_common.c?rev=1721698&view=auto
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/worker_prefork_common.c (added)
+++ tcl/rivet/trunk/src/mod_rivet/worker_prefork_common.c Sat Dec 26 00:22:11 2015
@@ -0,0 +1,314 @@
+/* worker_prefork_common.c: function common to both the prefork and worker bridges */
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+/* $Id: rivet_prefork_mpm.c 1719851 2015-12-14 00:50:43Z mxmanghi $ */
+
+#include <httpd.h>
+#include <apr_strings.h>
+#include "mod_rivet.h"
+#include "mod_rivet_common.h"
+
+extern mod_rivet_globals* module_globals;
+extern apr_threadkey_t* rivet_thread_key;
+
+/*
+ * Rivet_DuplicateVhostInterp
+ *
+ *
+ */
+
+static rivet_thread_interp*
+Rivet_DuplicateVHostInterp(apr_pool_t* pool, rivet_thread_interp* source_obj)
+{
+ rivet_thread_interp* interp_obj = apr_pcalloc(pool,sizeof(rivet_thread_interp));
+
+ interp_obj->interp = source_obj->interp;
+ interp_obj->channel = source_obj->channel;
+ interp_obj->cache_free = source_obj->cache_free;
+ interp_obj->cache_size = source_obj->cache_size;
+
+ /* TODO: decouple cache by creating a new cache object */
+
+ if (interp_obj->cache_size) {
+ Rivet_CreateCache(pool,interp_obj);
+ }
+
+ interp_obj->pool = source_obj->pool;
+ interp_obj->scripts = (running_scripts *) apr_pcalloc(pool,sizeof(running_scripts));
+ interp_obj->per_dir_scripts = apr_hash_make(pool);
+ interp_obj->flags = source_obj->flags;
+ return interp_obj;
+}
+
+/* -- Rivet_VirtualHostsInterps
+ *
+ * The server_rec chain is walked through and server configurations is read to
+ * set up the thread private configuration and interpreters database
+ *
+ * Arguments:
+ *
+ * rivet_thread_private* private;
+ *
+ * Returned value:
+ *
+ * a new rivet_thread_private object
+ *
+ * Side effects:
+ *
+ * GlobalInitScript and ChildInitScript are run at this stage
+ *
+ */
+
+rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private)
+{
+ server_rec* s;
+ server_rec* root_server = module_globals->server;
+ rivet_server_conf* root_server_conf;
+ rivet_server_conf* myrsc;
+ rivet_thread_interp* root_interp;
+ void* parentfunction; /* this is topmost initialization script */
+ void* function;
+
+ root_server_conf = RIVET_SERVER_CONF (root_server->module_config);
+
+ ap_assert(RIVET_MPM_BRIDGE_FUNCTION(mpm_master_interp) != NULL);
+ root_interp = (*RIVET_MPM_BRIDGE_FUNCTION(mpm_master_interp))();
+
+ /* we must assume the module was able to create the root interprter otherwise
+ * it's just a null module. I try to have also this case to develop experimental
+ * bridges without the Tcl stuff
+ */
+
+ //if (root_interp == NULL) return private;
+
+ ap_assert (root_interp != NULL);
+
+ /* Using the root interpreter we evaluate the global initialization script, if any */
+
+ if (root_server_conf->rivet_global_init_script != NULL)
+ {
+ Tcl_Obj* global_tcl_script;
+
+ global_tcl_script = Tcl_NewStringObj(root_server_conf->rivet_global_init_script,-1);
+ Tcl_IncrRefCount(global_tcl_script);
+ if (Tcl_EvalObjEx(root_interp->interp, global_tcl_script, 0) != TCL_OK)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, module_globals->server,
+ MODNAME ": Error running GlobalInitScript '%s': %s",
+ root_server_conf->rivet_global_init_script,
+ Tcl_GetVar(root_interp->interp, "errorInfo", 0));
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, module_globals->server,
+ MODNAME ": GlobalInitScript '%s' successful",
+ root_server_conf->rivet_global_init_script);
+ }
+ Tcl_DecrRefCount(global_tcl_script);
+ }
+
+ /* then we proceed assigning/creating the interpreters for the
+ * virtual hosts known to the server
+ */
+
+ parentfunction = root_server_conf->rivet_child_init_script;
+
+ for (s = root_server; s != NULL; s = s->next)
+ {
+ rivet_thread_interp* rivet_interp;
+
+ myrsc = RIVET_SERVER_CONF(s->module_config);
+
+ /* by default we assign the root_interpreter as
+ * interpreter of the virtual host. In case of separate
+ * virtual interpreters we create new ones for each
+ * virtual host
+ */
+
+ rivet_interp = root_interp;
+
+ if (s == root_server)
+ {
+ Tcl_RegisterChannel(rivet_interp->interp,*rivet_interp->channel);
+ }
+ else
+ {
+ if (root_server_conf->separate_virtual_interps)
+ {
+ rivet_interp = Rivet_NewVHostInterp(private->pool);
+ if (myrsc->separate_channels)
+ {
+ rivet_interp->channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
+ Tcl_RegisterChannel(rivet_interp->interp,*rivet_interp->channel);
+ }
+ else
+ {
+ rivet_interp->channel = private->channel;
+ }
+ }
+ else
+ {
+ rivet_interp = Rivet_DuplicateVHostInterp(private->pool,root_interp);
+ }
+ }
+
+ /* interpreter base running scripts definition and initialization */
+
+ rivet_interp->scripts = Rivet_RunningScripts (private->pool,rivet_interp->scripts,myrsc);
+
+ private->interps[myrsc->idx] = rivet_interp;
+
+ /* Basic Rivet packages and libraries are loaded here */
+
+ if ((rivet_interp->flags & RIVET_INTERP_INITIALIZED) == 0)
+ {
+ Rivet_PerInterpInit(rivet_interp, private, root_server, private->pool);
+ }
+
+ /* TODO: check if it's absolutely necessary to lock the pool_mutex in order
+ * to allocate from the module global pool
+ */
+
+ /* this stuff must be allocated from the module global pool which
+ * has the child process' same lifespan
+ */
+
+ apr_thread_mutex_lock(module_globals->pool_mutex);
+ myrsc->server_name = (char*) apr_pstrdup (private->pool, s->server_hostname);
+ apr_thread_mutex_unlock(module_globals->pool_mutex);
+
+ /* when configured a child init script gets evaluated */
+
+ function = myrsc->rivet_child_init_script;
+ if (function &&
+ (s == root_server || root_server_conf->separate_virtual_interps || function != parentfunction))
+ {
+ char* errmsg = MODNAME ": Error in Child init script: %s";
+ Tcl_Interp* interp = rivet_interp->interp;
+ Tcl_Obj* tcl_child_init = Tcl_NewStringObj(function,-1);
+
+ Tcl_IncrRefCount(tcl_child_init);
+ Tcl_Preserve (interp);
+
+ /* There is a lot of passing around of pointers among various record
+ * objects. We should understand if this is all that necessary.
+ * Here we assign the server_rec pointer to the interpreter which
+ * is wrong, because without separate interpreters it doens't make
+ * any sense. TODO
+ */
+
+ if (Tcl_EvalObjEx(interp,tcl_child_init, 0) != TCL_OK) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server,
+ errmsg, function);
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server,
+ "errorCode: %s", Tcl_GetVar(interp, "errorCode", 0));
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server,
+ "errorInfo: %s", Tcl_GetVar(interp, "errorInfo", 0));
+ }
+ Tcl_Release (interp);
+ Tcl_DecrRefCount(tcl_child_init);
+ }
+ }
+ return private;
+}
+
+
+/*
+ * -- Rivet_ProcessorCleanup
+ *
+ * Thread private data cleanup. This function is called by MPM bridges to
+ * release data owned by private and pointed in the array of rivet_thread_interp
+ * objects. It has to be called just before an agent, either thread or
+ * process, exits. We aren't calling this function anymore as we rely entirely
+ * on the child process termination
+ *
+ * Arguments:
+ *
+ * data: pointer to a rivet_thread_private data structure.
+ *
+ * Returned value:
+ *
+ * none
+ *
+ * Side effects:
+ *
+ * resources stored in the array of rivet_thread_interp objects are released
+ * and interpreters are deleted.
+ *
+ */
+
+void Rivet_ProcessorCleanup (void *data)
+{
+ rivet_thread_private* private = (rivet_thread_private *) data;
+ Tcl_HashSearch* searchCtx;
+ Tcl_HashEntry* entry;
+ int i;
+ rivet_server_conf* rsc = RIVET_SERVER_CONF(module_globals->server->module_config);
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, module_globals->server,
+ "Thread exiting after %d requests served (%d vhosts)",
+ private->req_cnt,module_globals->vhosts_count);
+
+ /* We are deleting the interpreters and release the thread channel.
+ * Rivet channel is set as stdout channel of Tcl and as such is treated
+ * by Tcl_UnregisterChannel is a special way. When its refCount reaches 1
+ * the channel is released immediately by forcing the refCount to 0
+ * (see Tcl source code: generic/TclIO.c). Unregistering for each interpreter
+ * causes the process to segfault at least for certain Tcl versions.
+ * We unset the channel as stdout to avoid this
+ */
+
+ Tcl_SetStdChannel(NULL,TCL_STDOUT);
+
+ /* there must be always a root interpreter in the slot 0 of private->interps,
+ so there is always need to run at least one cycle here */
+
+ i = 0;
+ do
+ {
+
+ /* cleaning the cache contents and deleting it */
+
+ searchCtx = apr_pcalloc(private->pool,sizeof(Tcl_HashSearch));
+ entry = Tcl_FirstHashEntry(private->interps[i]->objCache,searchCtx);
+ while (entry)
+ {
+ Tcl_DecrRefCount(Tcl_GetHashValue(entry)); /* Let Tcl clear the mem allocated */
+ Tcl_DeleteHashEntry(entry);
+
+ entry = Tcl_NextHashEntry(searchCtx);
+ }
+
+ if ((i > 0) && rsc->separate_channels)
+ Rivet_ReleaseRivetChannel(private->interps[i]->interp,private->channel);
+
+ Tcl_DeleteInterp(private->interps[i]->interp);
+
+ /* if separate_virtual_interps == 0 we are running the same interpreter
+ * instance for each vhost, thus we can jump out of this loop after
+ * the first cycle as the only real intepreter object we have is stored
+ * in private->ext->interps[0]
+ */
+
+ } while ((++i < module_globals->vhosts_count) && rsc->separate_virtual_interps);
+
+ Tcl_DecrRefCount(private->request_init);
+ Tcl_DecrRefCount(private->request_cleanup);
+ apr_pool_destroy(private->pool);
+}
Modified: tcl/rivet/trunk/src/rivet.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/rivet.h?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/rivet.h (original)
+++ tcl/rivet/trunk/src/rivet.h Sat Dec 26 00:22:11 2015
@@ -59,11 +59,6 @@ static int cmd(\
int objc,\
Tcl_Obj *CONST objv[])
- /* we also define a convenience macro to cast the ClientData
- * into the thread private data pointer */
-
-#define THREAD_PRIVATE_DATA(p) p = (rivet_thread_private *)clientData;
-
#define TCL_OBJ_CMD( name, func ) \
Tcl_CreateObjCommand( interp, /* Tcl interpreter */\
name, /* Function name in Tcl */\
---------------------------------------------------------------------
To unsubscribe, e-mail: site-cvs-unsubscribe@tcl.apache.org
For additional commands, e-mail: site-cvs-help@tcl.apache.org