Here is a snippit from an e-mail I wrote that quotes the strace results. Please pardon the speculative tone of the e-mail. ---------------- ---------------- ---------------- I think there is a whole problem in the idea of opening a file using DB_File and then using a dup of $db->fh to lock the file, as in the below code: my $logindb_file = "db_file.db"; my $logindb_mode = 0644; my %db_hash; my $db; my $lock_fh; $db = tie(%db_hash, 'DB_File', $logindb_file, O_CREAT|O_RDWR, $logindb_mode, $DB_HASH); if ( not defined $db ) { warn "error opening db_file $logindb_file: $!"; return 1; } sleep 1; $lock_fh = new IO::File ("+<&=" . $db->fd); if ( not defined $lock_fh ) { warn "error duping filehandle: $!"; return 1; } flock($lock_fh, LOCK_EX); The problem is that this code produces the following system calls: # open the database open("./db_file.db", O_RDWR|O_CREAT|O_EXCL, 0644) = -1 EEXIST (File exists) open("./db_file.db", O_RDWR) = 4 fcntl(4, F_SETFD, FD_CLOEXEC) = 0 fstat(4, {st_mode=031771, st_size=0, ...}) = 0 read(4, "\0\0\0\0\0\0\0\0\0\0\0\0a\25\6\0"..., 512) = 512 close(4) = 0 brk(0x8177000) = 0x8177000 open("/etc/fstab", O_RDONLY) = 4 fstat(4, {st_mode=031567, st_size=0, ...}) = 0 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2aabf000 read(4, "/dev/hda5 / "..., 4096) = 608 close(4) = 0 munmap(0x2aabf000, 4096) = 0 open("/proc/cpuinfo", O_RDONLY) = 4 fstat(4, {st_mode=S_IFCHR|S_ISUID|S_ISGID|071, st_rdev=makedev(50, 120), ...}) = 0 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2aabf000 read(4, "processor\t: 0\nvendor_id\t: Gen"..., 1024) = 316 read(4, "", 1024) = 0 close(4) = 0 munmap(0x2aabf000, 4096) = 0 open("./db_file.db", O_RDWR) = 4 fcntl(4, F_SETFD, FD_CLOEXEC) = 0 fstat(4, {st_mode=031771, st_size=0, ...}) = 0 lseek(4, 0, SEEK_SET) = 0 read(4, "\0\0\0\0\0\0\0\0\0\0\0\0a\25\6\0"..., 4096) = 4096 # the sleep (inserted so we can tell where one block of code begins and the other ends) time([936194680]) = 936194680 SYS_175(0, 0x7ffffbd8, 0x7ffffb58, 0x8, 0) = 0 SYS_174(0x11, 0, 0x7ffff95c, 0x8, 0x11) = 0 SYS_175(0x2, 0x7ffffb58, 0, 0x8, 0x2) = 0 nanosleep(0x7ffffac4, 0x7ffffac4, 0x2ac211b4, 0x7ffffac4, 0x7ffffbd8) = 0 time([936194681]) = 936194681 # lock the database fcntl(4, F_GETFL) = 0x2 (flags O_RDWR) fstat(4, {st_mode=031771, st_size=0, ...}) = 0 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2aabf000 _llseek(0x4, 0, 0, 0x7ffff970, 0x1) = 0 fstat(4, {st_mode=031771, st_size=0, ...}) = 0 fcntl(4, F_SETFD, FD_CLOEXEC) = 0 flock(4, LOCK_EX) = 0 Notice that in the chunk of system calls which open the database, the first 4k of the database file is read. I suspect that this information is cached inside of the DB c driver code or perhaps a stdio structure beneath that. While waiting for the exclusive lock it may be possible for some other writer to come along and update that first 4k of the file. Then when this writer gets the lock and starts manipulating the database corruption can result.