moseley has asked for the wisdom of the Perl Monks concerning the following question:
I'm using IPC::Open3 on Win32 to avoid the shell. Notice how double quotes are handled below. I'm assuming this is a Windows issue and not a Perl issue, correct? Extra points if you can explain the logic of this. ;)
#!/usr/bin/perl -w use strict; use IPC::Open2; my @command = ( 'perl', 'my test.pl', 'first arg1', '"second arg2"', 'word "quoted" and \"backslashed\" word', '"2word "quoted" and \"backslashed\" word"', ); my $pid = IPC::Open2::open2( \*r, \*w, @command ); print "Pid = $pid\n"; print "output:\n"; print while $_ = <r>; print "done\n";
With output on Win32 as:
Pid = 316925 output: 316925 [first arg1] 316925 [second arg2] 316925 [word] 316925 [quoted] 316925 [and] 316925 ["backslashed"] 316925 [word] 316925 [2word quoted and "backslashed" word] 316925 done done
Part two of my IPC::Open3 question:
The docs say to call waitpid($pid,0) to reap the child process -- and indeed the windows process table fills up (64 processes?) if waitpid isn't called.
See, I've got a function that returns a file handle. Under Windows it uses IPC::Open3, otherwise it does a open($fh,'-|') call. So the code that calls this function isn't suppose to know or care about how that file handle is generated.
The question is about when to call waitpid() on Windows. I assume it must be called after calling close() (or after the returned file handle goes out of scope). Is that a correct assumption?
If waitpid() has to be called after the close() that means the function that returns the file handle must store the PID some place. So, seems like I need to tie the handle.
Here's my code. I have a few follow-up questions at the end:
#!/usr/bin/perl -w use strict; my %self; my @command = ( 'perl', 'my test.pl', 'one arg', '"two arg"' ); { my $fh = windows_fork( \%self, @command ); print while <$fh>; } print "out of scope\n"; exit; sub windows_fork { my ( $self, @args ) = @_; require IPC::Open2; my ( $rdrfh, $wtrfh ); # Deal with windows quotes my @command = map { s/"/\\"/g; qq["$_"] } @args; my $pid = IPC::Open2::open2($rdrfh, $wtrfh, @command ); binmode $rdrfh, ':crlf'; tie *handle, 'call_waitpid', $rdrfh, $pid; return \*handle } package call_waitpid; use strict; sub TIEHANDLE { my ( $class, $fh, $pid ) = @_; bless { handle => $fh, pid => $pid, }, $class; } sub READLINE { my ( $self ) = @_; my $fh = $self->{handle}; return <$fh>; } sub DESTROY { my ( $self ) = @_; close $self->{handle}; waitpid $self->{pid}, 0; }
Questions:
- Is this how you would deal with this issue. Use a tied handle to track the PID?
-
In READLINE I cannot do: return <$self->{handle}>; why?
syntax error at fork.pl line 81, near "<$self->{handle"
- In the "windows_fork() sub I'm blessing a typeglob. The problem is it's the same typeglob for every call to windows_fork(). So if windows_fork() is called twice the handles are mixed. I tried using gensym() but couldn't get that to work. I need a way to have more than one file handle active at a time.
Results in "other stuff" from $fh.my $fh = windows_fork( \%self, 'perl', 'my test.pl', 'first stuff'); my $fg = windows_fork( \%self, 'perl', 'my test.pl', 'other stuff'); print while <$fh>;
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: IPC::Open3 and Win32
by ikegami (Patriarch) on Sep 28, 2004 at 20:21 UTC | |
Re: IPC::Open3 and Win32
by Velaki (Chaplain) on Sep 28, 2004 at 19:25 UTC | |
by moseley (Acolyte) on Sep 28, 2004 at 23:46 UTC |