
Ertugrul Soeylemez wrote:
readFileLocked :: FilePath -> IO B.ByteString readFileLocked fn = withFile fn ReadMode $ \h -> do lockFile h -- for a suitable function lockFile B.hGetContents h
It is, BTW, always preferable to use withFile over openFile, if you can. This makes your code cleaner and also exception-safe.
Unless there is a better locking primative than waitToSetLock available, I don't know how to build your lockFile function. It seems that it would have a side effect of closing the handle. It could return a new handle like this, but then withFile's automatic close of the file would be defeated. lockFile h = do lockfd <- handleToFd h -- closes h waitToSetLock lockfd (lockType mode, AbsoluteSeek, 0, 0) newh <- fdToHandle lockfd return newh Here's what I'm using instead. withFileLocked file mode action = do -- TODO: find a way to use bracket here handle <- openFile file mode lockfd <- handleToFd handle -- closes handle waitToSetLock lockfd (lockType mode, AbsoluteSeek, 0, 0) handle' <- fdToHandle lockfd ret <- action handle' hClose handle' return ret where lockType ReadMode = ReadLock lockType _ = WriteLock BTW, thanks for the hint that ByteString has a strict getContents! I was prototyping my code with String and thought I'd worry about optimisation later, but that is a good reason to use ByteString up front. Jimmy Wylie wrote:
Implementations should enforce as far as possible, at least locally to the Haskell process, multiple-reader single-writer locking on files.
According to strace, this does not involve any system-level locking with flock/fcntl/lockf. It is done internally to the ghc process. -- see shy jo