in reply to Re^2: Non-blocking Reads from Pipe Filehandle
in thread Non-blocking Reads from Pipe Filehandle

Wrong! Win32::API does no defined check.

Hm, Maybe you're right, but it doesn't seem to be necessary. With your insight about buffering & EOF and a little wrapping, this seems to work quite nicely:

#! perl -slw use strict; use Win32API::File qw[ GetOsFHandle ]; use Win32::API::Prototype; ApiLink( 'Kernel32', q[ BOOL PeekNamedPipe( HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesRead, DWORD *lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage ) ] ) or die $^E; sub readlineMaybe { my $fh = shift; my $osfh = GetOsFHandle( $fh ) or die $^E; my( $bufsize, $buffer, $cAvail, $read ) = ( 1024, chr(0)x1024, 0, +0 ); PeekNamedPipe( $osfh, $buffer, $bufsize, $read, $cAvail, 0 ) or $^E == 109 or die $^E; return if $^E == 109; my $eolPos = 1+index $buffer, $/; return '' unless $eolPos; sysread( $fh, $buffer, $eolPos ) or die $!; return $buffer; } my $cmd = 'perl -le"$|++;print localtime().q[: some text] and sleep 1 for 1..1 +0" |'; my $pid = open my $pipe, $cmd or die $!; while( defined( my $line = readlineMaybe( $pipe ) ) ) { Win32::Sleep( 100 ) and next unless $line; chomp $line; chop $line; ## Annoying! print "Got: '$line'"; } __END__ c:\test>buk-pipe.pl Got: 'Wed Oct 1 02:01:21 2008: some text' Got: 'Wed Oct 1 02:01:22 2008: some text' Got: 'Wed Oct 1 02:01:23 2008: some text' Got: 'Wed Oct 1 02:01:24 2008: some text' Got: 'Wed Oct 1 02:01:25 2008: some text' Got: 'Wed Oct 1 02:01:26 2008: some text' Got: 'Wed Oct 1 02:01:27 2008: some text' Got: 'Wed Oct 1 02:01:28 2008: some text' Got: 'Wed Oct 1 02:01:29 2008: some text' Got: 'Wed Oct 1 02:01:30 2008: some text'

The only annoying thing is the need for that chop in addition to chomp.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."

Replies are listed 'Best First'.
Re^4: Non-blocking Reads from Pipe Filehandle
by ikegami (Patriarch) on Oct 01, 2008 at 02:07 UTC

    Hm, Maybe you're right, but it doesn't seem to be necessary

    It stopped your program from working for over a year. It's forcing you to have to OS do unnecessary and possible unwanted work. It's definitely a necessity even though though it could be fudged this time.

      It's definitely a necessity even though though it could be fudged this time.

      For the record. This is from API.XS:

      case T_POINTER: ## If pointer params[i].t = T_POINTER; origST[i] = ST(i+1); if(has_proto) { pointerCallPack(ST(i+1), i, intypes); params[i].p = (char *) SvPV_nolen(ST(i+1)); } else { ## and no proto if(SvIOK(ST(i+1)) && SvIV(ST(i+1)) == 0) { ## and IV is OK +and zero params[i].p = NULL; ## use NULL } else { params[i].p = (char *) SvPV_nolen(ST(i+1)); ## else use th +e address of the PV } }

      So, if you work with the module instead of fighting it, and use 0 (zero) instead of undef to indicate that you want this pointer parameter set to null, that's what it does!

      Ie. it's not a "fudge", but how the author designed it!


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        I used 0. Didn't work. But then again, has_proto is true for the snippet that shows the problem. What's getting you so excited?

        Update: Bug report. Proposed change:

        case T_POINTER: params[i].t = T_POINTER; origST[i] = ST(i+1); if(has_proto) { - pointerCallPack(ST(i+1), i, intypes); - params[i].p = (char *) SvPV_nolen(ST(i+1)); + if(SvOK(ST(i+1)) { + pointerCallPack(ST(i+1), i, intypes); + params[i].p = (char *) SvPV_nolen(ST(i+1)); + } else { + params[i].p = NULL; + } } else { if(SvIOK(ST(i+1)) && SvIV(ST(i+1)) == 0) { params[i].p = NULL; } else { params[i].p = (char *) SvPV_nolen(ST(i+1)); } } ... if(params[i].t == T_POINTER && has_proto) { - pointerCallUnpack(origST[i], i, intypes); + if(SvOK(origST[i]) { + pointerCallUnpack(origST[i], i, intypes); + } }

        it's not a "fudge"

        lpTotalBytesAvail and lpBytesLeftThisMessage are both LPDWORD. You pass zero to both. Yet, you want me to believe doing so results in passing a non-NULL pointer for lpTotalBytesAvail and a NULL pointer for lpBytesLeftThisMessage?

      It stopped your program from working for over a year. It's forcing you to have to OS do unnecessary and possible unwanted work. It's definitely a necessity even though though it could be fudged this time.

      Oh dear. You really do talk bollocks sometimes!

      My "program" was a throw away attempt at something to which I already had (and posted) a simpler, better alternative.

      What stopped that throw-away from working, for the whole 10 minutes I spent on it, had absolutely nothing to do with all your ballshit above about "having to manage your own buffers".

      As I demonstrated, that is all completely unnecessary. You (and your mentor) just like doing things the hard way for some reason.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.