Re: Threaded C fcgiapp implementation problems and questions

"Jonathan Gray" <[email protected]>
Newsgroups gmane.comp.web.fastcgi.devel
Message-ID <[email protected]>
If I disable keep-alives in lighttpd, I no longer see lots of connections
in lighttpd status in the read state.  That seems to have been tied to
keep-alives.

How does that work with fastcgi and fcgiapp?  Is there anything i need to
do to be able to take advantage of keep-alives?  The build-up of extra
connections in weird states leads me to believe that the keep-alives are
not working.

On Wed, April 22, 2009 12:54 pm, Jonathan Gray wrote:
> Hello,
>
>
> I have a multithreaded, C FastCGI script using the fcgiapp library
> running on top of lighttpd.
>
> I'm having a recurring problem on my production environment that crops up
>  after a few days straight of load around 20-40 concurrent connections.
>
> This script is implementing something called COMET
> http://en.wikipedia.org/wiki/Comet_(programming)
>
>
> It's basically using AJAX/XHR requests to simulate pushing to the client.
>  The user opens an AJAX request to the script and the server keeps it
> loading until a message comes in from the server (it connects to a central
>  server which sends messages to clients), or until we time it out.  On
> the wikipedia page, this is described as Ajax with long polling /
> XMLHttpRequest long polling.
>
>
> This has been working for a very long time but recently as load has been
> increasing we started to see a weird behavior.
>
> All of a sudden, lighttpd/mod_fastcgi will start to reject all new
> connections.  The log shows this error:
>
> 2009-04-01 12:21:33: (mod_fastcgi.c.3005) got proc: pid: 3664 socket:
> unix:/home/user/cgi/socks/event.sock-0 load: 25
> 2009-04-01 12:21:33: (mod_fastcgi.c.2494) unexpected end-of-file (perhaps
> the fastcgi process died): pid: 3664 socket:
> unix:/home/user/cgi/socks/event.sock-0
>
>
>
> The process is not dead, there are 24 other connections that are
> currently being properly handled.  When these requests come in, the script
> does not see them at all (ie. FCGX_Accept_r does not return).
>
> After all the existing connections have dropped, it will then continue
> normal operation and start to accept new connections:
>
> 2009-04-01 12:22:00: (mod_fastcgi.c.1515) released proc: pid: 3664
> socket:
> unix:/home/user/cgi/socks/event.sock-0 load: 2
> 2009-04-01 12:22:01: (mod_fastcgi.c.1515) released proc: pid: 3664 socket:
>  unix:/home/user/cgi/socks/event.sock-0 load: 1
> 2009-04-01 12:22:03: (mod_fastcgi.c.1515) released proc: pid: 3664 socket:
>  unix:/home/user/cgi/socks/event.sock-0 load: 0
>
>
> and then
>
> 2009-04-01 12:22:03: (mod_fastcgi.c.3005) got proc: pid: 3664 socket:
> unix:/home/user/cgi/socks/event.sock-0 load: 1
>
>
> The same PID (the process never crashed) then does start to see new
> connections and things go for another few days without problems, then the
> same thing happens again.
>
>
> The design of my application differs from the example threaded
> application because I do not keep a thread per connection, rather I use
> queues, timers, hash tables, etc to track the state of sessions and their
> FCGX_Request.
>
>
> Since I can't just use a FCGX_Request per thread, as done in the example,
>  I pre-instantiate a large array of FCGX_Requests of size
> MAX_ALLOC_REQUESTS.  I then loop through this array, sliding down one
> index each time.  This array is significantly large that I do not get
> anywhere close to reusing a request that was not FCGX_Finish_r'd already.
>  (this is set to 25,000 right now, in benchmarking i'm trying to get over
>  10k.  i am nowhere near this in production where the bug happens).
>
>
> Is this a sane approach?  Could I be messing something up with my
> allocating so many and doing FCGX_InitRequest on each.
>
> for(i=0;i<MAX_ALLOC_REQUESTS;i++) FCGX_InitRequest(&reqs[i],0,0);
>
>
> I am locking around the accept, so the accepting of connections is
> single-threaded:
>
>
> pthread_mutex_lock(&accept_mutex); rc = FCGX_Accept_r(&reqs[curreq]);
> nextreq = (curreq + 1) % MAX_ALLOC_REQUESTS;
> pthread_mutex_unlock(&accept_mutex);
>
>
> I have two potential threads that can close the connection.  In all
> cases, the closing of the connection follows the form:
>
> FCGX_FPrintF(request->out,"...");
> FCGX_Finish_r(request);
>
>
>
> That request is still part fo the reqs[] and will be called again, much
> later, with FCGX_Accept_r.
>
> Again, is this right?  I read that FCGX_Finish_r is thread-safe, so I'm
> not locking around that, there are potentially two threads running FPrintF
>  and Finish_r simultaneously (but ALWAYS on different FCGX_Requests).
>
>
> I have increased all kinds of system limits like file/socket descriptor
> limits and memory limits.  I have seen the requests "loop" through the big
>  array of pre-allocated ones, and they are reused without a problem.
>
> One thing i'm also not sure about is how keep-alives and pipelining might
>  interact with what i'm doing.  When looking into the lighttpd status
> page, sometimes I noticed connections, after they are out of handle-req
> and the script has returned/finish_r'd it, they sit in a 'read' state for
> some time.  The only pointer I've got w.r.t. that was it might be trying
> to read another request from the client?
>
>
> I'd really appreciate any kind of help.  I'm a bit stuck and in any case
> could use some best practices advice.
>
> Thanks.
>
>
> Jonathan Gray
> _______________________________________________
> FastCGI-developers mailing list
> FastCGI-developers-xGejAJT2w6xVgU18Zptdi0EOCMrvLtNR@public.gmane.org
> http://mailman.pins.net/mailman/listinfo.cgi/fastcgi-developers
>
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.