[FASTCGI] libfcgi in multi threaded app
Rob
rclemley at booksys.com
Mon May 3 13:05:40 EDT 2010
On 05/03/2010 10:27 AM, AlannY wrote:
> I've created a socket via FCGX_OpenSocket. Everything all right.
>
> Then, I'm creating threads (5, for example). In each thread, I'm
> creating a request with FCGX_InitRequest (with socket, created early and
> FCGI_FAIL_ACCEPT_ON_INTR).
>
> Then the main loop starts. In this loop I'm calling FCGX_Accept_r on
> this request. Here is trouble. Some of threads can successfully accept,
> but some of then can't. Return code from FCGX_Accept is -9.
The main thread loop should repeatedly call FCGX_Accept_r(). Requests
successfully accepted by FCGX_Accept_r() must then be passed off to your
worker threads for processing. Therefore, you might choose to
dynamically allocate an fcgi request structure before calling
FCGX_Accept_r() and then pass the dynamically allocated request
structure to an available worker thread. The worker thread would then
process the request and then deallocate the request.
The multi-threaded problem is: "how to pass the requests to the worker
threads?" Your program will be simple and graceful if you choose the
means of a synchronized queue data structure. In a synchronized queue
object, all of the thread synchronization is performed upon access to
get or put items on the queue. The mutex guards access to the internal
data. The conditions NotFull and NotEmpty signal the threads to wake up
appropriately via the condition primitives: notify_one or notify_all.
We use C++ and boost::threads to do something like this:
pseudo code for main thread:
synchronized_queue_class synchronized_queue #this is the only
object that must be visible from all threads
function get_fcgi_request( request )
request = allocate(sizeof request)
FCGX_init_request(request ...)
if FCGX_Accept_r(request) is successful
then return TRUE
else return FALSE
endif
endfunction
while get_fcgi_request( request )
synchronized_queue.Put(request)
endwhile
pseudo code for worker threads:
while synchronized_queue.Get(request)
process(request)
deallocate(request)
endwhile
pseudo code for synchronized_queue_class:
class synchronized_queue_class:
queue internal_queue
condition notFull_condition
condition notEmpty_condition
mutex monitor
procedure Put(item):
scoped_lock(monitor)
while internal_queue.full()
notFull_condition.wait(monitor)
internal_queue.put(item)
notEmpty_condition.notify_one()
endprocedure
procedure Get(item):
scoped_lock(monitor)
while internal_queue.empty:
notEmpty_condition.wait(monitor)
internal_queue.push(item)
notFull_condtion.notify_one()
endprocedure
endclass
(There are other details in the synchronized queue which should be
addressed, such as how to shut down the queue at the end of the program
and tell the worker threads to exit.)
More information about the FastCGI-developers
mailing list