Recct
Recct

Reputation: 923

Perl: When does "system" actually return?

In a CGI webpage, I have a button which when pressed submits a form and a subroutine is called which has:

sub run {
     &emailDebug("Started " .localtime);
    system("(/tools/script1.pl &) ; (/tools/script2.pl &)");
    &emailDebug("Ended " .localtime);
}

They both start at 11:08:05 (hence the fancy command), I take timestamps in the scripts themselves and send them in an email to myself.

The second finished 11:08:22 and the first 11:08:36 but the sent emails from above would show 11:08:06.

Most interestingly, the page is loading for about 30 seconds, as long as the longer of the two scripts run.

I don't mind the page loading but I don't understand why it behaves like this. As the page is loading, clearly the subroutine run itself doesn't return, but both emails are sent almost at the same time.

Upvotes: 3

Views: 190

Answers (3)

Borodin
Borodin

Reputation: 126732

What do you mean by those print statements above? Your code shows no print calls

Your run subroutine is returning as soon as the two child processes are started. You could make things clearer by making two calls to system and removing the parentheses in the command lines. Because of the trailing ampersand both calls to system will return immediately leaving the children to run independently

Something else must be delaying the return of the page after the call to run, and presumably it is somehow detecting when the work of the child processes is complete

By the way, you should never use an ampersand on a subroutine name when you are making a simple call. It hasn't been necessary since we got Perl 5 eighteen years ago

Upvotes: 1

Oleg V. Volkov
Oleg V. Volkov

Reputation: 22421

system returns as soon as command that you call lets it to. In this particular example it should return immediately, but this may break depending on shell. To be extra sure you might try to just split call in two:

system("/tools/script1.pl &");
system("/tools/script2.pl &");

Also, depending on your web-server configuration, it may notice that you still have STDOUT open in forked childs and it will wait for all them to end before serving response, even if your main script is already ended. Redirect your spawned scripts STDOUT/ERR to /dev/null, close(STDOUT) and close(STDERR) in main script or consult your web-server/framework documentation on how to flush response when you're done with output.

Upvotes: 6

perreal
perreal

Reputation: 97968

You are executing the scripts as background processes so system returns immediately. If you want to wait for completion then remove the &s and execute them sequentially:

system("(/tools/script1.pl) ; (/tools/script2.pl)");

Upvotes: 2

Related Questions