http://qs321.pair.com?node_id=11123410


in reply to eof() blocking

From perldoc -f eof

Note that this function actually reads a character and then "ungetc"s it, so isn't useful in an interactive context.
What I would do instead:

#!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11123397 use warnings; use Socket; my $child; #filehandle to child process my $parent; #filehandle to parent process my $pid; #Process ID of child process socketpair($child, $parent, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $! +"; $child->autoflush(1); $parent->autoflush(1); if ($pid = fork()) { close $parent or die "close: $!\n"; sleep 1; print STDOUT time%1000, ": polling child\n"; my $buf = ''; while( sysread $child, $buf, 4096, length $buf ) { while( $buf =~ s/(.*)\n// ) { print STDOUT time%1000, ": received <$1>\n"; } } print STDOUT time%1000, ": end of input from child\n"; wait; } elsif( defined $pid ) { close $child or die "close: $!\n"; print STDOUT time%1000, ": child started\n"; sleep 5; print $parent time%1000, ": child printed\n"; close $parent or die "close: $!\n"; exit; } else { die "cannot fork: $!"; }

Replies are listed 'Best First'.
Re^2: eof() blocking
by azadian (Sexton) on Nov 05, 2020 at 10:07 UTC
    Thanks for your input. I have a hard time regarding this as an "interactive" context, but I guess the moral of the story is that eof() only works if it's an honest-to-God file. The fact that it blocks seems to me completely contrary to the whole point of the function. The system IO is what I was hoping to avoid, but it looks like I can't.

      While I'm not completely sure of what you want, it appears to me you are looking for something like a "datawaiting()" call instead of an end-of-file.
      Here's a (somewhat) minimal change to your program with the end-of-file replaced :)

      #!/usr/bin/perl use diagnostics; use strict 'subs'; use strict 'refs'; use Socket; use IO::Handle; my $child; #filehandle to child process my $parent; #filehandle to parent process my $pid; #Process ID of child process socketpair($child, $parent, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $! +"; $child->autoflush(1); $parent->autoflush(1); if ($pid = fork()) { #parent close $parent or die "close: $!\n"; sleep 1; print STDOUT time%1000, ": polling child\n"; if (not datawaiting($child)) { ##### CHANGE +D print STDOUT time%1000, ": no input from child yet\n"; } else { my $line = <$child>; chomp $line; print STDOUT time%1000, ": received <$line>\n"; } } else { #child die "cannot fork: $!" unless defined $pid; close $child or die "close: $!\n"; print STDOUT time%1000, ": child started\n"; sleep 5; print {$parent} time%1000, ": child printed\n"; close $parent or die "close: $!\n"; exit; } sub datawaiting ####### CHANGED see perldoc -f select { my $rin = my $win = my $ein = ''; vec($rin, fileno(shift), 1) = 1; return scalar select my $rout = $rin, my $wout = $win, my $eout = $e +in, 0; }

      Outputs:

      277: child started 278: polling child 278: no input from child yet

      Is that what you were looking for ?

      With IO::Select, this isn't too much to avoid, is it?

      #!/usr/bin/perl use diagnostics; use strict 'subs'; use strict 'refs'; use Socket; use IO::Handle; use IO::Select; #### ADDED my $child; #filehandle to child process my $parent; #filehandle to parent process my $pid; #Process ID of child process socketpair($child, $parent, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $! +"; $child->autoflush(1); $parent->autoflush(1); if ($pid = fork()) { #parent close $parent or die "close: $!\n"; sleep 1; print STDOUT time%1000, ": polling child\n"; if ( IO::Select->new($child)->can_read(0) ) { ############### CHA +NGE my $line = <$child>; chomp $line; print STDOUT time%1000, ": received <$line>\n"; } else { print STDOUT time%1000, ": no input from child yet\n"; } } else { #child die "cannot fork: $!" unless defined $pid; close $child or die "close: $!\n"; print STDOUT time%1000, ": child started\n"; sleep 5; print {$parent} time%1000, ": child printed\n"; close $parent or die "close: $!\n"; exit; }