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

I agree. Once I got the appropriate combination of search terms I eventually found the same thing you described. Essentially that <$sd> is a buffering read and I have to use sysread().

I've fixed my app now but I'm not real happy with that solution. I had managed to write a fairly large and featureful app over a long weekend due to how simple perl makes so many little coding tasks. But being forced to replace <$sd> with sysread() has bloated my code and probably added a lot more development time.

It's like chopping the language off at the knees to not have any visibility into those input buffers. From the standpoint of the perl language being as useful as possible I still think the select() should be aware of the input buffers and should have returned true for sockets with buffered input.

But thanks for your help. I agree with the assessment of the problem and the necessary fix. Thanks.

Replies are listed 'Best First'.
Re^3: select() and input buffering
by ikegami (Patriarch) on Apr 14, 2011 at 05:17 UTC

    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.

      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).