You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tcl.apache.org by mx...@apache.org on 2019/01/22 00:17:46 UTC
[tcl-rivet] branch quattuor updated: now committing real first
draft of mod_rivet 4
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
The following commit(s) were added to refs/heads/quattuor by this push:
new 89628d6 now committing real first draft of mod_rivet 4
89628d6 is described below
commit 89628d67d74e6b2183ce0e6e9186c2c0a8ed4f40
Author: Massimo Manghi <mx...@apache.org>
AuthorDate: Tue Jan 22 01:17:29 2019 +0100
now committing real first draft of mod_rivet 4
---
ChangeLog | 3 +
src/TclWeb.h | 25 ++++-
src/mod_rivet_ng/TclWebapache.c | 2 -
src/mod_rivet_ng/mod_rivet.c | 86 ++++++++---------
src/mod_rivet_ng/mod_rivet_common.c | 96 ++++++++++++++++++-
src/mod_rivet_ng/mod_rivet_common.h | 20 ++--
src/mod_rivet_ng/rivet_prefork_mpm.c | 157 +++++++++++++------------------
src/mod_rivet_ng/rivet_worker_mpm.c | 85 ++++++++++++-----
src/mod_rivet_ng/worker_prefork_common.c | 122 +++++-------------------
src/mod_rivet_ng/worker_prefork_common.h | 1 +
src/rivet.h | 51 +++++++++-
11 files changed, 360 insertions(+), 288 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index f5dc5f0..3c15543 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,7 @@
2019-01-21 Massimo Manghi <mx...@apache.org>
+ * src/mod_rivet_ng/*: first draft version that compiles and runs with prefork
+
+2019-01-21 Massimo Manghi <mx...@apache.org>
* src/rivet.h: Add error message buffer size definition (was still hardcoded
here and there)
diff --git a/src/TclWeb.h b/src/TclWeb.h
index 899eab9..dffec44 100644
--- a/src/TclWeb.h
+++ b/src/TclWeb.h
@@ -1,5 +1,26 @@
-#ifndef TCLWEB_H
-#define TCLWEB_H
+/* -- TclWeb.h: Common API layer
+
+ 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.
+*/
+
+
+#ifndef __tclweb_h__
+#define __tclweb_h__
#include <tcl.h>
#include "apache_request.h"
diff --git a/src/mod_rivet_ng/TclWebapache.c b/src/mod_rivet_ng/TclWebapache.c
index 2446072..d755507 100644
--- a/src/mod_rivet_ng/TclWebapache.c
+++ b/src/mod_rivet_ng/TclWebapache.c
@@ -19,8 +19,6 @@
under the License.
*/
-/* $Id$ */
-
/* Rivet config */
#ifdef HAVE_CONFIG_H
diff --git a/src/mod_rivet_ng/mod_rivet.c b/src/mod_rivet_ng/mod_rivet.c
index f23f7ad..36df39f 100644
--- a/src/mod_rivet_ng/mod_rivet.c
+++ b/src/mod_rivet_ng/mod_rivet.c
@@ -4,7 +4,7 @@
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
+ 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
@@ -62,6 +62,7 @@
#include "rivet.h"
#include "mod_rivet_common.h"
#include "mod_rivet_generator.h"
+#include "rivetCore.h"
/*
* Macros DLLIMPORT and DLLEXPORT are defined in tcl.h
@@ -211,11 +212,6 @@ Rivet_CreateModuleGlobals (apr_pool_t* pool, server_rec* server)
exit(1);
}
- /* We cannot assume we are running in an OS with a fork system call
- * therefore we have to check module_globals in order to establish if the
- * structure has to be allocated
- */
-
mod_rivet_g->server = server;
return mod_rivet_g;
@@ -248,9 +244,28 @@ Rivet_RunServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, ser
server_rec* s;
int idx;
rivet_thread_private* private;
+ rivet_thread_interp* root_interp = NULL;
FILEDEBUGINFO;
+ /* In order to know the size of the server_interps array we need
+ * to count the virtual hosts. This is an extra work to do
+ * but it's done only once
+ */
+
+ idx = 0;
+ for (s = server; s != NULL; s = s->next)
+ {
+ rivet_server_conf* vhost_rsc;
+
+ vhost_rsc = RIVET_SERVER_CONF(s->module_config);
+ vhost_rsc->idx = idx++;
+
+ vhost_rsc->server_name = (char*) apr_pstrdup (pPool,s->server_hostname);
+ }
+ module_globals->vhosts_count = idx;
+ module_globals->server_interps = apr_pcalloc(pPool,module_globals->vhosts_count*sizeof(rivet_thread_interp));
+
#ifdef WIN32
/* This code conditionally compiled when we are building for the
@@ -292,22 +307,6 @@ Rivet_RunServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, ser
Rivet_SetupTclPanicProc();
- /* In order to know the size of the server_interps array we need
- * to count the virtual hosts. This is an extra work to do
- * but it's done only once
- */
-
- idx = 0;
- for (s = server; s != NULL; s = s->next)
- {
- rivet_server_conf* vhost_rsc;
-
- vhost_rsc = RIVET_SERVER_CONF(s->module_config);
- vhost_rsc->idx = idx++;
- }
- module_globals->vhosts_count = idx;
- module_globals->server_interps = apr_pcalloc(pPool,module_globals->vhosts_count*sizeof(rivet_thread_interp));
-
for (s = server; s != NULL; s = s->next)
{
rivet_server_conf* vhost_rsc;
@@ -317,7 +316,6 @@ Rivet_RunServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, ser
if (vhost_rsc->rivet_server_init_script != NULL)
{
- Tcl_Interp* interp;
Tcl_Obj* server_init;
/* either we want separate virtual interps or we haven't
@@ -334,6 +332,17 @@ Rivet_RunServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, ser
*/
Rivet_PerInterpInit(interp_obj,private,s,pPool);
+
+ if (s == server)
+ {
+ root_interp = interp_obj;
+ }
+
+ } else {
+
+ interp_obj =
+ Rivet_DuplicateVHostInterp(pPool,root_interp);
+
}
/* This loop enables the prefork bridge to pick
@@ -342,42 +351,21 @@ Rivet_RunServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, ser
module_globals->server_interps[vhost_rsc->idx] = interp_obj;
+ /* we now establish the full rivet core command set for the root interpreter */
+ // Rivet_InitCore (module_globals->server_interps[vhost_rsc->idx],private);
+
/* We don't create the cache here: it would make sense only
* for the prefork MPM. Non-fork bridges should do it
* themselves
*/
- interp = interp_obj->interp;
server_init = Tcl_NewStringObj(vhost_rsc->rivet_server_init_script,-1);
Tcl_IncrRefCount(server_init);
-
- if (Tcl_EvalObjEx(interp, server_init, 0) != TCL_OK)
- {
- ap_log_error (APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
- MODNAME ": Error running ServerInitScript '%s': %s",
- vhost_rsc->rivet_server_init_script,
- Tcl_GetVar(interp, "errorInfo", 0));
- }
- else
- {
- ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, server,
- MODNAME ": ServerInitScript '%s' successful",
- vhost_rsc->rivet_server_init_script);
- }
-
+ Rivet_EvalScript (s,interp_obj,server_init,"ServerInitScript");
Tcl_DecrRefCount(server_init);
- }
- else if (s == server)
- {
- /* an interpreter on the initial position is always set */
-
- interp_obj = Rivet_NewVHostInterp(private,s);
- Rivet_PerInterpInit(interp_obj,private,s,pPool);
- module_globals->server_interps[vhost_rsc->idx] = interp_obj;
}
-
}
/* bridge specific server init script */
@@ -530,7 +518,7 @@ static void Rivet_ChildInit (apr_pool_t *pChild, server_rec *server)
{
rivet_server_conf* myrsc;
- myrsc = RIVET_SERVER_CONF( s->module_config );
+ myrsc = RIVET_SERVER_CONF(s->module_config);
/* We only have a different rivet_server_conf if MergeConfig
* was called. We really need a separate one for each server,
diff --git a/src/mod_rivet_ng/mod_rivet_common.c b/src/mod_rivet_ng/mod_rivet_common.c
index 3da2ba6..f2d5471 100644
--- a/src/mod_rivet_ng/mod_rivet_common.c
+++ b/src/mod_rivet_ng/mod_rivet_common.c
@@ -237,11 +237,15 @@ void Rivet_PerInterpInit(rivet_thread_interp* interp_obj,
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;
+ Tcl_Obj* auto_path = NULL;
+ Tcl_Obj* rivet_tcl = NULL;
+ Tcl_Interp* interp;
+
+ /* Do we need to initialize this interpreter? */
+ if ((interp_obj->flags & RIVET_INTERP_INITIALIZED)) { return; }
+
+ interp = interp_obj->interp;
ap_assert (interp != (Tcl_Interp *)NULL);
Tcl_Preserve (interp);
@@ -380,6 +384,7 @@ rivet_thread_interp* Rivet_NewVHostInterp(rivet_thread_private* private,server_r
RivetCache_Create(pool,interp_obj);
}
+ interp_obj->channel = NULL;
interp_obj->flags = 0;
interp_obj->scripts = (running_scripts *) apr_pcalloc(pool,sizeof(running_scripts));
interp_obj->per_dir_scripts = apr_hash_make(pool);
@@ -432,6 +437,8 @@ Rivet_CreateRivetChannel(apr_pool_t* pPool, apr_threadkey_t* rivet_thread_key)
return outchannel;
}
+
+
/*-----------------------------------------------------------------------------
*
* -- Rivet_ReleaseRivetChannel
@@ -828,6 +835,85 @@ int Rivet_chdir_file (const char *file)
chdir_retval = chdir(chdir_buf);
#endif
}
-
return chdir_retval;
}
+
+
+/*-----------------------------------------------------------------------------
+ *
+ * -- Rivet_ImportNamespace
+ *
+ * Executes a Tcl code fragment to import into the global space
+ * the commands created in the ::rivet namespace
+ *
+ * Arguments:
+ *
+ * - server_rec* server
+ * - rivet_thread_interps* server interps array
+ *
+ * Returned value
+ *
+ * none
+ *
+ * Side Effects:
+ *
+ * If needed a Rivet channel is created and registered with an interpreter
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void Rivet_ImportNamespace (server_rec* server,rivet_thread_interp* interp)
+{
+ rivet_server_conf* rsc;
+ server_rec* s;
+ char* tcl_import_cmd =
+ "namespace eval :: { namespace import -force ::rivet::* }\n";
+
+ for (s = server; s != NULL; s = s->next)
+ {
+ int idx;
+
+ rsc = RIVET_SERVER_CONF(s->module_config);
+ idx = rsc->idx;
+
+ Tcl_Eval (module_globals->server_interps[idx]->interp,tcl_import_cmd);
+
+ }
+
+}
+
+/* -- Rivet_EvalScript
+ *
+ * Utility function to evaluate single Tcl scripts like configuration
+ * specified script (GlobalInitScript,ChildInitScript and ChildExitScript)
+ *
+ *
+ */
+
+int Rivet_EvalScript (server_rec* server,
+ rivet_thread_interp* interp_obj,
+ Tcl_Obj* tcl_script,
+ const char* script_name)
+{
+ int tcl_retcode;
+
+ tcl_retcode = Tcl_EvalObjEx(interp_obj->interp,tcl_script,0);
+ if (tcl_retcode != TCL_OK)
+ {
+
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
+ MODNAME "errorCode: %s", Tcl_GetVar(interp_obj->interp, "errorCode", 0));
+ ap_log_error(APLOG_MARK,APLOG_ERR,APR_EGENERAL,server,
+ MODNAME ": Error running '%s': %s",script_name,
+ Tcl_GetVar(interp_obj->interp,"errorInfo",0));
+
+ } else {
+
+ ap_log_error(APLOG_MARK,APLOG_DEBUG,0,server,
+ MODNAME ": GlobalInitScript '%s' successful",script_name);
+
+ }
+
+ return tcl_retcode;
+}
+
diff --git a/src/mod_rivet_ng/mod_rivet_common.h b/src/mod_rivet_ng/mod_rivet_common.h
index 5cac8aa..12d9e26 100644
--- a/src/mod_rivet_ng/mod_rivet_common.h
+++ b/src/mod_rivet_ng/mod_rivet_common.h
@@ -22,22 +22,24 @@
#ifndef __mod_rivet_common__
#define __mod_rivet_common__
-EXTERN rivet_thread_interp* Rivet_DuplicateVHostInterp(apr_pool_t* pool, rivet_thread_interp* source_obj);
+EXTERN rivet_thread_interp* Rivet_DuplicateVHostInterp (apr_pool_t* pool, rivet_thread_interp* source_obj);
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,
+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(rivet_thread_private* private,server_rec* s);
+EXTERN rivet_thread_interp* Rivet_NewVHostInterp (rivet_thread_private* private,server_rec* s);
EXTERN void Rivet_ProcessorCleanup (void *data);
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 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_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);
-
-#endif
+EXTERN void Rivet_ImportNamespace (server_rec* server,rivet_thread_interp* interp);
+EXTERN int Rivet_EvalScript (server_rec* server,rivet_thread_interp* interp_obj,Tcl_Obj* tcl_script,
+ const char* script_name);
+#endif /* __mod_rivet_common__ */
diff --git a/src/mod_rivet_ng/rivet_prefork_mpm.c b/src/mod_rivet_ng/rivet_prefork_mpm.c
index 1eeaba1..471e485 100644
--- a/src/mod_rivet_ng/rivet_prefork_mpm.c
+++ b/src/mod_rivet_ng/rivet_prefork_mpm.c
@@ -29,13 +29,12 @@
#include "rivet.h"
#include "rivetCore.h"
#include "worker_prefork_common.h"
-#include "TclWeb.h"
extern DLLIMPORT mod_rivet_globals* module_globals;
extern DLLIMPORT apr_threadkey_t* rivet_thread_key;
module rivet_module;
-rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private);
+extern TclWebRequest* TclWeb_NewRequestObject (apr_pool_t *p);
int Prefork_Bridge_ServerInit (apr_pool_t *pPool,
apr_pool_t *pLog,
@@ -44,14 +43,21 @@ int Prefork_Bridge_ServerInit (apr_pool_t *pPool,
rivet_thread_interp** server_interps = module_globals->server_interps;
rivet_server_conf* rsc;
server_rec* s;
- rivet_thread_interp* interp_obj;
rivet_thread_private* private;
+ int server_idx;
RIVET_PRIVATE_DATA_NOT_NULL(rivet_thread_key,private)
- /* Assuming the first interpreter in server_interps array to always be set */
+ /* Enforcing the first interpreter in server_interps to be set */
- interp_obj = server_interps[0];
+ rsc = RIVET_SERVER_CONF(server->module_config);
+ server_idx = rsc->idx;
+
+ if (server_interps[server_idx] == NULL)
+ {
+ server_interps[server_idx] = Rivet_NewVHostInterp(private,server);
+ Rivet_PerInterpInit(server_interps[server_idx],private,server,pPool);
+ }
/*
* Looping through all the server records and creating (or assigning
@@ -62,6 +68,8 @@ int Prefork_Bridge_ServerInit (apr_pool_t *pPool,
{
int idx;
+ if (s == server) { continue; }
+
rsc = RIVET_SERVER_CONF(s->module_config);
idx = rsc->idx;
@@ -72,9 +80,9 @@ int Prefork_Bridge_ServerInit (apr_pool_t *pPool,
if (server_interps[idx] == NULL)
{
- if ((s == server) || (rsc->separate_virtual_interps == 0))
+ if (rsc->separate_virtual_interps == 0)
{
- module_globals->server_interps[idx] = interp_obj;
+ server_interps[idx] = server_interps[server_idx];
}
else
{
@@ -83,7 +91,6 @@ int Prefork_Bridge_ServerInit (apr_pool_t *pPool,
}
}
}
-
return OK;
}
@@ -104,94 +111,71 @@ apr_status_t Prefork_Bridge_Finalize (void* data)
return OK;
}
+/* -- Prefork_ReseedRNG
+ *
+ */
+
+static void Prefork_ReseedRNG(server_rec* server,rivet_thread_interp* interp_obj)
+{
+ int tcl_status;
+ // rivet_server_conf* rsc = RIVET_SERVER_CONF(server->module_config);
+
+ tcl_status = Tcl_Eval(interp_obj->interp,"expr {srand([clock clicks] + [pid])}");
+ if (tcl_status != TCL_OK)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
+ MODNAME ": Tcl interpreter random number generation reseeding failed");
+ }
+
+}
+
/* -- Prefork_Bridge_ChildInit: bridge child process initialization */
void Prefork_Bridge_ChildInit (apr_pool_t* pool, server_rec* server)
{
rivet_thread_private* private;
- Tcl_Obj* global_tcl_script;
rivet_server_conf* root_server_conf;
rivet_thread_interp** server_interps = module_globals->server_interps;
- rivet_server_conf* rsc;
- int idx;
+ //Tcl_Channel* channel;
+ //server_rec* s;
RIVET_PRIVATE_DATA_NOT_NULL(rivet_thread_key,private)
- /*
- * Assuming the good global initialization script is in the
- * first server configuration record
- */
-
root_server_conf = RIVET_SERVER_CONF(server->module_config);
- if (root_server_conf->rivet_global_init_script != NULL)
- {
- server_rec* s;
- global_tcl_script = Tcl_NewStringObj(root_server_conf->rivet_global_init_script,-1);
- Tcl_IncrRefCount(global_tcl_script);
-
- if (root_server_conf->separate_virtual_interps)
- {
- for (s = server; s != NULL; s = s->next)
- {
-
- rsc = RIVET_SERVER_CONF(s->module_config);
- idx = rsc->idx;
-
- ap_assert(server_interps[idx] != NULL);
- if (Tcl_EvalObjEx(server_interps[idx]->interp,global_tcl_script,0) != TCL_OK)
- {
- ap_log_error (APLOG_MARK,APLOG_ERR,APR_EGENERAL,s,
- MODNAME ": Error running GlobalInitScript '%s': %s",
- root_server_conf->rivet_global_init_script,
- Tcl_GetVar(server_interps[idx]->interp, "errorInfo", 0));
- } else {
- ap_log_error(APLOG_MARK,APLOG_DEBUG,0,s,
- MODNAME ": GlobalInitScript '%s' successful",
- root_server_conf->rivet_global_init_script);
- }
-
- }
- }
- else
- {
- rsc = RIVET_SERVER_CONF(server->module_config);
- idx = rsc->idx;
- Rivet_PerInterpInit(server_interps[idx],NULL,server,pool);
- if (Tcl_EvalObjEx(server_interps[idx]->interp,global_tcl_script,0) != TCL_OK)
- {
- ap_log_error (APLOG_MARK,APLOG_ERR,APR_EGENERAL,server,
- MODNAME ": Error running GlobalInitScript '%s': %s",
- root_server_conf->rivet_global_init_script,
- Tcl_GetVar(server_interps[idx]->interp, "errorInfo", 0));
- } else {
- ap_log_error(APLOG_MARK,APLOG_DEBUG,0,server,
- MODNAME ": GlobalInitScript '%s' successful",
- root_server_conf->rivet_global_init_script);
- }
- }
-
- Tcl_DecrRefCount(global_tcl_script);
- }
+ /* Bridge specific data are allocate here */
- /* The intepreter was created by the server initiazione, we now create its Rivet channel */
+ private->ext = apr_pcalloc(private->pool,sizeof(mpm_bridge_specific));
- private->channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
-
/*
- * Prefork bridge has inherited the parent process pool but we have to initialize ourselves
- * the request descriptor obj
+ * Prefork bridge has inherited the parent process pool but we have
+ * to initialize ourselves the request descriptor obj
*/
private->req = TclWeb_NewRequestObject(private->pool);
- /* Bridge specific data are allocate here */
+ /* The prefork MPM just needs to keep a pointer
+ * to the interpreters array in module_globals->server_interps
+ */
- private->ext = apr_pcalloc(private->pool,sizeof(mpm_bridge_specific));
private->ext->interps = module_globals->server_interps;
-
- //apr_pcalloc(private->pool,module_globals->vhosts_count*sizeof(rivet_thread_interp));
-
+
+ /* reseeding the RNG for each interpreter when a new child process is created */
+
+ RIVET_FOREACH_SERVER(server,server_interps,Prefork_ReseedRNG)
+
+ 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);
+
+ RIVET_FOREACH_SERVER2(server,server_interps,Rivet_EvalScript,global_tcl_script,"GlobalInitScript");
+
+ Tcl_DecrRefCount(global_tcl_script);
+ }
+
/* This step is not needed anymore, we rely on the initialization that took
* place with the server initialization
*/
@@ -202,29 +186,15 @@ void Prefork_Bridge_ChildInit (apr_pool_t* pool, server_rec* server)
#ifdef RIVET_NAMESPACE_IMPORT
- {
- rivet_server_conf* rsc;
- server_rec* s;
- char* tcl_import_cmd = "namespace eval :: { namespace import -force ::rivet::* }\n";
-
- for (s = server; s != NULL; s = s->next)
- {
- int idx;
-
- rsc = RIVET_SERVER_CONF(s->module_config);
- idx = rsc->idx;
+ RIVET_FOREACH_SERVER(server,server_interps,Rivet_ImportNamespace)
- Tcl_Eval (module_globals->server_interps[idx]->interp,tcl_import_cmd);
-
- }
- }
#endif
/*
- * We proceed creating the vhost interpreters database
+ * We proceed creating the whole virtual host interpreters array
*/
- if (Rivet_VirtualHostsInterps (private) == NULL)
+ if (Rivet_SetupInterps(private) == NULL)
{
ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
MODNAME ": Tcl Interpreters creation fails");
@@ -261,6 +231,7 @@ int Prefork_Bridge_Request (request_rec* r,rivet_req_ctype ctype)
return Rivet_SendContent(private,r);
}
+#if 0
rivet_thread_interp* MPM_MasterInterp(server_rec* server)
{
rivet_thread_private* private;
@@ -289,6 +260,7 @@ rivet_thread_interp* MPM_MasterInterp(server_rec* server)
}
return module_globals->server_interps[0];
}
+#endif
/*
* -- Prefork_Bridge_ExitHandler
@@ -328,7 +300,6 @@ RIVET_MPM_BRIDGE {
Prefork_Bridge_Finalize,
Prefork_Bridge_ExitHandler,
Prefork_Bridge_Interp,
- Prefork_MPM_Interp,
true
};
diff --git a/src/mod_rivet_ng/rivet_worker_mpm.c b/src/mod_rivet_ng/rivet_worker_mpm.c
index 45b3850..2c26ca2 100644
--- a/src/mod_rivet_ng/rivet_worker_mpm.c
+++ b/src/mod_rivet_ng/rivet_worker_mpm.c
@@ -19,8 +19,6 @@
under the License.
*/
-/* $Id$*/
-
#include <httpd.h>
#include <math.h>
#include <tcl.h>
@@ -59,8 +57,6 @@ apr_threadkey_t* handler_thread_key;
int round(double d) { return (int)(d + 0.5); }
#endif /* RIVET_NO_HAVE_ROUND */
-rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private);
-
typedef struct mpm_bridge_status {
apr_thread_t* supervisor;
int server_shutdown;
@@ -91,7 +87,7 @@ typedef struct _handler_private
{
apr_thread_cond_t* cond;
apr_thread_mutex_t* mutex;
- request_rec* r; /* request rec */
+ request_rec* r; /* request rec */
int code;
int status;
rivet_req_ctype ctype;
@@ -170,6 +166,41 @@ void Worker_Bridge_Shutdown (void)
return;
}
+/* -- Worker_CreateInterps
+ */
+
+static void Worker_CreateInterps (rivet_thread_private* private,rivet_thread_interp** interps)
+{
+ server_rec* server = module_globals->server;
+ server_rec* s;
+ rivet_thread_interp* interp_obj = NULL;
+
+ for (s = server; s != NULL; s = s->next)
+ {
+ rivet_server_conf* server_conf;
+ rivet_thread_interp* root_interp = NULL;
+
+ server_conf = RIVET_SERVER_CONF(s->module_config);
+
+ if ((s == server) || (server_conf->separate_virtual_interps))
+ {
+
+ interp_obj = Rivet_NewVHostInterp(private,s);
+ Rivet_PerInterpInit(interp_obj,private,s,private->pool);
+ if (s == server) { root_interp = interp_obj; }
+
+ } else {
+
+ interp_obj =
+ Rivet_DuplicateVHostInterp(private->pool,root_interp);
+
+ }
+
+ interps[server_conf->idx] = interp_obj;
+
+ }
+
+}
/*
* -- request_processor_ng
*/
@@ -195,7 +226,9 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
private->ext->interps =
apr_pcalloc(private->pool,module_globals->vhosts_count*sizeof(rivet_thread_interp));
- /* So far nothing differs much with what we did for the prefork bridge */
+ /* We need to create the thread's interpreters */
+
+ Worker_CreateInterps (private,private->ext->interps);
/* At this stage we have to set up the private interpreters of configured
* virtual hosts (if any). We assume the server_rec stored in the module
@@ -203,7 +236,7 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
* configuration and to the rivet global script
*/
- if (Rivet_VirtualHostsInterps(private) == NULL)
+ if (Rivet_SetupInterps(private) == NULL)
{
*(apr_thread_t **) apr_array_push(module_globals->mpm->exiting) = thd;
apr_thread_cond_signal(module_globals->mpm->job_cond);
@@ -217,7 +250,7 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
thread_obj = apr_pcalloc(private->pool,sizeof(handler_private));
ap_assert(apr_thread_cond_create(&(thread_obj->cond), private->pool) == APR_SUCCESS);
ap_assert(apr_thread_mutex_create(&(thread_obj->mutex),APR_THREAD_MUTEX_UNNESTED,private->pool)
- == APR_SUCCESS);
+ == APR_SUCCESS);
thread_obj->status = idle;
@@ -304,7 +337,7 @@ static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
static apr_status_t create_worker_thread (apr_thread_t** thd)
{
- return apr_thread_create(thd, NULL, request_processor, NULL, module_globals->pool);
+ return apr_thread_create(thd,NULL,request_processor,NULL,module_globals->pool);
}
static void start_thread_pool (int nthreads)
@@ -377,14 +410,16 @@ static void supervisor_housekeeping (void)
static void* APR_THREAD_FUNC threaded_bridge_supervisor (apr_thread_t *thd, void *data)
{
mpm_bridge_status* mpm = module_globals->mpm;
+ server_rec* s;
- server_rec* s = (server_rec *)data;
#ifdef RIVET_MPM_SINGLE_TCL_THREAD
int threads_to_start = 1;
#else
int threads_to_start = mpm->max_threads;
#endif
+ s = module_globals->server;
+
ap_log_error(APLOG_MARK,APLOG_INFO,0,s,"starting %d Tcl threads",threads_to_start);
start_thread_pool(threads_to_start);
@@ -471,8 +506,8 @@ void Worker_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
ap_assert (apr_threadkey_private_create (&rivet_thread_key, NULL, pool) == APR_SUCCESS);
- /* On some platform this is required in order to initialize the
- *
+ /* On some plattform this is required in order to initialize
+ * APR atomic function utilities
*/
apr_atomic_init(pool);
@@ -511,12 +546,6 @@ void Worker_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
ap_assert (apr_threadkey_private_create(&handler_thread_key,NULL,pool) == APR_SUCCESS);
- /* This bridge keeps an array of the ids of threads about to exit. This array is protected by
- * the mutex module_globals->job_mutex and signals through module_globals->job_cond
- */
-
- module_globals->mpm->exiting = apr_array_make(pool,100,sizeof(apr_thread_t*));
-
/* This APR-Util queue object is the central communication channel from the Apache
* framework to the Tcl threads through the request handler */
@@ -527,8 +556,8 @@ void Worker_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
exit(1);
}
- /* In order to set up some workload balancing let's
- * query apache for some configuration parameters of the worker MPM
+ /* In order to set up some data for workload balancer we
+ * query apache about some configuration parameters of the worker MPM
*/
if (ap_mpm_query(AP_MPMQ_MAX_THREADS,&module_globals->mpm->max_threads) != APR_SUCCESS)
@@ -544,12 +573,20 @@ void Worker_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
module_globals->mpm->max_spare_threads = TCL_INTERPS;
}
+ /* This bridge keeps an array of the ids of threads about to exit. This array is protected by
+ * the mutex module_globals->job_mutex and signals through module_globals->job_cond
+ */
+
+ module_globals->mpm->exiting = apr_array_make(pool,module_globals->mpm->max_threads,sizeof(apr_thread_t*));
+
/* We allocate the array of Tcl threads id. We require it to have AP_MPMQ_MAX_THREADS slots */
- module_globals->mpm->workers = apr_pcalloc(pool,module_globals->mpm->max_threads * sizeof(void *));
+ module_globals->mpm->workers = apr_pcalloc(pool,module_globals->mpm->max_threads*sizeof(void *));
+
+ /* thread arguments pass the master server record and the process pool */
- rv = apr_thread_create( &module_globals->mpm->supervisor, NULL,
- threaded_bridge_supervisor, server, module_globals->pool);
+ rv = apr_thread_create(&module_globals->mpm->supervisor,NULL,
+ threaded_bridge_supervisor,NULL,pool);
if (rv != APR_SUCCESS) {
char errorbuf[RIVET_MSG_BUFFER_SIZE];
@@ -787,6 +824,6 @@ RIVET_MPM_BRIDGE {
Worker_MPM_Request,
Worker_MPM_Finalize,
Worker_MPM_ExitHandler,
- Worker_MPM_Interp
+ Worker_MPM_Interp,
false,
};
diff --git a/src/mod_rivet_ng/worker_prefork_common.c b/src/mod_rivet_ng/worker_prefork_common.c
index c93cdb3..85ee1f7 100644
--- a/src/mod_rivet_ng/worker_prefork_common.c
+++ b/src/mod_rivet_ng/worker_prefork_common.c
@@ -39,9 +39,7 @@ extern DLLIMPORT mod_rivet_globals* module_globals;
extern DLLIMPORT apr_threadkey_t* rivet_thread_key;
extern DLLIMPORT module rivet_module;
-extern rivet_thread_interp* MPM_MasterInterp(server_rec* s);
-
-/* -- Rivet_VirtualHostsInterps
+/* -- Rivet_SetupInterps
*
* The server_rec chain is walked through and server configurations is read to
* set up the thread private configuration and interpreters database
@@ -60,143 +58,69 @@ extern rivet_thread_interp* MPM_MasterInterp(server_rec* s);
*
*/
-rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private)
+rivet_thread_private* Rivet_SetupInterps (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;
+ Tcl_Channel* channel;
root_server_conf = RIVET_SERVER_CONF (root_server->module_config);
- root_interp = MPM_MasterInterp(module_globals->server);
-
- /* we must assume the module was able to create the root interprter */
-
- 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 each virtual host */
+ /* The intepreters were created by the server init script, we now create its Rivet channel */
+ channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
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;
+ rivet_server_conf* rsc;
+ rivet_thread_interp* interp_obj;
+
+ rsc = RIVET_SERVER_CONF(s->module_config);
+ interp_obj = private->ext->interps[rsc->idx];
- if (s == root_server)
+ if ((s != root_server) &&
+ (root_server_conf->separate_channels) &&
+ (root_server_conf->separate_virtual_interps))
{
- Tcl_RegisterChannel(rivet_interp->interp,*rivet_interp->channel);
- }
- else
- {
- if (root_server_conf->separate_virtual_interps)
- {
- rivet_interp = Rivet_NewVHostInterp(private,s);
- 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);
- }
+ channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
}
+ interp_obj->channel = channel;
+
+ Tcl_RegisterChannel(interp_obj->interp,*interp_obj->channel);
/* interpreter base running scripts definition and initialization */
- rivet_interp->scripts = Rivet_RunningScripts (private->pool,rivet_interp->scripts,myrsc);
+ interp_obj->scripts = Rivet_RunningScripts (private->pool,interp_obj->scripts,rsc);
- //private->ext->interps[myrsc->idx] = rivet_interp;
-
- RIVET_POKE_INTERP(private,myrsc,rivet_interp);
+ private->ext->interps[rsc->idx] = interp_obj;
/* Basic Rivet packages and libraries are loaded here */
- if ((rivet_interp->flags & RIVET_INTERP_INITIALIZED) == 0)
- {
- Rivet_PerInterpInit(rivet_interp, private, s, private->pool);
- }
+ Rivet_PerInterpInit(interp_obj, private, s, private->pool);
/* It seems that allocating from a shared APR memory pool is not thread safe,
* but it's not very well documented actually. In any case we protect this
* memory allocation with a mutex
*/
- /* 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;
+ function = rsc->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_Interp* interp = interp_obj->interp;
Tcl_Obj* tcl_child_init = Tcl_NewStringObj(function,-1);
Tcl_IncrRefCount(tcl_child_init);
Tcl_Preserve (interp);
- /* There is a lot of passing pointers around among various structures.
- * 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
- */
-
- /* before we run a script we have to store the pointer to the
- * running configuration in the thread private data. The design has
- * to improve and running a script must have everything sanely
- * prepared TODO
- */
-
- private->running_conf = myrsc;
+ private->running_conf = rsc;
if (Tcl_EvalObjEx(interp,tcl_child_init, 0) != TCL_OK) {
ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server, errmsg, function);
diff --git a/src/mod_rivet_ng/worker_prefork_common.h b/src/mod_rivet_ng/worker_prefork_common.h
index e79c388..e96d19c 100644
--- a/src/mod_rivet_ng/worker_prefork_common.h
+++ b/src/mod_rivet_ng/worker_prefork_common.h
@@ -33,5 +33,6 @@ typedef struct mpm_bridge_specific {
} mpm_bridge_specific;
int Interps_Init (rivet_thread_interp** , apr_pool_t* , server_rec* );
+rivet_thread_private* Rivet_SetupInterps (rivet_thread_private* private);
#endif /* */
diff --git a/src/rivet.h b/src/rivet.h
index 6572647..83e7272 100644
--- a/src/rivet.h
+++ b/src/rivet.h
@@ -1,4 +1,4 @@
-/* rivet.h: */
+/* rivet.h */
/*
Licensed to the Apache Software Foundation (ASF) under one
@@ -19,10 +19,8 @@
under the License.
*/
-/* $Id$ */
-
-#ifndef _RIVET_H_
-#define _RIVET_H_
+#ifndef __rivet_h__
+#define __rivet_h__
#include <tcl.h>
#include "rivet_types.h"
@@ -108,6 +106,49 @@ EXTERN int Rivet_InitList(Tcl_Interp *interp);
EXTERN int Rivet_InitCrypt(Tcl_Interp *interp);
EXTERN int Rivet_InitWWW(Tcl_Interp *interp);
+#define RIVET_FOREACH_SERVER(server,interps,aFunction) \
+{\
+ server_rec* s; \
+ rivet_server_conf* rsc; \
+ rivet_thread_interp* interp_obj; \
+\
+ rsc = RIVET_SERVER_CONF(server->module_config); \
+ interp_obj = interps[rsc->idx]; \
+ for (s = server; s != NULL; s = s->next) { \
+ aFunction (s, interp_obj); \
+ if (rsc->separate_virtual_interps == 0) { break; } \
+ } \
+}
+
+#define RIVET_FOREACH_SERVER2(server,interps,aFunction,...) \
+{\
+ server_rec* s; \
+ rivet_server_conf* rsc; \
+ rivet_thread_interp* interp_obj; \
+\
+ rsc = RIVET_SERVER_CONF(server->module_config); \
+ 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; } \
+ } \
+}
+
+
+#define RIVET_FORALL_SERVERS(server,interps,aFunction,...) \
+{\
+ server_rec* s; \
+ rivet_server_conf* rsc; \
+ rivet_thread_interp* interp_obj; \
+\
+ rsc = RIVET_SERVER_CONF(server->module_config); \
+ interp_obj = interps[rsc->idx]; \
+ for (s = server; s != NULL; s = s->next) { \
+ aFunction (s, interp_obj, __VA_ARGS__ ); \
+ } \
+}
+
#endif
+
/* _RIVET_H_ */
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tcl.apache.org
For additional commands, e-mail: commits-help@tcl.apache.org