I have a program that opens two different Fds to the same file, uses setLock on the first Fd, and then getLock on the second Fd. Once the getLock is done, the program no longer has a lock set on the file. This is with unix 2.7.0.1 and ghc 7.10.1.
This is very surprising (and is a testcase from stumbling over this problem in the wild), and I don't see behavior like this when I write a C program that does the same thing using fcntl F_SETLK and F_GETLK.
I'll paste my test program at the end of this bug report. The way to use it is open 2 terminals. In the first, run "./test setLock getLock". Then in the second, run "./test setLock" and see that it successfully sets the lock; the first process lost its lock on the file. If you instead run "./test setLock" in both terminals, it behaves as expected with the first process taking the lock so the second fails to take it.
import System.Posix.IO
import System.IO
import System.Environment
main = do
mapM_ go =<< getArgs
getLine
go "setLock" = do
writeFile lck ""
fd <- openFd lck ReadWrite Nothing defaultFileFlags
print ("opened lock fd", fd)
setLock fd (WriteLock, AbsoluteSeek, 0, 0)
print ("setLock")
go "getLock" = do
checkfd <- openFd lck ReadOnly Nothing defaultFileFlags
print ("opened lock check fd", checkfd)
ret <- getLock checkfd (ReadLock, AbsoluteSeek, 0, 0)
case ret of
Nothing -> print "getLock indicates the file is not locked"
Just (pid, fl) -> print ("getLock detected lock by pid", pid)
closeFd checkfd
lck = "locktest"
I have a program that opens two different Fds to the same file, uses setLock on the first Fd, and then getLock on the second Fd. Once the getLock is done, the program no longer has a lock set on the file. This is with unix 2.7.0.1 and ghc 7.10.1.
This is very surprising (and is a testcase from stumbling over this problem in the wild), and I don't see behavior like this when I write a C program that does the same thing using fcntl F_SETLK and F_GETLK.
I'll paste my test program at the end of this bug report. The way to use it is open 2 terminals. In the first, run "./test setLock getLock". Then in the second, run "./test setLock" and see that it successfully sets the lock; the first process lost its lock on the file. If you instead run "./test setLock" in both terminals, it behaves as expected with the first process taking the lock so the second fails to take it.