Should I disable the buffer to launch a background process in a CGI program?
In my Perl/CGI web application, I sometimes need to run a long process which makes the wait for the next page interminable. So I've been disabling the buffer as below so that the page contents get sent before the long process runs.
local $| = 1;
print "Content-type: text/html\n\n";
print $output;
&background_process();
However it seems to me that the buffer has its uses and I sh开发者_运维问答ould not be in the habit of doing this. Is there a better way to run a long process and still return html to the client quickly? Should I be forking or somesuch?
Here is some code I use to spawn off a background process in my FastCGI script:
$SIG{CHLD} = 'IGNORE';
# This should flush stdout.
my $ofh = select(STDOUT);$| = 1;select $ofh;
my $kpid = fork;
if ($kpid)
{
# Parent process
waitpid($kpid, 0);
}
else
{
close STDIN;
close STDOUT;
close STDERR;
setsid();
my $gpid = fork;
if (!$gpid)
{
open(STDIN, "</dev/null") ;
open(STDOUT, ">/dev/null") ;
open(STDERR, ">/dev/null") ;
# Child process
exec($pgm, @execargs) ;
}
exit 0;
}
A couple of salient points here:
- I ignore SIGCHLD, which is the signal you get when your child process exits.
- I flush STDOUT, so the web browser gets the whole page.
- I fork twice to make sure that the web server will be able to exit even if the process I'm trying to spawn is still running.
- I redirect all the standard file descriptors to make sure that the grandchild process is fully detached from the parent.
The best way is to fork your process and put it in the background. That way it won't be stopped by the user leaving the page, and the page will not be in a loading state in the web browser all the time.
精彩评论