*BSD News Article 54771


Return to BSD News archive

#! rnews 2042 bsd
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!yarrina.connect.com.au!munnari.OZ.AU!news.hawaii.edu!ames!usenet.kornet.nm.kr!news.kreonet.re.kr!europa.chnt.gtegsc.com!wlbr!news.cerf.net!pagesat.net!calweb!not-for-mail
From: Lee Daniel Crocker <lee@piclab.com>
Newsgroups: comp.lang.perl.misc,comp.os.linux.misc,comp.unix.bsd.freebsd.misc
Subject: flock() bug in Perl, Linux, or FreeBSD?
Followup-To: comp.lang.perl.misc
Date: Fri, 17 Nov 1995 10:23:11 -0500 (EST)
Organization: CalWeb Internet Services, Inc.
Lines: 37
Sender: lcrocker@un.configured.software
Message-ID: <1.#zc-i2^n5@un.configured.software>
NNTP-Posting-Host: web1.calweb.com
Cc: perlbug@perl.com
Xref: euryale.cc.adfa.oz.au comp.lang.perl.misc:7802 comp.os.linux.misc:70608 comp.unix.bsd.freebsd.misc:8938

I have one acount on a Linux ISP, and another on FreeBSD.  On
both systems, the straightforward C equivalent of the Perl
script below works exactly as expected: run 3 simultaneous
copies, and you get a nicely incremented counter, with mixed
pids, indicating that flock() is doing its job.  The Perl
script itself, doing exactly the same thing, generates a list
of duplicated numbers, indicating that simultaneous reads are
being allowed.  The perl code is calling flock().  It doesn't
matter if you replace the flock() operator with the syscall()
equivalent, it still fails, so I suspect the problem is with
the OS, but I'm surprised the behavior is identical between
Linux and BSD.  Whose bug is it?

#!/usr/local/bin/perl5.001
#
# Expects 'counter' to be a file with one line, which
# is just an ASCII integer.

open(COUNTER, "+<counter") || die "open failed";

for (1..10) {
    flock(COUNTER, 2) || die "lock failed";

    seek(COUNTER, 0, 0);         # read current count
    chop($count = <COUNTER>);

    print "$$: $count\n";        # display pid, count
    ++$count;

    seek(COUNTER, 0, 0);         # write incremented count
    print COUNTER "$count\n";

    flock(COUNTER, 8) || die "unlock failed";
}

close COUNTER;
exit 0;