in t/modules/proxy_fcgi.t [50:110]
sub run_fcgi_handler($$)
{
my $fcgi_port = shift;
my $handler_func = shift;
# Use a pipe for ready-signalling between the child and parent. Much faster
# (and more reliable) than just sleeping for a few seconds.
pipe(READ_END, WRITE_END);
my $pid = fork();
unless (defined $pid) {
t_debug "couldn't fork FCGI process";
ok 0;
exit;
}
if ($pid == 0) {
# Child process. Open up a listening socket.
my $sock;
if ($fcgi_port =~ m@/@) {
$sock = FCGI::OpenSocket("$fcgi_port", 10); # uds
}
else {
$sock = FCGI::OpenSocket(":$fcgi_port", 10);
}
# Signal the parent process that we're ready.
print WRITE_END 'x';
close WRITE_END;
# Listen for and respond to exactly one request from the client.
my $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV,
$sock, &FCGI::FAIL_ACCEPT_ON_INTR);
if ($request->Accept() == 0) {
# Run the handler.
$handler_func->();
$request->Finish();
}
# Clean up and exit.
FCGI::CloseSocket($sock);
exit;
}
# Parent process. Wait for the daemon to launch.
unless (IO::Select->new((\*READ_END,))->can_read(2)) {
t_debug "timed out waiting for FCGI process to start";
ok 0;
kill 'TERM', $pid;
# Note that we don't waitpid() here because Perl's fork() implementation
# on some platforms (Windows) doesn't guarantee that the pseudo-TERM
# signal will be delivered. Just wait for the child to be cleaned up
# when we exit.
exit;
}
return $pid;
}