in reply to Re: Diagnosing blocking io (or: finding the WHY of my Open2 woes).
in thread Diagnosing blocking io (or: finding the WHY of my Open2 woes).

$JSWRITE->autoflush(1); Changes nothing, unfortunately. I tried that already, along with other things like:
use Fcntl; ... my $flags |= O_NONBLOCK; fcntl($JSWRITE, F_SETFL, $flags); ...
And, yes "`which js`" is the same... I forget why I had that in there. Still doesn't work, but I'll update the open2() call in the original post to avoid confusion.

Replies are listed 'Best First'.
Re^3: Diagnosing blocking io (or: finding the WHY of my Open2 woes).
by ikegami (Patriarch) on Nov 18, 2008 at 23:28 UTC

    Your program works fine for me when I run a Perl script for the child.

    my $pid = open2($JSREAD, $JSWRITE, q{perl -e"{ $_=<>; last if /^END$/; + ++$i; $m=qq{$i: $_}; warn $m; print $m; redo}"});

    (The $|=1 isn't even necessary!)

    Seems to me the problem is in the js side. But I doubt it's in readline. Are you sure your Perl script reaches END? Are you sure END is causing the child to exit?

    By the way, you're adding newlines where they already exist in two different places.

      Yes, you're right about the unnecessary newlines. I fixed the newline where it feeds the file one line at a time to the child. The perl absolutely reaches "END".

      test.js is three simple lines:

      var foo=0; var bar=1; var baz=2;

      And I can type these in, one at a time, into the running javascript program from the command line:

      $ js js> load('jslint.js'); var foo=0; var bar=1; var baz=3; END jslint: No problems found. $

      If I drop warns in:

      open FILE, '<', "test.js"; while (<FILE>) { warn "printing $_"; print $JSWRITE "$_"; } close(FILE); warn "printing END\n"; print $JSWRITE "END\n";

      I see:

      $ ./jslint.pl printing var foo=0; printing var bar=1; printing var baz=3; printing END

      And strace shows this:

      ... write(4, "load(\'jslint.js\');\n", 19) = 19 open("test.js", O_RDONLY) = 3 ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff8d5e9440) = -1 ENOTTY (I +nappropriate ioctl for device) lseek(3, 0, SEEK_CUR) = 0 fstat(3, {st_mode=S_IFREG|0664, st_size=33, ...}) = 0 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 read(3, "var foo=0;\nvar bar=1;\nvar baz=3;"..., 4096) = 33 write(2, "printing var foo=0;\n", 20printing var foo=0; ) = 20 write(4, "var foo=0;\n", 11) = 11 write(2, "printing var bar=1;\n", 20printing var bar=1; ) = 20 write(4, "var bar=1;\n", 11) = 11 write(2, "printing var baz=3;\n", 20printing var baz=3; ) = 20 write(4, "var baz=3;\n", 11) = 11 read(3, "", 4096) = 0 close(3) = 0 write(2, "printing END\n", 13printing END ) = 13 write(4, "END\n", 4) = 4 close(4) = 0 read(5, <unfinished ...>

      Which, if I remove reading from $JSREAD, becomes:

      write(4, "load(\'jslint.js\');\n", 19) = 19 open("test.js", O_RDONLY) = 3 ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff38afb950) = -1 ENOTTY (I +nappropriate ioctl for device) lseek(3, 0, SEEK_CUR) = 0 fstat(3, {st_mode=S_IFREG|0664, st_size=33, ...}) = 0 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 read(3, "var foo=0;\nvar bar=1;\nvar baz=3;"..., 4096) = 33 write(2, "printing var foo=0;\n", 20printing var foo=0; ) = 20 write(4, "var foo=0;\n", 11) = 11 write(2, "printing var bar=1;\n", 20printing var bar=1; ) = 20 write(4, "var bar=1;\n", 11) = 11 write(2, "printing var baz=3;\n", 20printing var baz=3; ) = 20 write(4, "var baz=3;\n", 11) = 11 read(3, "", 4096) = 0 close(3) = 0 write(2, "printing END\n", 13printing END ) = 13 write(4, "END\n", 4) = 4 close(4) = 0 close(5) = 0 wait4(8790, <unfinished ...>
        Perl's doing everything you ask of it. You're tracing the wrong program as far as I'm concerned.

        Call strace with the -f option to have it trace forked processes as well (i.e. the js interpreter).

        Comparing the output you get with what you get when doing the same steps interactively, would certainly help to figure out what's different. In particular look for the read(0, ...) calls from the subprocess.