in reply to Re: OT (Perhaps) File Locking
in thread OT (Perhaps) File Locking

A write may be atomic, but prints and printfs go via the stdio layer (or in newer perls, via the perlio layer), which will perform buffering and does writes as much as possible in fixed sized blocks (typically 1, 2 or 8k). Which could mean a single is actually performed as two writes. Or two prints will be done as one write.

If you want to be safe, you always do: lock, seek, print, unlock.

As for pointers, consult Stevens' "Advanced programming in the UNIX environment", IMO, a more useful book for a Perl programmer than all "Perl book"s combined. Afterall, where C is portable assembler, Perl is portable UNIX.

Abigail

Replies are listed 'Best First'.
(tye)Re: OT (Perhaps) File Locking
by tye (Sage) on Jun 04, 2002 at 15:34 UTC

    If you haven't "disabled" buffering [via HANDLE->autoflush(1), for example], then your advice to lock won't really help much either (except that if you use Perl's own flock, it will flush the buffer before unlocking -- on modern versions of Perl).

    derby was correct: If you are writing relatively small amounts of data in a single operation (such as via a single print or printf, for example) and have the file opened for append access under Unix, then locking is not needed but disabling of buffering is needed. If you are using multiple operations or writing large amounts of data, then you need locking but you also need to disable buffering.

    Disabling buffering is usually done via autoflush (or $| and 1-argument select) but you can get the same effect by using Perl's flock and requiring a modern version of Perl (5.004 or later).

    Update: Yes, I assumed Perl, but I didn't assume flock, especially since you didn't even mention it (there are other, often better, ways to lock files in Perl than flock). The reason I said "Perl's flock" was to prevent people from getting the impression that the underlying flock() is what does the buffer flushing.

    And if I'm going to write a program that relies on a Perl-specific aspect of flock, then I tend to document this as I would not be surprised to see a Perl routine converted to C for any number of reasons. Since this feature is documented as not always having been true even in Perl, a require 5.004; makes a great place to put such documentation. But my point was more that I'd rather not rely on this feature and instead put the autoflush in place so that a change in locking method doesn't break things.

    And, yes, when answering questions, I do consider it important to note things that won't work on older versions of Perl. After all, everything covered here works even in Perl4 except for flock flushing buffers. And this lack would not be easy to notice if you ended up running this code on an old version of Perl, making it more important to point out.

            - tye (but my friends call me "Tye")
      If you haven't "disabled" buffering {via HANDLE->autoflush(1), for example}, then your advice to lock won't really help much either (except that if you use Perl's own flock, it will flush the buffer before unlocking -- on modern versions of Perl).

      Uhm, well, considering this forum is about Perl, I do assume we are talking about Perl's flock, not the one of some other language. As for modern Perls, 5.004 was released over 5 years ago. Annotating everything that has changed over the years isn't practical. Where do we stop? Early versions of perl required you to use do to call a sub. But I don't think it's very useful to say you need a modern version of Perl to call a sub without do.

      Abigail

Re^2: OT (Perhaps) File Locking
by Aristotle (Chancellor) on Jun 03, 2002 at 22:09 UTC
    And to mention a trap - the unlock in there only works as such if you are not depending on data read from the file though. If you do, then you shouldn't explicity unlock the file - rather, process as quick as possible, close it and forget what you read. I don't know where it was, but merlyn wrote a note or two to that effect here once upon a time.

    Makeshifts last the longest.