Re: Yet Another Autoflush problem -- What's wrong with this code?

From: Walter Roberson (roberson_at_ibd.nrc-cnrc.gc.ca)
Date: 01/24/04


Date: 24 Jan 2004 05:32:58 GMT

In article <40118a1e$0$12721$61fed72c@news.rcn.com>,
John Chambers <jmchambers@rcn.com> wrote:
:Ben Morrow wrote:
:> Here is your problem. <$server> will not return until it reads a
:> newline. You either want to set $/ to \1 (which will read a byte at a
:> tyme: not very efficient) or set non-blobking mode and use

:> while (read $server, $line, 1024) {

:> ; or maybe sysread instead.

:So I guess all those FAQs and RTFMs are just red herrings, and
:I was guessing right all along. I wonder why I never ran across
:any comments about this? Others have had to stumbled across the
:same problem. There's gotta be a lot of people trying to send
:data across TCP links in perl, right? And data isn't always in
:the form of ASCII text with newlines at the end of every data
:object, right?

The behaviour is deducible, by reading in perlops that <handle>
is equivilent to readline(*handle) and then reading the perlfunc
documentation of readline as returning the next line delimited
by the current record separator.

More explicit discussion appears in the perlipc documentation in
the section "Interactive Client with IO::Socket"

          If the remote server sends data a byte at time, and you need
          that data immediately without waiting for a newline (which
          might not happen), you may wish to replace the "while" loop
          in the parent with the following:

              my $byte;
              while (sysread($handle, $byte, 1) == 1) {
                  print STDOUT $byte;
              }

          Making a system call for each byte you want to read is not
          very efficient (to put it mildly) but is the simplest to
          explain and works reasonably well.

They are, as they hint, hiding complications in that reading of a
single byte. The sysread() call can potentially return anywhere -up-
to the number of bytes you ask for, dependant on internal buffering.
The maximum number of bytes of pipe data that are guaranteed to be handled
atomically is 512 for any POSIX compliant system; the SGI IRIX systems
I use most provide up to 10240 bytes atomically.

(For more information about these limits on a POSIX system, see
<limits.h> and the sysconf() and pathconf() calls, and the
constants _POSIX_PIPE_BUF and PIPE_BUF .)

When you are reading from a device (e.g., a tty) instead of a pipe, then
all guarantees about minimum I/O sizes are off: essentially you get
whatever became available between interrupts. When data is flowing
at a steady rate and you are in a tight loop, the read sizes tend to
be consistant, but not necessarily very big, and the first read
isn't necessarily going to be the same size. In one of the tests I
did, I tended to get 3 bytes on the first read and then groups of 10
bytes when running at 38400 bps across a serial port... but
that was only a tendancy, and it varied with load and was
pom-dependent.

The net result of these uncertainties is that if you are using
sysread() with a buffer size greater than 1 and there is any
possibility that the data might not arrive atomically, then you need
to explicitly examine the number of bytes that arrived and cycle back
until you get the full number of bytes that you want to read in
this trip. As sysread() does not pay attention to line boundaries,
you will probably need to decrement your buffer size by the number
of bytes that arrived, and probably need to munge the offset within
the buffer to be stored into. Once you've seen the resulting code
a couple of times, it's easy to recognize.

-- 
How does Usenet function without a fixed point?


Relevant Pages

  • Re: Perls read() vs. sysread()
    ... > Perl's readfunction and its sysread() function. ... > tried reading the man pages on freadand read, ... What this means is that when you say read, Perl ... it actually only goes into a buffer. ...
    (comp.lang.perl.misc)
  • Re: is it possible to efficiently read a large file?
    ... one buffer and storage is getting allocated for $buffer on each call and ... I had created a long string and passed it to sysread but it didn't seem ... just to make sure I'm reading no more than I should be. ...
    (comp.lang.perl.misc)
  • Re: Discovering variable types...
    ... >memory it points to is on the heap. ... sequentially reading data, if one is randomly reading records, then a ... >project is what's prompting me to improve disk access. ... from a memory buffer I can do it in about a second. ...
    (comp.lang.pascal.delphi.misc)
  • Re: asrock, problem with nic after windows-boot - Exact Opposite issue the OP is having
    ... concerning Reading the Startup "Buffer" of the Bootup ... Time to read those startup scripts, ... are identified as STANDARD, INFORMATIONAL and HISTORIC, etc.? ...
    (comp.os.linux.networking)
  • Re: IO::Select extension
    ... >> leaves me to deal with all the messy sysread and syswrite stuff. ... > then you need to find a way to allow reador readline() not to block ... > the buffer but not enough to satisfy the reador readline. ... can_write report handles that are under some in-use buffer-space threshold, ...
    (comp.lang.perl.misc)