On Mon, Aug 12, 2019 at 4:33 PM Don Poitras <don.poit...@sas.com> wrote: > > Eric, > I'm not sure what you're asking. The global mutex will cover the call to > init_conn_pool(), so there isn't a problem with worker->cp getting overlayed > if that's what you're thinking.
I am thinking the opposite. Two threads interleaved in ap_proxy_initialize_worker could both think they're initializing the worker. When the 2nd one gets blocked halfway through in the global mutex, the first will have created worker->cp->pool, left, and begin using it (for the DNS calls). > The problem is that ap_proxy_initialize_worker() gets called repeatedly with > the same worker pointer. The first time it's called for a particular worker, > it creates a connection pool and the worker thread mutex. > But _every_ use of worker->cp->pool must be serialized. Yes, minus the direct constructor call that only creates a subpool. > Subsequent calls to ap_proxy_initialize_worker() with the same worker pointer > will use the pool and mutex created in the first call. It's only these calls > after the first that are at risk for concurrent use of the pool (hence my use > of the 'notfirst' flag). In the first call, I don't even bother getting the > proxy mutex as there isn't any way for other threads to be using the pool > before it's created. I think the first thread has to grab the thread mutex it just created if the global lock is not held earlier than it is today (to make checking the initialization state safer). Another route to safety is to create the mutex when the worker is defined since this is at startup rather than this lazy load but it is probably a riskier change.