I’m having a little problem with nginx and the Perl FCGI module. I have a long operation in my FCGI program that may outlive the server (or the user on the server) on the other end of the Unix socket I’m using to communicate FCGI. I need the FCGI accept() loop in my program to break if the FCGI request is closed. I tried installing INT, TERM, etc signal handlers, but they do nothing, since the only communication between nginx and my program happens over the FCGI socket, AFAIK.
I also tried this but there’s no way that I can see to use the FCGI module in Perl to send raw data to or from nginx over the FCGI socket. Is there a way I can do it without modifying the FCGI module to have a “ping” function?
The basic problem is that my program does not know if nginx has terminated the FCGI request.
Example:
#!/usr/bin/perl -w
use strict;
use FCGI;
my $fcgi_socket = FCGI::OpenSocket( '/tmp/test.socket', 100000 );
my $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV, $fcgi_socket);
REQUEST: while($request->Accept() >= 0) {
#begin handling request
my $result = '';
while (1) { #or select(), etc
if (somehow check whether the fcgi $request is still live) {
next REQUEST;
}
#check for results, set $result if done
}
print $result;
}
You have to use a
FCGIimplementation which treatsFCGI_ABORT_REQUEST.You cannot use the following, because they ignore
FCGI_ABORT_REQUEST:You could use the following, which treat
FCGI_ABORT_REQUEST:When using
AnyEvent-FCGI, checking for an aborted request is as easy as calling$request->is_active(), but keep in mind thatis_active()will not reflect the true state of the request until theon_requesthandler returns, which means you have to return fromon_requestas soon as possible and somehow do the actual work “in parallel” (you probably don’t want to use Perl threads, but something more akin to continuations) in order to give theAnyEventloop the opportunity to process any further requests (includingFCGI_ABORT_REQUESTs) while you are completing the long-winded operations.I am not familiar enough with
AnyEventto know for sure whether there is a better way of doing this, but here’s my take, below, for a start: