1

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.

Community
  • 1
  • 1
raz3r
  • 3,071
  • 8
  • 44
  • 66
  • 1
    What does *"no luck so far"* mean? Do you get errors? What errors? Do you know if `perl myplugin.pl` is being executed? How do you know? – pilcrow May 09 '12 at 13:33
  • With no luck so far I mean that it waits for _myplugin.pl_ to finish. The plugin is being executed, this is not the problem. – raz3r May 09 '12 at 13:46
  • The very basic `$cmd &` works for me, i.e. that CGI program does not wait for `myplugin.pl` to finish. Provide more details about your CGI execution environment and its configuration. Mind that you need to give enough information to [reproduce the problem](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html#showmehow). – daxim May 09 '12 at 14:01
  • Well that may be hard because as for now the only information I can give you is that CGIs are running on Apache. – raz3r May 09 '12 at 14:20

2 Answers2

4

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!";
}
Joe Orost
  • 878
  • 7
  • 12
Ven'Tatsu
  • 3,565
  • 16
  • 18
  • 1
    +1 For not using system. (I know error-checking is omitted, but I'd still suggest a die() after that exec().) – pilcrow May 09 '12 at 19:10
3

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 ...").

pilcrow
  • 56,591
  • 13
  • 94
  • 135
  • First, it works so many thanks :) Second, may I know why you think system is wierd? I want to improve my Perl skill so feel free to explain me :D – raz3r May 09 '12 at 14:40
  • 2
    I doubt pilcrow thinks it's weird. I might use the phrase distasteful. Variable interpolation in a `system` call with one argument can lead to security issues. Using the list form of `system` would prevent this, but it would also prevent the shell redirections as well. – Ven'Tatsu May 09 '12 at 14:56
  • 1
    @Ven'Tatsu: Ha. `use warnings 'distasteful';` – pilcrow May 09 '12 at 15:11
  • @pilcrow, =) I have a feeling a patch to implement that might not get accepted, but maybe a [`Perl::Critic` policy theme](http://p3rl.org/Perl::Critic#POLICY-THEMES) could be made. – Ven'Tatsu May 09 '12 at 15:23