I've experienced similar problems with autoflush and sockets, particularily on Solaris - which seems to have a write-ahead buffer of ~8 bytes on some streams that autoflush doesn't touch, I'm guessing to make it send larger packets. Anyhow, the solution is to use sysread and syswrite for all IO that you want to be unbuffered (this would be genuinely unbuffered rather than automatically flushed). Note that most of perl's IO functions are buffered and consequently should not be mixed with sysread/syswrite. In particular, print and eof are buffered (you can determine end of file by checking the results of a sysread)

If you are using select or any other low-level IO call (this includes using IO::Select), then the use of sysread and syswrite is mandatory.

I do usually add that I've never experienced any problems under Linux, only under other OSes like Solaris and even then only sporadically... Sometimes data just seems to get stuck in a buffer and isn't sent until some more data comes along.

Andrew.

Update: I worked out the exact reason why autoflush doesn't work very well in these sort of circumstances. The docs very specifically say that it only autoflushes the *output* buffer. If any input buffering is being used, autoflush will have no effect. Thus, autoflush will make sure that data you send from your script will not be buffered, but makes no such guarantees about data you read. Therefore, it's fine for writing to a pipe or a socket, but not a good idea for reading from a pipe or a socket (unless you can be sure that the other side has closed the pipe/socket).

See the perlvar man page for details. I would guess the precise behaviour depends on what C library your version of perl is linked to. I suspect many flush the input buffer on a newline, which is why many people fail to notice this particular subtlety. sysread will give you all the data that's currently available on a given file handle, newline or no. You'll need to buffer it yourself until a newline finally does arrive, but at least your script won't randomly hang while it waits for enough input data to empty the appropriate buffer. I suspect this is a big gotcha for many people (first time I came across it, it had me scratching my head for weeks)


In reply to Re: Redirecting STDIN / STDOUT after fork by ahunter
in thread Redirecting STDIN / STDOUT after fork by astanley

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.