Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

open(TO, "|-") is a bad file name?

by SavannahLion (Pilgrim)
on Feb 24, 2004 at 01:36 UTC ( [id://331278] : perlquestion . print w/replies, xml ) Need Help??

SavannahLion has asked for the wisdom of the Perl Monks concerning the following question:

I have a process that I would like to fork at least three times. Twice to launch little helper apps on my PC and another to do some tiddly stuff with another running application.
I have zero problems creating three seperate scripts to do what I want them to do. But I want to merge the code from all three into one single script. So I figured a fork would work nicely. Problem is, all the examples I've seen out there show how to Fork only once. For example:
FORK: { if ($pid = fork) { #Parent here. #Child process pid is available in $pid } elsif (defined $pid) { #pid is zero here if defined #child here #parent process pid is available with getppid (Not available wit +h Windows). } elsif ($! == EAGAIN) { #EAGAIN is supposedly recoverable fork error sleep 5; redo FORK; } else { #Weird fork error die "Can't fork: $!\n"; } }

No problem with two things. But how do I get three going? So I looked around and figured maybe I should create a pipe the forked children and tell it what I want it to do (two of the processes launch help apps, so they use the same generic code). So I looked in the camel and located the following snippet:

if (open(TO, "|-")) { print TO $fromparent; } else { $tochild = <STDIN>; #Do whatever with $child exit; };
OK. So, put my pieces together, run script and it dies with, "Bad command or file name."
That's nice, after a bit of testing, I figure out that Windows thinks I want a file named |-.
Now I'm stuck. Did a search for |- and only one node came up. Not what I was looking for.

So then I tried "Pipe Child" and "Pipe STDIN" and couldn't discover the little nugget.
I did however, find a hint, "pipe," and I think I can utilize this to communicate to my children. Problem is, I'm not sure how this is done. The format follows something like, pipe READHANDLE,WRITEHANDLE. I figure I could use the $pid of the child, but what do I used for the WRITEHANDLE?

Again, the Camel has another example on how to use Pipe to communicate with children. I type the code example in the book to open a pipe to my child:

pipe(FROM_PARENT, TO_CHILD) or die "pipe: $!"; select((select(TO_CHILD), $| = 1))[0]);
And the Perl script dies with a "Not enough arguments for select system call" along with a syntax error.... grrr.....
I've examined this code and compared it to the book character and character. I've left the entire script out, but the code is exactly as it's presented to me in the Camel.

I can't believe that Pipe is a UNIX only function. I swear on my left nut, I've used it in Windows environment before. But if Pipe is a UNIX only function, what is the comparable Windows call? How can I communicate to my children? Besides gathering the family together for dinner.

Thanks for your patience.
Prove your knowledge @ HLPD

Replies are listed 'Best First'.
Re: open(TO, "|-") is a bad file name?
by ysth (Canon) on Feb 24, 2004 at 03:41 UTC
    Re: not enough arguments for select; look at your select, not at the pipe :) Can you spot the difference here:
    $ c:/perl/bin/perl -we'select((select(TO_CHILD), $| = 1))[0]);' Not enough arguments for select system call at -e line 1, near "))" syntax error at -e line 1, near ")[" Execution of -e aborted due to compilation errors. $ c:/perl/bin/perl -we'select((select(TO_CHILD), ($| = 1))[0]);' Name "main::TO_CHILD" used only once: possible typo at -e line 1.
    For multiple forks, you should be able to just put a for my $childnum (1..3) { ... } around your FORK block and have conditional code to do different things based on $childnum in the child section.

    Don't know anything about |- on windows (other than that it works with cygwin :), sorry.

      Hmmm, that is so interesting. I've been banging my head on a typo from the Camel?
      After reading your post, I went back and compared
      select((select(TO_CHILD), $| = 1))[0]);
      between what I wrote and the book. That is exactly as it appears in the 3rd edition of the Camel under Bidirectional Communication on page 432.

      Thank you for the $childnum suggestion, but where am I supposed to get that value from? The $pid results in a negative number for me. Searching for $childnum reveals only two nodes. And a search on PerlDoc turns up nothing :(

      Thanks for your patience.
      Prove your knowledge @ HLPD

        $childnum has no special meaning; I was just suggesting that you loop through the fork code three times, doing different things in the "child" section for each iteration (but making sure the child execs or exits or something rather than continuing the loop.)
Re: open(TO, "|-") is a bad file name?
by BUU (Prior) on Feb 24, 2004 at 08:02 UTC
    Perhaps I'm over looking something, but why not just, (assuming you need no interprocess communication, cause thats icky)
    my $id = fork; if( not $id ) { #child 1, assuming no errors exit; } my $id2 = fork; if( not $id2 ) { #child 2,etc exit; } #parent exit;
Re: open(TO, "|-") is a bad file name?
by promethyl (Initiate) on Feb 25, 2004 at 16:51 UTC
    The only time you can pipe in Windows (that i know of) is during programme invocation on the command line or in batch.