On 2013-06-12 11:48, Alex Bligh wrote:
On 12 Jun 2013, at 10:20, Sorin Manolache wrote:
If I understand correctly, the main thread belongs to your module, i.e. it is
not a concise pseudo-code of the request processing in apache's code.
The main thread is the (presumably single) thread of the prefork mpm process,
created (I assume) by a fork() in apache's worker code.
The pseudo code was what my long-running request handler does (after creating
the other thread). IE, broadly speaking my request handler (the main thread if
you like) does this:
apr_thread_create; /* create the spawned thread */
while (!done)
{
/* Blocking read */
apr_brigade_create;
ap_get_brigade;
apr_brigade_flatten;
/* Do stuff with the data */
blocking_socket_write;
}
apr_thread_join; /* wait until the spawned thread has executed */
I don't see where the output brigade appears in the main thread. I think this
is critical, as the output_bucket_brigade is the data item shared between the
two threads. ap_get_brigade triggers the execution of the chain of input
filters. One of these input filters writes to the output brigade?
ap_get_brigade is called with APR_BLOCK_READ.
What I now /believe/ this does (because it's the only way data would actually
get written) is write the post processed output bucket brigade to the client
too. If this were not the case, it's difficult to see how a single threaded
application would every write the output bucket brigade.
Or are you saying the output bucket brigade is only actually written to the
client during an ap_fwrite()? In which case are all the filters (primarily
mod_ssl) guaranteed to be thread safe if a different thread is doing input from
that doing output?
"Normally" the output brigade is only written during the
ap_rprintf/ap_fwrite and the like.
There is no output brigade when the request_rec structure is created.
The way to write something to the client is via
ap_pass_brigade(r->output_filter, brigade). Typically the function that
calls ap_pass_brigade creates the brigade first. So you write something
to the brigade and you pass it downstream. The last filter writes its
contents to the network. Be aware that there are filters that buffer the
brigades and do not send them further down the chain unless the buffers
are full.
If you created a handler that would just return OK without ever calling
an ap_rprintf/ap_fwrite, the module would create no output brigade and
the client would get no response.
I think your hypothesis is unlikely. For it to hold, you'd need an input
filter that is triggered when ap_get_brigade is called, that that input
filter creates a brigade and stores it somewhere and that the spawned
thread somehow writes to this stored brigade. So the ap_fwrite in the
spawned thread would need to write to a brigade created in an input
filter triggered by ap_get_brigade in the main thread.
To verify this hypothesis, check which is the brigade whose pointers are
corrupted. I mean, where is it referenced, in which apache module, in
which apache filter. Then you can inspect the sources of that module to
see if the brigade is shared between input and output.
S