peters has asked for the wisdom of the Perl Monks concerning the following question:

I've got a strange problem with using <> on perl 5.8.8 on Solaris. It doesn't occur on 5.8.8 or 5.10.0 on Linux. Upgrading is not an option; I have a clumsy workaround and am looking for something better. Here's demonstration code:

use strict; use warnings; my $FILE = "/tmp/foo"; { open my $fh, ">", $FILE or die; print {$fh} "Fnord\n" } print "Contents =\n****\n", file_contents(), "****\n"; { open my $fh, '>>', $FILE or die $!; print {$fh} "Plugh\n" } print "Contents =\n****\n", file_contents(), "****\n"; print "Contents =\n****\n", file_contents(), "****\n"; sub file_contents { local @ARGV = $FILE; local $/; my $contents = <>; return $contents; }

And here's the output:

Contents = **** Fnord **** Contents = **** Plugh **** Contents = **** Fnord Plugh ****
The problem is that the second print of the file contents yields only the last line that was inserted, not both lines. I've been focusing on the end of the block containing the append. I've tried explicitly assigning () to @ARGV, explicitly closing $fh, explicitly undef'ing $fh.
Now I can always just call file_contents() from that point in the append block and throw away the result. Does anyone have a more elegant solution?
Again, note - this only happens on Solaris, not Linux.

Update:Yep, the close ARGV works - nice and elegant, thanks.

Peter Scott
Perl Medic

Replies are listed 'Best First'.
Re: Weird 5.8.8 Solaris <> bug (close)
by tye (Sage) on Oct 29, 2009 at 02:11 UTC

    On the several 5.8.x versions of Perl that I had handy none of which were 5.8.8 and none of which were on Solaris, I was unable to reproduce the problem so I can't test my fix. However, I suspect the following would fix the problem:

    sub file_contents { local @ARGV = $FILE; local $/; my $contents = <>; close ARGV; # Make EOF more obvious to Solaris Perl 5.8.8 return $contents; }

    The problem isn't how you are writing to the files. It seems clear that the problem is that the *ARGV file handle isn't being fully closed between the first and second round. Otherwise, it makes no sense to have just the second line read.

    - tye        

Re: Weird 5.8.8 Solaris <> bug
by gmargo (Hermit) on Oct 29, 2009 at 02:27 UTC

    If that <> construct is not working, then don't use it. Don't use local, ARGV, $/, or slurping. Just open the file, read it line by line to create a string, close the file, and return the string. Maybe you consider that a "clumsy workaround", but there's nothing inelegant about working, portable, maintainable code.

Re: Weird 5.8.8 Solaris <> bug
by jakobi (Pilgrim) on Oct 29, 2009 at 07:10 UTC

    That somewhat reminds me of the buffering problem with $./file offset and implicit close we've seen for stdout recently, even if this time, there's no magic hardcoded "stdout" involved. Still I no longer quite trust buffering for implicit close and reopen:

    As tye suggests, try an explicit close of ARGV in the sub (before return) and in addition explicitly close $fh after printing (instead of implicitly by leaving the scope).

    Note that you currently assign multiple times the same filename to @ARGV for an implicit <> open, which might be an interesting part of the confusion between Perl's IO and underlying OS IO you observed.

    cu & HTH, Peter -- hints may be untested unless stated otherwise; use with caution & understanding.