Reputation: 2951
I am in Windows running a Perl script that calls an executable:
$command = "$path_to_exe -i $dir -o $results";
my $pid = fork();
if ( !$pid ) {
system($command);
#do stuff
} else {
#do stuff
}
print "Exiting..."
exit;
Instead of exiting after, perl.exe just idles. A pop-up then tells me that the "Perl command line interpreter has stopped working."
I don't know very much about process management in Windows, and I have read previously on this forum that it's not good practice to use fork()
and exec()
, but the code works well besides the interpreter not closing part. I've tried everything from trying to implement the program in Unix (which gives the same error) to using Win32::Process
commands -- but nothing works. I hoped there might be a simpler solution that would allow me to preserve what I've already written.
If anyone could explain what exactly is happening in Windows when this code is run, that would be a help too!
Upvotes: 5
Views: 2261
Reputation: 136
In my case I removed some "use" statements and it was solved. It probably happens because the perl implementation for "fork" on Windows isn't perfect and has problems importing some "heavy" object such as the OLE library.
The exact uses I removed:
#use Win32::OLE qw(in with);
#use Win32::OLE::Const 'Microsoft Excel';
Workaround: if possible, try import dynamically the libraries after the point there is no fork in the code.
Example for my case:
# code with fork
eval "use Win32::OLE::Const 'Microsoft Excel';";
eval "use Win32::OLE qw(in with);";
# code without fork
Upvotes: 1
Reputation: 1
I can see 2 independent problems.
system()
creates a child process, thus if you call a system()
from a forked child, you will have 3 processes. But you kill only the second (the forked child), and the child of the child (the $command) not. Try to use some function like exec()
, on unix it starts the child process on the place (and on the pid) of the actual process. If you have luck, Perl on Windows does the same.
in the parent thread you kill $$
, which is the current process. Probably you wanted to kill $pid
(which is the pid of the child process on the parent thread).
Upvotes: 4
Reputation: 2951
I used the following (it times out the program and, most importantly, doesn't break the Perl interpreter!):
use Win32::Job;
my $job = Win32::Job->new;
# Run $command for $max_time
$job->spawn($Config{"path/cmd.exe"}, $command);
$job->run($max_time);
exit;
Upvotes: 1