This is an automated email from the ASF dual-hosted git repository. mxmanghi pushed a commit to branch quattuor in repository https://gitbox.apache.org/repos/asf/tcl-rivet.git
commit 7db381382295ce3736285e9f8ba604ed59a679e7 Author: Massimo Manghi <mxman...@apache.org> AuthorDate: Thu May 18 17:12:24 2023 +0200 Handling the server_rec pointer in the module globals for the benefit of logging into the specific virtual host log file during child init stage --- ChangeLog | 12 +++- src/mod_rivet_ng/mod_rivet.c | 12 ++-- src/mod_rivet_ng/mod_rivet.h | 1 + src/mod_rivet_ng/mod_rivet_common.c | 8 +-- src/mod_rivet_ng/rivetCore.c | 14 ++++- src/mod_rivet_ng/worker_prefork_common.c | 95 ++++++++++++++++++++++++++------ 6 files changed, 111 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2b82f58..91f4d2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,13 @@ -2023-05-14 Massimo Manghi <mxman...@apache.org> +2023-05-18 Massimo Manghi <mxman...@apache.org> + * src/mod_rivet_ng/mod_rivet.c: + * src/mod_rivet_ng/mod_rivet.h: + * src/mod_rivet_ng/mod_rivet_common.c: + * src/mod_rivet_ng/rivetCore.c: + * src/mod_rivet_ng/worker_prefork_common.c: now storing the server record in the intepreter globals + to be used by Rivet_LogErrorCmd instead of module_globals->server when threads private data are + not available (like when ChildInitScript is executed) + +2023-05-04 Massimo Manghi <mxman...@apache.org> * tests/rivet.test: more contributions provided by Scott Pitcher <sco...@svptechnicalservices.com.au>) * tests/apachetest/apachetest.tcl: More improvements to the test script. Now handling also Apache directive IncludeOptional and enabling execution control @@ -6,7 +15,6 @@ * tests/post.rvt: * tests/post.test: add a test for ::rivet::raw_post - * 2023-04-11 Massimo Manghi <mxman...@apache.org> * src/mod_rivet_ng/TclWebapache.c: * src/mod_rivet_ng/rivetCore.c: diff --git a/src/mod_rivet_ng/mod_rivet.c b/src/mod_rivet_ng/mod_rivet.c index 37549ff..c63efda 100644 --- a/src/mod_rivet_ng/mod_rivet.c +++ b/src/mod_rivet_ng/mod_rivet.c @@ -289,15 +289,19 @@ Rivet_RunServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, ser { char* parent_pid_var = NULL; + /* if the environment variable AP_PARENT_PID is set + * we know we are in a child process of the winnt MPM + */ + apr_env_get(&parent_pid_var,"AP_PARENT_PID",pTemp); if (parent_pid_var != NULL) { - ap_log_error(APLOG_MARK,APLOG_DEBUG,0,server, - "AP_PARENT_PID found: not running the Tcl server script in winnt MPM child process"); + ap_log_perror(APLOG_MARK,APLOG_INFO,0,pPool, + "AP_PARENT_PID found: not running the Tcl server script in winnt MPM child process"); return OK; } else { - ap_log_error(APLOG_MARK,APLOG_DEBUG,0,server, - "AP_PARENT_PID undefined, we proceed with server initialization"); + ap_log_perror(APLOG_MARK,APLOG_INFO,0,pPool, + "AP_PARENT_PID undefined, we proceed with server initialization"); } } diff --git a/src/mod_rivet_ng/mod_rivet.h b/src/mod_rivet_ng/mod_rivet.h index c107690..8239c31 100644 --- a/src/mod_rivet_ng/mod_rivet.h +++ b/src/mod_rivet_ng/mod_rivet.h @@ -253,6 +253,7 @@ typedef struct _thread_worker_private { typedef struct _rivet_interp_globals { Tcl_Namespace* rivet_ns; /* Rivet commands namespace */ + server_rec* server; /* Virtual host server rec */ } rivet_interp_globals; rivet_server_conf *Rivet_GetConf(request_rec *r); diff --git a/src/mod_rivet_ng/mod_rivet_common.c b/src/mod_rivet_ng/mod_rivet_common.c index 35fe13b..2103849 100644 --- a/src/mod_rivet_ng/mod_rivet_common.c +++ b/src/mod_rivet_ng/mod_rivet_common.c @@ -250,7 +250,7 @@ void Rivet_ReleasePerDirScripts(rivet_thread_interp* rivet_interp) * * Rivet_PerInterpInit -- * - * Do the initialization that needs to happen to every interpreter. + * Do the interpreter environment creation and initialization. * * Results: * None. @@ -283,11 +283,11 @@ void Rivet_PerInterpInit(rivet_thread_interp* interp_obj, //Tcl_SetAssocData (interp,"rivet",NULL,globals); /* - * the ::rivet namespace is the only information still stored - * in the interpreter global data + * we store in the globals some information relevant to + * the embedded interpreter work */ - /* Rivet commands namespace is created */ + /* the ::rivet namespace is created */ interp_obj->rivet_ns = Tcl_CreateNamespace (interp,RIVET_NS,private,(Tcl_NamespaceDeleteProc *)NULL); diff --git a/src/mod_rivet_ng/rivetCore.c b/src/mod_rivet_ng/rivetCore.c index c32ed15..82fba23 100644 --- a/src/mod_rivet_ng/rivetCore.c +++ b/src/mod_rivet_ng/rivetCore.c @@ -1770,7 +1770,7 @@ TCL_CMD_HEADER( Rivet_InspectCmd ) *----------------------------------------------------------------------------- */ -TCL_CMD_HEADER( Rivet_LogErrorCmd ) +TCL_CMD_HEADER(Rivet_LogErrorCmd) { char *message = NULL; @@ -1855,9 +1855,17 @@ TCL_CMD_HEADER( Rivet_LogErrorCmd ) /* if we are serving a page, we know our server, * else send null for server */ - serverRec = ((private == NULL) || (private->r == NULL)) ? module_globals->server : private->r->server; - ap_log_error (APLOG_MARK, apLogLevel, 0, serverRec, "%s", message); + if ((private == NULL) || (private->r == NULL)) + { + rivet_interp_globals* globals = Tcl_GetAssocData(interp, "rivet", NULL); + serverRec = globals->server; + } + else + { + serverRec = private->r->server; + } + ap_log_error (APLOG_MARK,apLogLevel,0,serverRec,"%s",message); return TCL_OK; } diff --git a/src/mod_rivet_ng/worker_prefork_common.c b/src/mod_rivet_ng/worker_prefork_common.c index 48c4b36..ec92c33 100644 --- a/src/mod_rivet_ng/worker_prefork_common.c +++ b/src/mod_rivet_ng/worker_prefork_common.c @@ -40,6 +40,34 @@ extern DLLIMPORT apr_threadkey_t* rivet_thread_key; extern DLLIMPORT module rivet_module; /* -- Rivet_SetupInterps + * + * + */ + +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; + + /* An intepreter must have its own cache */ + + if (interp_obj->cache_size) { + RivetCache_Create(source_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 are read to * set up the thread private configuration and interpreters database @@ -60,7 +88,7 @@ extern DLLIMPORT module rivet_module; rivet_thread_private* Rivet_SetupInterps (rivet_thread_private* private) { - server_rec* s; + server_rec* vhost_server; server_rec* root_server = module_globals->server; rivet_server_conf* root_server_conf; void* parentfunction; /* this is topmost initialization script */ @@ -77,15 +105,15 @@ rivet_thread_private* Rivet_SetupInterps (rivet_thread_private* private) parentfunction = root_server_conf->rivet_child_init_script; - for (s = root_server; s != NULL; s = s->next) + for (vhost_server = root_server; vhost_server != NULL; vhost_server = vhost_server->next) { rivet_server_conf* rsc; rivet_thread_interp* interp_obj; - rsc = RIVET_SERVER_CONF(s->module_config); + rsc = RIVET_SERVER_CONF(vhost_server->module_config); interp_obj = private->ext->interps[rsc->idx]; - if ((s != root_server) && + if ((vhost_server != root_server) && module_globals->separate_channels && module_globals->separate_virtual_interps) { @@ -97,42 +125,73 @@ rivet_thread_private* Rivet_SetupInterps (rivet_thread_private* private) /* interpreter base running scripts definition and initialization */ - interp_obj->scripts = Rivet_RunningScripts(private->pool,interp_obj->scripts,rsc); - - private->ext->interps[rsc->idx] = interp_obj; + interp_obj->scripts = Rivet_RunningScripts (private->pool,interp_obj->scripts,rsc); + RIVET_POKE_INTERP(private,rsc,interp_obj); /* Basic Rivet packages and libraries are loaded here */ - Rivet_PerInterpInit(interp_obj, private, s, private->pool); + if ((interp_obj->flags & RIVET_INTERP_INITIALIZED) == 0) + { + Rivet_PerInterpInit(interp_obj,private,vhost_server,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); + rsc->server_name = (char*) apr_pstrdup (private->pool,vhost_server->server_hostname); + apr_thread_mutex_unlock(module_globals->pool_mutex); + /* when configured a child init script gets evaluated */ function = rsc->rivet_child_init_script; if (function && - (s == root_server || module_globals->separate_virtual_interps || function != parentfunction)) + (vhost_server == root_server || module_globals->separate_virtual_interps || function != parentfunction)) { char* errmsg = MODNAME ": Error in Child init script: %s"; - Tcl_Interp* interp = interp_obj->interp; Tcl_Obj* tcl_child_init = Tcl_NewStringObj(function,-1); + rivet_interp_globals* globals = NULL; Tcl_IncrRefCount(tcl_child_init); - Tcl_Preserve (interp); + Tcl_Preserve (interp_obj->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 + */ + + globals = Tcl_GetAssocData(interp_obj->interp, "rivet", NULL); + + /* + * The current server record is stored to enable ::rivet::apache_log_error and + * other commands to log error messages in the virtual host's designated log file + */ + globals->server = vhost_server; 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); - 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)); + if (Tcl_EvalObjEx(interp_obj->interp,tcl_child_init, 0) != TCL_OK) { + ap_log_error(APLOG_MARK, APLOG_ERR,APR_EGENERAL,vhost_server,errmsg, function); + ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL,vhost_server, + "errorCode: %s", Tcl_GetVar(interp_obj->interp, "errorCode", 0)); + ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL,vhost_server, + "errorInfo: %s", Tcl_GetVar(interp_obj->interp, "errorInfo", 0)); } - Tcl_Release (interp); + Tcl_Release (interp_obj->interp); Tcl_DecrRefCount(tcl_child_init); } } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@tcl.apache.org For additional commands, e-mail: commits-h...@tcl.apache.org