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

The following code hangs on both ActiveState & Strawberry perl 5.10.0, 5.10.1:
use Fcntl qw(LOCK_EX LOCK_UN); #select H; $|=1; select STDOUT; # Uncomment to fix $| = 1; open H,'>','foo.txt' or die "Can't open, $!\n"; print "Opened filehandle. Forking into 2\n"; my $pid=fork; if (!defined $pid) {die "fork failed\n"} elsif ($pid) { print "Parent will lock, wait a couple seconds, and exit\n"; flock H,LOCK_EX; print "Parent has lock\n"; print H "Parent writes to file\n"; # Comment this out to "fix" sleep 2; flock H, LOCK_UN; print "Parent byebye\n"; exit; } else { sleep 1; print "Child hi\n"; flock H,LOCK_EX; print "Child has lock\n"; flock H, LOCK_UN; print "I am the free child. Bye now!\n"; exit; }
It prints:
Opened filehandle. Forking into 2
Parent will lock, wait a couple seconds, and exit
Parent has lock
Child hi
and then hangs. Apparently the child waiting for the flock also stops the parent. You can switch the "sleeps" & "print H" so that the child writes to the file and then pauses, and the program then hangs when the parent waits on the "flock".

If it doesn't write to "H", there's no hang. If the log file is not buffered, there's no hang. (Update: ++ikegami for pointing out mis-use of "line buffered")

Why does perl hang? I looked in the the perl source, at win32/win32.c, to see how flock was defined. I also read up a bit on threads and how my perl is configured to try and answer that myself. What I've found so far:

  1. Both strawberry and activestate have "flock" simulated via LockFileEx and UnlockFileEx.
  2. Both use interpreter threads, ie ithread
  3. and of course since it's windows, "fork" is emulated with threads.
  4. The task manager shows me that there really are two OS threads after the fork- verified by sleeping before the fork and watching the thread count.
Given the above, why does the parent hang on the "flock H, LOCK_UN;" call, after it writes to the file, while a child is waiting on the lock?