Question

I have a Perl plugin that takes a while in order to complete operations. That plugin is usually launched via web from a CGI interface that is supposed to send it in the background and immediately print a message. Unfortunately I couldn't find a way to do that. I mean the CGI correctly starts the plugin but it also waits for it to complete wich I don't want to happen. I tryed with &, with fork, with detach, even with Proc::Background, no luck so far. I am quite sure that the problem is related to the CGI but I'd like to know why and, if possible, to fix this. Here are the codes I tryed, please keep in mind that all methods work great from console, it is just CGI that creates problem.

# CGI
my $cmd = "perl myplugin.pl";

# Proc::Background
my $proc = Proc::Background->new($cmd);
# The old friend &
system("$cmd &");
# The more complicated fork
my $pid = fork;
if ($pid == 0) {
    my $launch = `$cmd`;
    exit;
}
# Detach

print "Content-type: text/html\n\n";
print "Plugin launched!";

I know that there is a similar question on StackOverflow but as you can see it does not solve my problem.

Was it helpful?

Solution

Have your child process close or dup away its inherited standard out and standard error, so that Apache knows it is free to respond to the client. See merlyn's article on the subject.

Example:

system("$cmd >/dev/null 2>&1 &");

Though I shudder to see system("$cmd ...").

OTHER TIPS

This is basically a Perl implementation of what the shell is doing behind the scenes in pilcrow's answer. It has two potential advantages, it does not need to use the shell to call your second script, and it provides better user feedback in the rare case that the fork fails.

my @cmd = qw(perl myplugin.pl);

my $pid = fork;
if ($pid) {
    print "Content-type: text/html\n\n";
    print "Plugin launched!";
}
elsif (defined $pid) {
    # I skip error checking here because the expectation is that there is no one to report the error to.
    open STDIN,  '<', '/dev/null';
    open STDOUT, '>', '/dev/null'; # or point this to a log file
    open STDERR, '>&STDOUT';
    exec(@cmd);
}
else {
    print "Status: 503 Service Unavailable\n";
    print "Content-type: text/html\n\n";
    print "Plugin failed to launch!";
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top