From m at alanny.ru Mon May 3 11:27:24 2010 From: m at alanny.ru (AlannY) Date: Mon, 03 May 2010 19:27:24 +0400 Subject: [FASTCGI] libfcgi in multi threaded app Message-ID: <4BDEEB5C.4060509@alanny.ru> Hi there. I'm having trouble with libfcgi and my multi threaded application. 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. I've tried to setup mutex before and after FCGX_Accept_r, but it's not helps ;-( At the end of thread, I'm calling FCGX_Finish_r with 0 (don't destroy socket, because it may be used by another thread). What can I do? How to sync threads? P.S. Single threaded apps works well ;-( -- )\._.,--....,'``. /, _.. \ _\ (`._ ,. `._.-(,_..'--(,_..'`-.;.' From chapmanm at pixia.com Mon May 3 12:56:09 2010 From: chapmanm at pixia.com (Martin Chapman) Date: Mon, 3 May 2010 10:56:09 -0600 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: <4BDEEB5C.4060509@alanny.ru> References: <4BDEEB5C.4060509@alanny.ru> Message-ID: <6A3C3B09441A4EE2B33CBB0A82A18EED@chapmanm64> AlannY, Here is the bad news. Although the website claims that you can do this, you really cannot run multiple fastcgi accepts in a true mutli threaded fashion without modification to the code. The reason for this is because fastcgi stores the stdio handles in a global structure that is not thread safe. The example they provide launches multiple threads but in order to have it work correctly you have to synchronize all the code between the accept and the finish calls which defeats the purpose of having multiple threads in the first place. This is what happens when you let multiple threads run simultaneously using fastcgi: 1. All threads launch and they all block on FCGX_Accept_r until a request is received. 2. The first request is received by a single thread and the thread starts to process the request. 3. A second request is received by another thread before the first thread is finished and when this happens the stdio variables in the global struct are reset for the second request. 4. The first thread finishes it's processing and attempts to write its response to stdio and it hangs because the stdio variables were reset by the second thread when the second thread received the second request. That said, a dude from Apple did post a way to get around this a few months ago but I never got around to seeing if it worked and if it truly was a solution for multi threaded processing. The link is listed below: http://www.fastcgi.com/archives/fastcgi-developers/2009-December/000406.html If it works I would love to hear about it. Martin -----Original Message----- From: fastcgi-developers-bounces+chapmanm=pixia.com at mailman.fastcgi.com [mailto:fastcgi-developers-bounces+chapmanm=pixia.com at mailman.fastcgi.com] On Behalf Of AlannY Sent: Monday, May 03, 2010 9:27 AM To: fastcgi-developers at mailman.fastcgi.com Subject: [FASTCGI] libfcgi in multi threaded app Hi there. I'm having trouble with libfcgi and my multi threaded application. 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. I've tried to setup mutex before and after FCGX_Accept_r, but it's not helps ;-( At the end of thread, I'm calling FCGX_Finish_r with 0 (don't destroy socket, because it may be used by another thread). What can I do? How to sync threads? P.S. Single threaded apps works well ;-( -- )\._.,--....,'``. /, _.. \ _\ (`._ ,. `._.-(,_..'--(,_..'`-.;.' _______________________________________________ FastCGI-developers mailing list FastCGI-developers at mailman.fastcgi.com http://mailman.pins.net/mailman/listinfo.cgi/fastcgi-developers From rclemley at booksys.com Mon May 3 13:05:40 2010 From: rclemley at booksys.com (Rob) Date: Mon, 03 May 2010 12:05:40 -0500 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: <4BDEEB5C.4060509@alanny.ru> References: <4BDEEB5C.4060509@alanny.ru> Message-ID: <4BDF0264.4050603@booksys.com> 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.) From chapmanm at pixia.com Mon May 3 13:14:10 2010 From: chapmanm at pixia.com (Martin Chapman) Date: Mon, 3 May 2010 11:14:10 -0600 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: <4BDF0264.4050603@booksys.com> References: <4BDEEB5C.4060509@alanny.ru> <4BDF0264.4050603@booksys.com> Message-ID: <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> 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=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 From codehero at gmail.com Mon May 3 13:22:35 2010 From: codehero at gmail.com (Dave Bender) Date: Mon, 3 May 2010 13:22:35 -0400 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> References: <4BDEEB5C.4060509@alanny.ru> <4BDF0264.4050603@booksys.com> <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> Message-ID: 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 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 > =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: From rclemley at yahoo.com Mon May 3 14:19:56 2010 From: rclemley at yahoo.com (Rob) Date: Mon, 03 May 2010 13:19:56 -0500 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> References: <4BDEEB5C.4060509@alanny.ru> <4BDF0264.4050603@booksys.com> <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> Message-ID: <4BDF13CC.20404@yahoo.com> FCGX_Accept_r() operates only on the "FCGX_Request *reqDataPtr". I cannot find where FCGX_Accept_r() resets the stdio global structure, though I do see this being done in FCGX_Accept(), which uses global variables and as such is a no-no for multi-threaded apps. A *new* FCGX_Request is allocated before each and every call to FCGX_Accept_r(). Once a request has been accepted, then the FCGX_Request structure is passed to a worker thread. After processing, the worker thread Finishes and deallocates the FCGX_Request structure. We use only the FastCGI thread-safe function calls. I've got hundreds of apache2 VirtualHosts, each running a multi-threaded FastCgiExternalServer, high traffic day-in and day-out with no multi-thread synchronization or IO problems. I cannot guarantee that this thing is doing exactly what I think it's doing, but it sure seems to work in practice, as well as in theory. In reality, only one data-stream can pass through the network interface at one time. The fact is, because each worker thread accesses only it's own FCGX_Request structure, several requests to a virtual host *appear* to be processed simultaneously. Rob On 05/03/2010 12:14 PM, Martin Chapman 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=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 From rclemley at booksys.com Mon May 3 14:27:29 2010 From: rclemley at booksys.com (Rob) Date: Mon, 03 May 2010 13:27:29 -0500 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: References: <4BDEEB5C.4060509@alanny.ru> <4BDF0264.4050603@booksys.com> <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> Message-ID: <4BDF1591.2090606@booksys.com> I cannot really address your question because you're touching deeper into the internals of libfcgi and attempting to reconcile it with "the spec", without explicit references to which part of the spec. I just don't have time to do that much research right now. I would guess that you're missing some understanding of the complete flow of processing web requests, and how the requests are handled in the various nooks and crannies of FastCGI. Rob On 05/03/2010 12:22 PM, Dave Bender wrote: > 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 > 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 > @mailman.fastcgi.com > [mailto:fastcgi-developers-bounces+chapmanm > =pixia.com > @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: From rclemley at booksys.com Mon May 3 15:30:43 2010 From: rclemley at booksys.com (Rob) Date: Mon, 03 May 2010 14:30:43 -0500 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: References: <4BDEEB5C.4060509@alanny.ru> <4BDF0264.4050603@booksys.com> <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> <4BDF1591.2090606@booksys.com> Message-ID: <4BDF2463.8090307@booksys.com> The variables mentioned (FCGI_MPXS_CONNS, FCGI_MAX_REQS, and FCGI_MAX_CONNS) are not referenced anywhere in either the libfcgi or the apache2 mod_fastcgi libraries. They are set only in the code fragment you included, but never referenced. However in the introduction to the spec, we find this (emphasis mine): After a FastCGI process accepts a connection on its listening socket, the process executes a simple protocol to receive and send data. The protocol serves two purposes. /*First, the protocol multiplexes a single transport connection between several independent FastCGI requests. This supports applications that are able to **process concurrent requests using event-driven or multi-threaded programming techniques. Second, within each request the protocol provides several independent data streams in each direction.*/ This way, for instance, both stdout and stderr data pass over a single transport connection from the application to the Web server, rather than requiring separate pipes as with CGI/1.1. By using FCGX_Accept*_r*(), which keeps these streams separate, we're able to simultaneously handle multiple FastCGI connections within one App. Also, in Appendix B, example #4, we see: 4. Two instances of example 1, multiplexed onto a single connection. The first request is more difficult than the second, so the application finishes the requests out of order: [...] I think the variables that we're discussing probably don't mean what you think they mean. Rob On 05/03/2010 01:32 PM, Dave Bender wrote: > Section 4.1 ( http://www.fastcgi.com/devkit/doc/fcgi-spec.html#SA ) > states: > > FCGI_MPXS_CONNS: "0" if this application does not multiplex > connections (i.e. handle concurrent requests over each connection), > "1" otherwise. > > Seeing as how the library is limited to 1 connection and 1 request, > > On Mon, May 3, 2010 at 2:27 PM, Rob > wrote: > > I cannot really address your question because you're touching > deeper into the internals of libfcgi and attempting to reconcile > it with "the spec", without explicit references to which part of > the spec. I just don't have time to do that much research right now. > > Section 4.1 ( http://www.fastcgi.com/devkit/doc/fcgi-spec.html#SA ) > states: > > FCGI_MPXS_CONNS: "0" if this application does not multiplex > connections (i.e. handle concurrent requests over each connection), > "1" otherwise. > > This would imply connections are handled one at a time. > > I would guess that you're missing some understanding of the > complete flow of processing web requests, and how the requests are > handled in the various nooks and crannies of FastCGI. > > Rob > > > > On 05/03/2010 12:22 PM, Dave Bender wrote: >> 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 >> > 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 >> @mailman.fastcgi.com >> >> [mailto:fastcgi-developers-bounces+chapmanm >> =pixia.com >> @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: From codehero at gmail.com Mon May 3 15:45:23 2010 From: codehero at gmail.com (Dave Bender) Date: Mon, 3 May 2010 15:45:23 -0400 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: <4BDF2463.8090307@booksys.com> References: <4BDEEB5C.4060509@alanny.ru> <4BDF0264.4050603@booksys.com> <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> <4BDF1591.2090606@booksys.com> <4BDF2463.8090307@booksys.com> Message-ID: On Mon, May 3, 2010 at 3:30 PM, Rob wrote: > The variables mentioned (FCGI_MPXS_CONNS, FCGI_MAX_REQS, and > FCGI_MAX_CONNS) are not referenced anywhere in either the libfcgi or the > apache2 mod_fastcgi libraries. They are set only in the code fragment you > included, but never referenced. > > The only way the web server knows whether the fastcgi server can actually multiplex is through these variables. These variables are what inform the web server of the fastcgi server's capabilities. libfcgi reports it is incapable of multiplexing requests. Being hard coded responses, they are trivially not referenced by the rest of the code. > However in the introduction to the spec, we find this (emphasis mine): > > After a FastCGI process accepts a connection on its listening socket, the > process executes a simple protocol to receive and send data. The protocol > serves two purposes. *First, the protocol multiplexes a single transport > connection between several independent FastCGI requests. This supports > applications that are able to process concurrent requests using > event-driven or multi-threaded programming techniques. Second, within each > request the protocol provides several independent data streams in each > direction.* This way, for instance, both stdout and stderr data pass over > a single transport connection from the application to the Web server, rather > than requiring separate pipes as with CGI/1.1. > > By using FCGX_Accept*_r*(), which keeps these streams separate, we're able > to simultaneously handle multiple FastCGI connections within one App. > Your conclusion is incorrect. There are only two input streams per request: params and stdin; these streams are not even concurrent; params must precede stdin. There are only two output streams per request: stdout and stderr. Keeping these streams separate is handled by parsing the headers of each packet, not by calling FCGX_Accept(_r) Looking through the source, the first thing that FCGX_Accept_r does is call FCGX_Finish_r. > > Also, in Appendix B, example #4, we see: > > 4. Two instances of example 1, multiplexed onto a single connection. The > first request is more difficult than the second, so the application finishes > the requests out of order: [...] > > > I think the variables that we're discussing probably don't mean what you > think they mean. > Please read the spec and the source code more carefully. > > Rob > > > > On 05/03/2010 01:32 PM, Dave Bender wrote: > > Section 4.1 ( http://www.fastcgi.com/devkit/doc/fcgi-spec.html#SA ) > states: > > FCGI_MPXS_CONNS: "0" if this application does not multiplex connections > (i.e. handle concurrent requests over each connection), "1" otherwise. > > Seeing as how the library is limited to 1 connection and 1 request, > > On Mon, May 3, 2010 at 2:27 PM, Rob wrote: > >> I cannot really address your question because you're touching deeper into >> the internals of libfcgi and attempting to reconcile it with "the spec", >> without explicit references to which part of the spec. I just don't have >> time to do that much research right now. >> >> Section 4.1 ( http://www.fastcgi.com/devkit/doc/fcgi-spec.html#SA ) > states: > > FCGI_MPXS_CONNS: "0" if this application does not multiplex connections > (i.e. handle concurrent requests over each connection), "1" otherwise. > > This would imply connections are handled one at a time. > > >> I would guess that you're missing some understanding of the complete flow >> of processing web requests, and how the requests are handled in the various >> nooks and crannies of FastCGI. >> >> > Rob >> >> >> >> On 05/03/2010 12:22 PM, Dave Bender wrote: >> >> 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 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 >>> =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: From codehero at gmail.com Mon May 3 15:51:24 2010 From: codehero at gmail.com (Dave Bender) Date: Mon, 3 May 2010 15:51:24 -0400 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: References: <4BDEEB5C.4060509@alanny.ru> <4BDF0264.4050603@booksys.com> <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> <4BDF1591.2090606@booksys.com> <4BDF2463.8090307@booksys.com> Message-ID: Please see function ProcessBeginRecord, line 1536: /* * The Web server is multiplexing the connection. This library * doesn't know how to handle multiplexing, so respond with * FCGI_END_REQUEST{protocolStatus = FCGI_CANT_MPX_CONN} */ Examining FCGX_Accept_r() indicates no more than one connection is open at a time. Since connections cannot multiplex and only one connection is open at a time, only one request may be active. On Mon, May 3, 2010 at 3:45 PM, Dave Bender wrote: > > > On Mon, May 3, 2010 at 3:30 PM, Rob wrote: > >> The variables mentioned (FCGI_MPXS_CONNS, FCGI_MAX_REQS, and >> FCGI_MAX_CONNS) are not referenced anywhere in either the libfcgi or the >> apache2 mod_fastcgi libraries. They are set only in the code fragment you >> included, but never referenced. >> >> > The only way the web server knows whether the fastcgi server can actually > multiplex is through these variables. These variables are what inform the > web server of the fastcgi server's capabilities. libfcgi reports it is > incapable of multiplexing requests. Being hard coded responses, they are > trivially not referenced by the rest of the code. > > >> However in the introduction to the spec, we find this (emphasis mine): >> >> >> After a FastCGI process accepts a connection on its listening socket, the >> process executes a simple protocol to receive and send data. The protocol >> serves two purposes. *First, the protocol multiplexes a single transport >> connection between several independent FastCGI requests. This supports >> applications that are able to process concurrent requests using >> event-driven or multi-threaded programming techniques. Second, within each >> request the protocol provides several independent data streams in each >> direction.* This way, for instance, both stdout and stderr data pass over >> a single transport connection from the application to the Web server, rather >> than requiring separate pipes as with CGI/1.1. >> >> By using FCGX_Accept*_r*(), which keeps these streams separate, we're >> able to simultaneously handle multiple FastCGI connections within one App. >> > > Your conclusion is incorrect. There are only two input streams per > request: params and stdin; these streams are not even concurrent; params > must precede stdin. There are only two output streams per request: stdout > and stderr. Keeping these streams separate is handled by parsing the headers > of each packet, not by calling FCGX_Accept(_r) > > Looking through the source, the first thing that FCGX_Accept_r does is call > FCGX_Finish_r. > >> >> Also, in Appendix B, example #4, we see: >> >> 4. Two instances of example 1, multiplexed onto a single connection. The >> first request is more difficult than the second, so the application finishes >> the requests out of order: [...] >> >> >> I think the variables that we're discussing probably don't mean what you >> think they mean. >> > > Please read the spec and the source code more carefully. > >> >> Rob >> >> >> >> On 05/03/2010 01:32 PM, Dave Bender wrote: >> >> Section 4.1 ( http://www.fastcgi.com/devkit/doc/fcgi-spec.html#SA ) >> states: >> >> FCGI_MPXS_CONNS: "0" if this application does not multiplex connections >> (i.e. handle concurrent requests over each connection), "1" otherwise. >> >> Seeing as how the library is limited to 1 connection and 1 request, >> >> On Mon, May 3, 2010 at 2:27 PM, Rob wrote: >> >>> I cannot really address your question because you're touching deeper >>> into the internals of libfcgi and attempting to reconcile it with "the >>> spec", without explicit references to which part of the spec. I just don't >>> have time to do that much research right now. >>> >>> Section 4.1 ( http://www.fastcgi.com/devkit/doc/fcgi-spec.html#SA ) >> states: >> >> FCGI_MPXS_CONNS: "0" if this application does not multiplex connections >> (i.e. handle concurrent requests over each connection), "1" otherwise. >> >> This would imply connections are handled one at a time. >> >> >>> I would guess that you're missing some understanding of the complete >>> flow of processing web requests, and how the requests are handled in the >>> various nooks and crannies of FastCGI. >>> >>> >> Rob >>> >>> >>> >>> On 05/03/2010 12:22 PM, Dave Bender wrote: >>> >>> 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 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 >>>> =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: From rclemley at booksys.com Mon May 3 19:21:14 2010 From: rclemley at booksys.com (Rob) Date: Mon, 03 May 2010 18:21:14 -0500 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: References: <4BDEEB5C.4060509@alanny.ru> <4BDF0264.4050603@booksys.com> <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> <4BDF1591.2090606@booksys.com> <4BDF2463.8090307@booksys.com> Message-ID: <4BDF5A6A.7080007@booksys.com> Dave, Unless you actually answer the question of who's using these 3 variables, this will be my last post on this thread. I know that my apps handle multi-threaded simultaneous concurrent connections to web clients via [libfcgi - mod_fastcgi - apache2 - web browsers], and both the docs and the source code support this. Further comments below: On 05/03/2010 02:45 PM, Dave Bender wrote: > On Mon, May 3, 2010 at 3:30 PM, Rob > wrote: > > The variables mentioned (FCGI_MPXS_CONNS, FCGI_MAX_REQS, and > FCGI_MAX_CONNS) are not referenced anywhere in either the libfcgi > or the apache2 mod_fastcgi libraries. They are set only in the > code fragment you included, but never referenced. > > > The only way the web server knows whether the fastcgi server can > actually multiplex is through these variables. These variables are > what inform the web server of the fastcgi server's capabilities. > libfcgi reports it is incapable of multiplexing requests. Being hard > coded responses, they are trivially not referenced by the rest of the > code. Where is the web server code which references these variables? The Apache2 mod_fastcgi module is the web server code in question (in my situation) and it doesn't use these variables. This is the crux of your claim and you haven't shown that these variables are used. > However in the introduction to the spec, we find this (emphasis mine): > > After a FastCGI process accepts a connection on its listening > socket, the process executes a simple protocol to receive and > send data. The protocol serves two purposes. /*First, the > protocol multiplexes a single transport connection between > several independent FastCGI requests. This supports > applications that are able to **process concurrent requests > using event-driven or multi-threaded programming techniques. > Second, within each request the protocol provides several > independent data streams in each direction.*/ This way, for > instance, both stdout and stderr data pass over a single > transport connection from the application to the Web server, > rather than requiring separate pipes as with CGI/1.1. > > By using FCGX_Accept*_r*(), which keeps these streams separate, > we're able to simultaneously handle multiple FastCGI connections > within one App. > > > Your conclusion is incorrect. There are only two input streams per > request: params and stdin; these streams are not even concurrent; > params must precede stdin. There are only two output streams per > request: stdout and stderr. Keeping these streams separate is handled > by parsing the headers of each packet, not by calling FCGX_Accept(_r) The way the streams are kept separate is because we pass /a different instance/ of the FCGX_Request structure to FCGX_Accept_r() every time. All communication with the web server goes through these discrete FCGX_Request structures, each of which maintains it's own streams, which in turn is reflected in the protocol. > Looking through the source, the first thing that FCGX_Accept_r does is > call FCGX_Finish_r. Which doesn't mean anything unless you re-use your FCGX_Request structure. The FCGX_Finish_r called inside Accept_r is a no-op in my case. > Also, in Appendix B, example #4, we see: > > 4. Two instances of example 1, multiplexed onto a single > connection. The first request is more difficult than the > second, so the application finishes the requests out of order: > [...] > > > I think the variables that we're discussing probably don't mean > what you think they mean. > > > Please read the spec and the source code more carefully. ??? Appendix B.4 clearly shows how the protocol maintains concurrent requests. That's a crude statement bordering on insult. Instructing me to "read more carefully?" What does that say about you? > > Rob > > > > On 05/03/2010 01:32 PM, Dave Bender wrote: >> Section 4.1 ( http://www.fastcgi.com/devkit/doc/fcgi-spec.html#SA >> ) states: >> >> FCGI_MPXS_CONNS: "0" if this application does not multiplex >> connections (i.e. handle concurrent requests over each >> connection), "1" otherwise. >> >> Seeing as how the library is limited to 1 connection and 1 request, >> >> On Mon, May 3, 2010 at 2:27 PM, Rob > > wrote: >> >> I cannot really address your question because you're touching >> deeper into the internals of libfcgi and attempting to >> reconcile it with "the spec", without explicit references to >> which part of the spec. I just don't have time to do that >> much research right now. >> >> Section 4.1 ( http://www.fastcgi.com/devkit/doc/fcgi-spec.html#SA >> ) states: >> >> FCGI_MPXS_CONNS: "0" if this application does not multiplex >> connections (i.e. handle concurrent requests over each >> connection), "1" otherwise. >> >> This would imply connections are handled one at a time. >> >> I would guess that you're missing some understanding of the >> complete flow of processing web requests, and how the >> requests are handled in the various nooks and crannies of >> FastCGI. >> >> Rob >> >> >> >> On 05/03/2010 12:22 PM, Dave Bender wrote: >>> 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 >>> > 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 >>> @mailman.fastcgi.com >>> >>> [mailto:fastcgi-developers-bounces+chapmanm >>> =pixia.com >>> @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: From codehero at gmail.com Mon May 3 23:02:14 2010 From: codehero at gmail.com (Dave Bender) Date: Mon, 3 May 2010 23:02:14 -0400 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: <4BDF5A6A.7080007@booksys.com> References: <4BDEEB5C.4060509@alanny.ru> <4BDF0264.4050603@booksys.com> <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> <4BDF1591.2090606@booksys.com> <4BDF2463.8090307@booksys.com> <4BDF5A6A.7080007@booksys.com> Message-ID: On Mon, May 3, 2010 at 7:21 PM, Rob wrote: > Dave, Unless you actually answer the question of who's using these 3 > variables, this will be my last post on this thread. > > I know that my apps handle multi-threaded simultaneous concurrent > connections to web clients via [libfcgi - mod_fastcgi - apache2 - web > browsers], and both the docs and the source code support this. > > OK I get it. I overlooked your reference to apache fast_modcgi and was only looking at libfcgi. Looking at lighttpd's mod_fastcgi, I see it along with apache also ignores management records. I guess the spec's definition of multiplexing is out of sync with current practice. Sorry for the misunderstanding. > > Looking through the source, the first thing that FCGX_Accept_r does is > call FCGX_Finish_r. > > > Which doesn't mean anything unless you re-use your FCGX_Request structure. > The FCGX_Finish_r called inside Accept_r is a no-op in my case. > It's not exactly a no-op. It seems kind of silly for FCGX_Finish_r to free all the request data (stream buffers), when immediately following it a new request will be reallocated! > > Also, in Appendix B, example #4, we see: >> >> 4. Two instances of example 1, multiplexed onto a single connection. The >> first request is more difficult than the second, so the application finishes >> the requests out of order: [...] >> >> >> I think the variables that we're discussing probably don't mean what you >> think they mean. >> > > Please read the spec and the source code more carefully. > > > ??? Appendix B.4 clearly shows how the protocol maintains concurrent > requests. > > That's a crude statement bordering on insult. Instructing me to "read more > carefully?" What does that say about you? > > It wasn't meant to be insulting, sorry if it came out like that. I think we were talking past each other. However, I think you may need to read B4 again. B4 illustrates the spec's intended method of multiplexing. It explicity says these requests are MULTIPLEXED over the SAME transport connection (in practice would be one socket fd). In this case the protocol defines a mechanism the library does not support. Everything you have talked about so far to handle multiple connections relies on the OS giving you separate fds for each request. B4 is out of sync with reality; libfcgi would return an FGCI_END_REQUEST as soon as request 2 showed its face. Sorry to be a stickler on these points, but from a syscall standpoint the distinction is big. According the original spec, multiple requests could be sent over a transport connection; libfcgi's way is to have a transport connection's lifetime bound to the lifetime of one request. While simpler than the spec's multiplexing method, the cost is extra accept(), close(), malloc(), and free() calls. > > > >> Rob >> >> >> >> On 05/03/2010 01:32 PM, Dave Bender wrote: >> >> Section 4.1 ( http://www.fastcgi.com/devkit/doc/fcgi-spec.html#SA ) >> states: >> >> FCGI_MPXS_CONNS: "0" if this application does not multiplex connections >> (i.e. handle concurrent requests over each connection), "1" otherwise. >> >> Seeing as how the library is limited to 1 connection and 1 request, >> >> On Mon, May 3, 2010 at 2:27 PM, Rob wrote: >> >>> I cannot really address your question because you're touching deeper >>> into the internals of libfcgi and attempting to reconcile it with "the >>> spec", without explicit references to which part of the spec. I just don't >>> have time to do that much research right now. >>> >>> Section 4.1 ( http://www.fastcgi.com/devkit/doc/fcgi-spec.html#SA ) >> states: >> >> FCGI_MPXS_CONNS: "0" if this application does not multiplex connections >> (i.e. handle concurrent requests over each connection), "1" otherwise. >> >> This would imply connections are handled one at a time. >> >> >>> I would guess that you're missing some understanding of the complete >>> flow of processing web requests, and how the requests are handled in the >>> various nooks and crannies of FastCGI. >>> >>> >> Rob >>> >>> >>> >>> On 05/03/2010 12:22 PM, Dave Bender wrote: >>> >>> 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 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 >>>> =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: From jon+fastcgi-developers at unequivocal.co.uk Tue May 4 06:21:03 2010 From: jon+fastcgi-developers at unequivocal.co.uk (Jon Ribbens) Date: Tue, 4 May 2010 11:21:03 +0100 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: References: <4BDEEB5C.4060509@alanny.ru> <4BDF0264.4050603@booksys.com> <585FF838A7EB4CD88CD2C05DE0BCAD0B@chapmanm64> <4BDF1591.2090606@booksys.com> <4BDF2463.8090307@booksys.com> <4BDF5A6A.7080007@booksys.com> Message-ID: <20100504102103.GJ20094@snowy.squish.net> On Mon, May 03, 2010 at 11:02:14PM -0400, Dave Bender wrote: > OK I get it. I overlooked your reference to apache fast_modcgi and was > only looking at libfcgi. Looking at lighttpd's mod_fastcgi, I see it along > with apache also ignores management records. This is a bug in Apache mod_fcgi then. > It wasn't meant to be insulting, sorry if it came out like that. I think > we were talking past each other. However, I think you may need to read B4 > again. B4 illustrates the spec's intended method of multiplexing. It > explicity says these requests are MULTIPLEXED over the SAME transport > connection (in practice would be one socket fd). In this case the protocol > defines a mechanism the library does not support. The FastCGI spec defines a system whereby there can be multiple connections to each app, and multiple requests on each connection. Apps can say that they don't support multiple requests per connection, and they can say that they don't support multiple connections. As far as I have seen, most FastCGI systems do not support multiple requests per connection. (My Python FastCGI library does, but I've never found a web server to test it with.) From m at alanny.ru Wed May 5 09:51:13 2010 From: m at alanny.ru (AlannY) Date: Wed, 05 May 2010 17:51:13 +0400 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: <4BDF0264.4050603@booksys.com> References: <4BDEEB5C.4060509@alanny.ru> <4BDF0264.4050603@booksys.com> Message-ID: <4BE177D1.4020403@alanny.ru> On 03/05/10 21:05, Rob wrote: > On 05/03/2010 10:27 AM, AlannY wrote: > 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 I've done my research. And also, I've done my program with your method from your pseudo-code (nice code). Seems, that everything works and I can handle requests in parallel. Several new problems arrived: how to shutdown FCGI socket? My program want to restart all threads, close connection, open new, create new threads. But It's not possible to create socket again, because of "Address already in use" error. I'll continue investigation. Thanks all. -- )\._.,--....,'``. /, _.. \ _\ (`._ ,. `._.-(,_..'--(,_..'`-.;.' From rclemley at booksys.com Wed May 5 11:02:44 2010 From: rclemley at booksys.com (Rob) Date: Wed, 05 May 2010 10:02:44 -0500 Subject: [FASTCGI] libfcgi in multi threaded app In-Reply-To: <4BE177D1.4020403@alanny.ru> References: <4BDEEB5C.4060509@alanny.ru> <4BDF0264.4050603@booksys.com> <4BE177D1.4020403@alanny.ru> Message-ID: <4BE18894.8000602@booksys.com> On 05/05/2010 08:51 AM, AlannY wrote: > On 03/05/10 21:05, Rob wrote: >> On 05/03/2010 10:27 AM, AlannY wrote: >> 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 > I've done my research. And also, I've done my program with your method > from your pseudo-code (nice code). > > Seems, that everything works and I can handle requests in parallel. > > Several new problems arrived: how to shutdown FCGI socket? My program > want to restart all threads, close connection, open new, create new > threads. But It's not possible to create socket again, because of > "Address already in use" error. I'll continue investigation. I'm not quite clear on the flow of your program from that description. I don't understand the how and why and the details of "restart all threads, close connection, open new, create new threads." One possibility omitted from the pseudo-code would be to call FCGX_Finish_r() in worker threads before de-allocation. Also in the "function get_fcgi_request()", the request should be deallocated if the FCGX_Accept_r() failed. Another error in the pseudo-code is that the "Get" procedure "pushes" the item instead of "popping." Some functionality is not in the pseudo code, such as how to startup and shutdown the worker threads. The pseudo-code is inconsistent: the synchronized queue "Get" procedure doesn't return a value, yet the worker thread loop tests "Get()" for true. This is a hint that the synchronized queue can have control methods and instance variables added so that the queue can be shutdown and can return false from "Get" to cause the worker threads to exit. Another problem is to detect shutdown conditions. We use signal handlers which detect shutdown events from the OS and set global variables. Before calling FCGX_Accept_r(), there's a loop which calls select() to test when data is available on the listen socket. The loop wakes up every second to check for shutdown events from the OS. If a shutdown event is detected, then the synchronized queue can be told to shutdown, returning false from the "Get" functions and causing the worker threads to exit. -- Rob From ysj.ray at gmail.com Thu May 6 22:06:56 2010 From: ysj.ray at gmail.com (Ray Allen) Date: Fri, 7 May 2010 10:06:56 +0800 Subject: [FASTCGI] Can I do some cleanup work when the request is timeout? In-Reply-To: <1658525663.20100504075528@gmail.com> References: <1658525663.20100504075528@gmail.com> Message-ID: Thanks, Daniel! You said that I can use a alarm signal to wake up my application when it's timeout, but it seems that there is no such mechanism in apache mod_fastcgi. Is there any FastCGI specification about this timeout signal? Or I have to implement it myself? On Tue, May 4, 2010 at 10:55 PM, Daniel Lo wrote: > Hello Ray, > > The first idea that comes to mind is that you can use a alarm signal to > wake up > your application and ask it to drop the connection. > > However, if you are checking your connection before you use it. You can > also > use the wait timeout from mysql. > > > http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_wait_timeout > > -daniel > > > Friday, April 30, 2010, 2:23:50 AM, you wrote: > > > Hi, all: > > > When I was using mod_fast cgi, I want to do some cleanup work when > the > > current request is timeout(the -idle-timeout configuration). How can I do > > that in my applications? For example, I want to kill a long running mysql > > connection just before the timeout. > > > > Thanks! > > > > > -- > Best regards, > Daniel mailto:wilburlo at gmail.com > > -- Ray Allen Best wishes! -------------- next part -------------- An HTML attachment was scrubbed... URL: From jsprenkle at gmail.com Thu May 6 23:24:18 2010 From: jsprenkle at gmail.com (Jay Sprenkle) Date: Thu, 6 May 2010 22:24:18 -0500 Subject: [FASTCGI] Can I do some cleanup work when the request is timeout? In-Reply-To: References: <1658525663.20100504075528@gmail.com> Message-ID: > > You said that I can use a alarm signal to wake up my application when it's > timeout, but it seems that there is no such mechanism in apache mod_fastcgi. > Is there any FastCGI specification about this timeout signal? Or I have to > implement it myself? > > You can read about signals here (if you're on linux or unix): > > http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html > -------------- next part -------------- An HTML attachment was scrubbed... URL: From scritch at gmx.de Tue May 11 07:02:45 2010 From: scritch at gmx.de (Scritch) Date: Tue, 11 May 2010 13:02:45 +0200 Subject: [FASTCGI] Java FastCGI + Lighttpd Message-ID: <4BE93955.5020004@gmx.de> Hello Everybody, I am currently writing a small script. Because I found a nice Lib that does 90% of my work, I chose Java. I wrote my mini app and installed it as a CGI script (mod_cgi). In Lighttpd. It worked fine. Because the Java VM startup time takes some time ((overall response time > 1sec), I now want to change my app to FastCGI. So I downloaded the FastCGI java apps, and changed my code accordingly. Then I configured lighty: fastcgi.server = ( "WerderWebcam.link" => (( "host" => "127.0.0.1", "port" => 10260, "bin-path" => "/bin/werder_jar", "max-procs" => 1 )) ) werder_jar is my wrapper script that starts my java class: java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9717 -DFCGI_PORT=10260 -jar /var/www/WerderWebcam.jar This does not work because my app immediately exits. With debugging I found out that the reason is because the FastCGI classes can not install themselves because the port is already used: "java.io.IOException: Port already in use". Next I checked which processes are blocking the port. To my surprise, I found out that my own script/app obviously blocks the port: (Found this by blocking my app in the debugger and thus preventing it from exiting) "lsof | grep 10260" gives me: werder_ja 5908 www-data 0u IPv4 888843 TCP localhost:10260 (LISTEN) java 5909 www-data 0u IPv4 888843 TCP localhost:10260 (LISTEN) How can such things happen? How does lighty start my script that it and its subprocesses are automatically listening on my FCGI port? This seems to be independent from the HTTP server. This post: http://software.itags.org/apache/46290/ indicates that Apache shows the same behavior. Any ideas for help? How can I get the FastCGI classes to work? From cecrume at gmail.com Tue May 11 23:16:50 2010 From: cecrume at gmail.com (Charles) Date: Tue, 11 May 2010 23:16:50 -0400 Subject: [FASTCGI] Problem with web site? Message-ID: <940D97BADD0744B9968E1D26ED177023@DEVELOPMENT> Hello; I'm new here and wanted to let someone know that on the "News" page it says: September 13th, 2008. We have updated our website! Please use the "add comment" at the bottom make suggestions to improve the various pages. We want to hear it all, spelling mistakes, grammar mistakes, suggestions and even replacement text! Only... there is no "add comment" (that I could see). Also, I run Apache 2.0 on a windows server and wanted to download the WIN32.dll -- but the links for the 1.3/2.0 dll's on the FastCGI servers page just brings up a "no page found" error. Can anyone help? Charles... ----------------------- Lowrey's Law of Expertise: Just when you get really good at something, you don't need to do it any more. -------------- next part -------------- An HTML attachment was scrubbed... URL: From cecrume at gmail.com Wed May 26 15:07:01 2010 From: cecrume at gmail.com (Charles) Date: Wed, 26 May 2010 15:07:01 -0400 Subject: [FASTCGI] FastCGI-developers Digest, Vol 22, Issue 11 References: Message-ID: Anyone?? Charles... ----------------------- Ninety-Ninety Rule of Project Schedules: The first 90% of a project takes the 1st 90% of the time. The remaining 10% of a project takes the OTHER 90% of the time. ----- Original Message ----- From: To: Sent: Wednesday, May 12, 2010 12:00 PM Subject: FastCGI-developers Digest, Vol 22, Issue 11 Send FastCGI-developers mailing list submissions to fastcgi-developers at mailman.fastcgi.com To subscribe or unsubscribe via the World Wide Web, visit http://mailman.pins.net/mailman/listinfo.cgi/fastcgi-developers or, via email, send a message with subject or body 'help' to fastcgi-developers-request at mailman.fastcgi.com You can reach the person managing the list at fastcgi-developers-owner at mailman.fastcgi.com When replying, please edit your Subject line so it is more specific than "Re: Contents of FastCGI-developers digest..." Today's Topics: 1. Problem with web site? (Charles) ---------------------------------------------------------------------- Message: 1 Date: Tue, 11 May 2010 23:16:50 -0400 From: Charles Subject: [FASTCGI] Problem with web site? To: Message-ID: <940D97BADD0744B9968E1D26ED177023 at DEVELOPMENT> Content-Type: text/plain; charset="iso-8859-1" Hello; I'm new here and wanted to let someone know that on the "News" page it says: September 13th, 2008. We have updated our website! Please use the "add comment" at the bottom make suggestions to improve the various pages. We want to hear it all, spelling mistakes, grammar mistakes, suggestions and even replacement text! Only... there is no "add comment" (that I could see). Also, I run Apache 2.0 on a windows server and wanted to download the WIN32.dll -- but the links for the 1.3/2.0 dll's on the FastCGI servers page just brings up a "no page found" error. Can anyone help? Charles... ----------------------- Lowrey's Law of Expertise: Just when you get really good at something, you don't need to do it any more. -------------- next part -------------- An HTML attachment was scrubbed... URL: ------------------------------ _______________________________________________ FastCGI-developers mailing list FastCGI-developers at mailman.fastcgi.com http://mailman.pins.net/mailman/listinfo.cgi/fastcgi-developers End of FastCGI-developers Digest, Vol 22, Issue 11 **************************************************