[FASTCGI] libfcgi in multi threaded app

Dave Bender codehero at gmail.com
Mon May 3 13:22:35 EDT 2010


I'm also curious, how does the library even accept multiple requests
simultaneously when the librar returns the following values for its
management records:

            if(strcmp(name, FCGI_MAX_CONNS) == 0) {
                value = '1';
            } else if(strcmp(name, FCGI_MAX_REQS) == 0) {
                value = '1';
            } else if(strcmp(name, FCGI_MPXS_CONNS) == 0) {
                value = '0';
            } else {
                name = NULL;
            }
(taken from fcgiapp.c, version 2.4.0)

According to the spec, the web server should only be sending 1 at a time.

-Dave

On Mon, May 3, 2010 at 1:14 PM, Martin Chapman <chapmanm at pixia.com> wrote:

> Rob,
>
> So how does this solution account for the fact that FCGX_Accept_r () resets
> the stdio global structure each time it's called?  If you are synchronizing
> the code between each request, regardless of it's processed on a separate
> worker thread then only one request at a time is really being executed.
>
> Martin
>
>
> -----Original Message-----
> From: fastcgi-developers-bounces+chapmanm=pixia.com at mailman.fastcgi.com
> [mailto:fastcgi-developers-bounces+chapmanm<fastcgi-developers-bounces%2Bchapmanm>
> =pixia.com at mailman.fastcgi.com]
> On Behalf Of Rob
> Sent: Monday, May 03, 2010 11:06 AM
> To: fastcgi-developers at mailman.pins.net
> Subject: Re: [FASTCGI] libfcgi in multi threaded app
>
>  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.)
>
>
>
>
>
> _______________________________________________
> FastCGI-developers mailing list
> FastCGI-developers at mailman.fastcgi.com
> http://mailman.pins.net/mailman/listinfo.cgi/fastcgi-developers
>
> _______________________________________________
> FastCGI-developers mailing list
> FastCGI-developers at mailman.fastcgi.com
> http://mailman.pins.net/mailman/listinfo.cgi/fastcgi-developers
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.pins.net/mailman/private.cgi/fastcgi-developers/attachments/20100503/7dbd714f/attachment-0001.html>


More information about the FastCGI-developers mailing list