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