This works fine and dosn't block because STDERR is sent to STDOUT. However the original poster had to ask for them to be separated, and it turned out to be trickier than I thought. So I'm posting the code I came up with below, and wondering if it's the best way to do it. At first I thought I could just read ERROR like READ and just print out both....but no...the filehandles blocked each other and the script would hang.#!/usr/bin/perl use warnings; use strict; use IPC::Open3; #interface to "bc" calculator #my $pid = open3(\*WRITE, \*READ, \*ERROR,"bc"); my $pid = open3(\*WRITE, \*READ,0,"bc"); #if \*ERROR is false, STDERR is sent to STDOUT while(1){ print "Enter expression for bc, i.e. 2 + 2\n"; chomp(my $query = <STDIN>); #send query to bc print WRITE "$query\n"; #get the answer from bc chomp(my $answer = <READ>); print "$query = $answer\n"; }
Also a few specific questions:
(1.) If I don't put the select(undef,undef,undef,.01) delay in, the script gives it's output on the next entry. Try it and see what I mean, the output is delayed by 1 cycle. The delay fixes it.
(2.) I did the sysread with a size of 4096. How can I just read the size of the filehandle? I tried using "-s ERROR" and "-s READ" instead of 4096, but would get no output.
(3.) Is there a way to do this without IO::Select?
#!/usr/bin/perl use warnings; use strict; use IPC::Open3; use IO::Select; #interface to "bc" calculator my $pid = open3(\*WRITE, \*READ,\*ERROR,"bc"); my $selread = new IO::Select(); my $selerror = new IO::Select(); $selread->add(\*READ); $selerror->add(\*ERROR); my($error,$answer)=('',''); while(1){ print "Enter expression for bc, i.e. 2 + 2\n"; chomp(my $query = <STDIN>); #send query to bc print WRITE "$query\n"; #timing delay needed tp let bc output select(undef,undef,undef,.01); #see which filehandles have output for debugging # if($selread->can_read(0)){print "ready->read\n"} # if($selerror->can_read(0)){print "ready->error\n"} #get any error from bc sysread(ERROR,$error,4096) if $selerror->can_read(0); if($error){print "ERROR-> $error\n"} #get the answer from bc sysread(READ,$answer,4096) if $selread->can_read(0); if($answer){print "$query = $answer\n"} ($error,$answer)=('',''); }
In reply to IPC::Open3 and blocking filehandles by zentara
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |