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 2018/01/19 21:06:51 UTC
svn commit: r1821714 - /tcl/rivet/trunk/doc/xml/lazybridge.xml
Author: mxmanghi
Date: Fri Jan 19 21:06:51 2018
New Revision: 1821714
URL: http://svn.apache.org/viewvc?rev=1821714&view=rev
Log:
display entire code of Lazy_MPM_ChildInit Lazy_MPM_Request and request processor
Modified:
tcl/rivet/trunk/doc/xml/lazybridge.xml
Modified: tcl/rivet/trunk/doc/xml/lazybridge.xml
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/doc/xml/lazybridge.xml?rev=1821714&r1=1821713&r2=1821714&view=diff
==============================================================================
--- tcl/rivet/trunk/doc/xml/lazybridge.xml (original)
+++ tcl/rivet/trunk/doc/xml/lazybridge.xml Fri Jan 19 21:06:51 2018
@@ -93,7 +93,7 @@ typedef struct mpm_bridge_status {
in the jump table points to <command>Lazy_MPM_ChildInit</command>
</para>
<programlisting>/*
- * Lazy_MPM_ChildInit
+ * -- Lazy_MPM_ChildInit
*
* child process initialization. This function prepares the process
* data structures for virtual hosts and threads management
@@ -153,7 +153,6 @@ void Lazy_MPM_ChildInit (apr_pool_t* poo
}
module_globals->mpm->server_shutdown = 0;
}</programlisting>
-
</section>
<section>
<title>Handling Tcl's exit core command</title>
@@ -220,7 +219,7 @@ typedef struct lazy_tcl_worker {
int ctype;
int ap_sts;
int nreqs;
- rivet_server_conf* conf; /* rivet_server_conf* record */
+ rivet_server_conf* conf; /* rivet_server_conf* record */
} lazy_tcl_worker;</programlisting>
<para>
The server field is assigned with the virtual host server record. Whereas the <command>conf</command>
@@ -235,42 +234,187 @@ typedef struct lazy_tcl_worker {
in case the array is empty and no threads are available, a new worker thread is
created. The code in the <command>Lazy_MPM_Request</command> function
</para>
- <programlisting> lazy_tcl_worker* w;
- ...
+ <programlisting>/* -- Lazy_MPM_Request
+ *
+ * The lazy bridge HTTP request function. This function
+ * stores the request_rec pointer into the lazy_tcl_worker
+ * structure which is used to communicate with a worker thread.
+ * Then the array of idle threads is checked and if empty
+ * a new thread is created by calling create_worker
+ */
+
+int Lazy_MPM_Request (request_rec* r,rivet_req_ctype ctype)
+{
+ lazy_tcl_worker* w;
+ int ap_sts;
+ rivet_server_conf* conf = RIVET_SERVER_CONF(r->server->module_config);
apr_array_header_t* array;
apr_thread_mutex_t* mutex;
- mutex = module_globals->mpm->vhosts[conf->idx].mutex;
- array = module_globals->mpm->vhosts[conf->idx].array;
+ mutex = module_globals->mpm->vhosts[conf->idx].mutex;
+ array = module_globals->mpm->vhosts[conf->idx].array;
apr_thread_mutex_lock(mutex);
-
- ...
-
+
+ if (module_globals->mpm->server_shutdown == 1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r,
+ MODNAME ": http request aborted during child process shutdown");
+ apr_thread_mutex_unlock(mutex);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
/* If the array is empty we create a new worker thread */
if (apr_is_empty_array(array))
{
- w = create_worker(module_globals->pool,r->server);
- (module_globals->mpm->vhosts[conf->idx].threads_count)++;
+ w = create_worker(module_globals->pool,r->server);
+ (module_globals->mpm->vhosts[conf->idx].threads_count)++;
}
else
{
w = *(lazy_tcl_worker**) apr_array_pop(array);
}
+
apr_thread_mutex_unlock(mutex);
+
+ apr_thread_mutex_lock(w->mutex);
+ w->r = r;
+ w->ctype = ctype;
+ w->status = init;
+ w->conf = conf;
+ apr_thread_cond_signal(w->condition);
+
+ /* we wait for the Tcl worker thread to finish its job */
+
+ while (w->status != done) {
+ apr_thread_cond_wait(w->condition,w->mutex);
+ }
+ ap_sts = w->ap_sts;
+
+ w->status = idle;
+ w->r = NULL;
+ apr_thread_cond_signal(w->condition);
+ apr_thread_mutex_unlock(w->mutex);
- ...</programlisting>
+ return ap_sts;
+}</programlisting>
<para>
- After a request is processed the Tcl worker thread returns its own
+ After a request is processed the worker thread returns its own
lazy_tcl_worker descriptor to the array and then waits
on the condition variable used to control and synchronize the bridge
- threads with the Apache worker threads.
+ threads with the Apache worker threads. The worker thread code
+ is the request_processor function
</para>
- <programlisting> /* rescheduling itself in the array of idle threads */
+ <programlisting>*
+ * -- request_processor
+ *
+ * The lazy bridge worker thread. This thread prepares its control data and
+ * will serve requests addressed to a given virtual host. Virtual host server
+ * data are stored in the lazy_tcl_worker structure stored in the generic
+ * pointer argument 'data'
+ *
+ */
+
+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;
+ int idx;
+ rivet_server_conf* rsc;
+
+ /* The server configuration */
+
+ rsc = RIVET_SERVER_CONF(w->server->module_config);
+
+ /* Rivet_ExecutionThreadInit creates and returns the thread private data. */
+
+ private = Rivet_ExecutionThreadInit();
+
+ /* A bridge creates and stores in private->ext its own thread private
+ * data. The lazy bridge is no exception. We just need a flag controlling
+ * the execution and an intepreter control structure */
+
+ private->ext = apr_pcalloc(private->pool,sizeof(mpm_bridge_specific));
+ private->ext->keep_going = 1;
+ private->ext->interp = Rivet_NewVHostInterp(private->pool,w->server);
+ private->ext->interp->channel = private->channel;
+
+ /* The worker thread can respond to a single request at a time therefore
+ must handle and register its own Rivet channel */
+
+ Tcl_RegisterChannel(private->ext->interp->interp,*private->channel);
+
+ /* From the rivet_server_conf structure we determine what scripts we
+ * are using to serve requests */
+
+ private->ext->interp->scripts =
+ Rivet_RunningScripts (private->pool,private->ext->interp->scripts,rsc);
+
+ /* This is the standard Tcl interpreter initialization */
+
+ Rivet_PerInterpInit(private->ext->interp,private,w->server,private->pool);
+
+ /* The child initialization is fired. Beware of the terminologic
+ * trap: we inherited from prefork only modules the term 'child'
+ * meaning 'child process'. In this case the child init actually
+ * is a worker thread initialization, because in a threaded module
+ * this is the agent playing the same role a child process plays
+ * with the prefork bridge */
+
+ Lazy_RunConfScript(private,w,child_init);
+
+ /* The thread is now set up to serve request within the the
+ * do...while loop controlled by private->keep_going */
+
+ idx = w->conf->idx;
+ apr_thread_mutex_lock(w->mutex);
+ do
+ {
+ module_globals->mpm->vhosts[idx].idle_threads_cnt++;
+ while ((w->status != init) && (w->status != thread_exit)) {
+ apr_thread_cond_wait(w->condition,w->mutex);
+ }
+ if (w->status == thread_exit) {
+ private->ext->keep_going = 0;
+ continue;
+ }
+
+ w->status = processing;
+ module_globals->mpm->vhosts[idx].idle_threads_cnt--;
+
+ /* Content generation */
+
+ private->req_cnt++;
+ private->ctype = w->ctype;
+
+ w->ap_sts = Rivet_SendContent(private,w->r);
+
+ if (module_globals->mpm->server_shutdown) continue;
+
+ w->status = done;
+ apr_thread_cond_signal(w->condition);
+ while (w->status == done) {
+ apr_thread_cond_wait(w->condition,w->mutex);
+ }
+
+ /* rescheduling itself in the array of idle threads */
- 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);</programlisting>
+ 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 (private->ext->keep_going);
+ apr_thread_mutex_unlock(w->mutex);
+
+ ap_log_error(APLOG_MARK,APLOG_DEBUG,APR_SUCCESS,w->server,"processor thread orderly exit");
+ Lazy_RunConfScript(private,w,child_exit);
+
+ apr_thread_mutex_lock(module_globals->mpm->vhosts[idx].mutex);
+ (module_globals->mpm->vhosts[idx].threads_count)--;
+ apr_thread_mutex_unlock(module_globals->mpm->vhosts[idx].mutex);
+
+ apr_thread_exit(thd,APR_SUCCESS);
+ return NULL;
+}</programlisting>
<para>
The lazy bridge <command>module_globals->bridge_jump_table->mpm_thread_interp</command>, which
is supposed to return the rivet_thread_interp structure pointer relevant to a given
---------------------------------------------------------------------
To unsubscribe, e-mail: site-cvs-unsubscribe@tcl.apache.org
For additional commands, e-mail: site-cvs-help@tcl.apache.org