in reply to Re^2: select() and input buffering
in thread select() and input buffering

Even if select could see the contents of the buffers (which it sometimes does, I believe), you still couldn't use readline (<$fh>).

I listed two conditions that make sysread suitable. Its non-buffering aspect was just one of them. The other is that it returns as soon as there's data available, so it doesn't block. readline, on the other hand, blocks.

What makes sysread complicated, the use of buffers, is the result of it's non-blocking nature. Its non-blocking nature is the reason you want to use it. If readline was non-blocking, you'd have to jump through the same hoops.

select is inherently complicated. Imagine if you had both readers and writers! Again, if you want simplicity, you want threads.

Replies are listed 'Best First'.
Re^4: select() and input buffering
by declan (Initiate) on Apr 15, 2011 at 04:53 UTC
    For this app I'd be okay with that. The logic of my app guarantees enough data to satisfy the readline will be on its way or else the socket will be dying justifying an empty readline. I don't expect select to guarantee me that all the data I could possibly want is available, just to notify me that some data is there. I can agree that sysread() is better though for complete safety in the presense of network hiccups.

    But there's a worse problem I think. Suppose the first thing I do after opening a socket is exchange some info back and forth and then I put the socket in my main loop where select is used. I'd like to use the easy readline coding style for those initial exchanges but unless I'm missing something I can't do that. If at any point in the future of the program my socket will be used with select() then I must not use any buffering read call earlier in the socket's life.

    That's a very harsh restriction. Is there any way around it?

      Untested:
      use IO::Handle qw( ); # Require a non-blocking handle. # Returns undef on read error (Check $!) sub is_ready_to_read { my ($fh) = @_; my $blocking = $fh->blocking(0); return undef if !defined($blocking); my $rv = _is_ready_to_read($fh); { local $!; local $^E; $fh->blocking($blocking); } return $rv; } sub _is_ready_to_read { my ($fh) = @_; return 1 if defined(eof($fh)); return 0 if $!{EAGAIN} || $!{EWOULDBLOCK}; return undef; }

      You'll want to handle EINTR too if you have signal handlers.

      Checking if a terminal has reached EOF clears its EOF flag, so it's not completely safe to use this on terminals (-t $fh).