End Perl Script Without Waiting for System Call to Return

End perl script without waiting for system call to return

The web server creates a pipe from which to receive the response. It waits for the the pipe to reach EOF before completing the request. A pipe reaches EOF when all copies of the writer handle are closed.

The writer end of the pipe is set as the child's STDOUT. That file handle was copied to be the shell's STDOUT, and again to the mycmd's STDOUT. So even though the CGI script and the shell ended and thus closed their ends of the file handle, mycmd still holds the handle open, so the web server is still waiting for the response to complete.

All you have to do with to close the last handle to the writer end of the pipe. Or more precisely, you can avoid making it in the first place by attaching a different handle to mycmd STDOUT.

mycmd arg1 arg2 </dev/null >/dev/null 2>&1 &

How do I make a system call and resume execution without waiting for the call to return?

Short answer, no. This is the entire point of fork(). The only question is whether you call fork() directly, or get something else to do that for you.

As mentioned, you could use the shell's backgrounding operator (&) to do that, but then you're using the shell, and that comes with the usual string-injection attack problem

system("some command with args &");

More directly, you could just do the usual fork() and exec() and then not perform the waitpid() that normally happens, which is where the blocking occurs:

if(fork() == 0) {
exec("some", "command", "with", "args") or die "Cannot exec - $!";
}
# No waitpid here so no waiting

If you're doing that, best also to put a SIGCHLD handler in to ignore when the child does eventually exit, so as not to leave zombies hanging around. At some point near the beginning of the code, put

$SIG{CHLD} = 'IGNORE';

Running job in the background from Perl WITHOUT waiting for return

Essentially you need to 'daemonize' a process -- fork off a child, and then entirely disconnect it from the parent so that the parent can safely terminate without affecting the child.

You can do this easily with the CPAN module Proc::Daemon:

use Proc::Daemon;
# do everything you need to do before forking the child...

# make into daemon; closes all open fds
Proc::Daemon::Init();

Is there a Perl function like 'system' that doesn't wait for a returned value?

An exec within a fork will work without blocking execution:

if (command is bla) { 
exec "osascript 'something.app'" if fork;
} else {
print $client "invalid command\r\n";
}

How to run a script and not wait for it in Perl?

if ($^O eq 'MSWin32') {
system('start "" \\path\\to\\utility >> \\redirect\\to\\log_file');
} else {
system('/path/to/utility >> /redirect/to/log_file &');
}

or

if ($^O eq 'MSWin32') {
system(1, '\\path\\to\\utility >> \\redirect\\to\\log_file');
} else {
system('/path/to/utility >> /redirect/to/log_file &');
}

Perl script is not waiting for a .bat file to complete and continuing execution

You need to remove the start command

Without the /wait option, start will create a process and return immediately

But there is no need for start at all. You can write just

system($bat_file);

to achieve the effect that you're asking for

I have a system call that somehow is causing malformed header from script Bad header

The system command just doesn’t give you complete control over capturing STDOUT and STDERR of the executed command.

Use backticks or open to execute the command instead. That will capture the STDOUT of the command’s execution. If the command also outputs to STDERR, then you can append 2>&1 to redirect STDERR to STDOUT for capture in backticks, like so:

my $output = `$command 2>&1`;

If you really need the native return status of the executed command, you can get that information using $? or ${^CHILD_ERROR_NATIVE}. See perldoc perlvar for details.

Another option is to use the IPC::Open3 Perl library, but I find that method to be overkill for most situations.



Related Topics



Leave a reply



Submit