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

Reply via email to