{-# LANGUAGE CPP #-} {-# LANGUAGE InterruptibleFFI #-} {-# LANGUAGE NoImplicitPrelude #-} module GHC.Internal.IO.Handle.Lock ( FileLockingNotSupported(..) , LockMode(..) , hLock , hTryLock , hUnlock ) where #include "HsBaseConfig.h" import GHC.Internal.Data.Functor (void) import GHC.Internal.Base import GHC.Internal.IO.Handle.Lock.Common (LockMode(..), FileLockingNotSupported(..)) import GHC.Internal.IO.Handle.Types (Handle) #if defined(mingw32_HOST_OS) import GHC.Internal.IO.Handle.Lock.Windows #elif HAVE_OFD_LOCKING import GHC.Internal.IO.Handle.Lock.LinuxOFD #elif HAVE_FLOCK import GHC.Internal.IO.Handle.Lock.Flock #else import GHC.Internal.IO.Handle.Lock.NoOp #endif -- | If a 'Handle' references a file descriptor, attempt to lock contents of the -- underlying file in appropriate mode. If the file is already locked in -- incompatible mode, this function blocks until the lock is established. The -- lock is automatically released upon closing a 'Handle'. -- -- Things to be aware of: -- -- 1. This function may block inside a C call. If it does, in order to be able -- to interrupt it with asynchronous exceptions and/or for other threads to -- continue working, you MUST use threaded version of the runtime system. -- -- 2. The implementation uses relies on any of a number of locking -- facilities, depending upon what the platform supports: -- -- * 'LockFileEx' is used on Windows -- * On platforms that support it we use the @F_OFD_SETLK@ and @F_OFD_SETLKW@ @fnctl@s. -- * Otherwise we use @flock@ -- -- hence all of their caveats also apply here. -- -- 3. On non-Windows platforms that don't support 'flock' (e.g. Solaris) this -- function throws 'FileLockingNotImplemented'. We deliberately choose to not -- provide fcntl based locking instead because of its broken semantics. -- -- @since base-4.10.0.0 hLock :: Handle -> LockMode -> IO () hLock :: Handle -> LockMode -> IO () hLock Handle h LockMode mode = IO Bool -> IO () forall (f :: * -> *) a. Functor f => f a -> f () void (IO Bool -> IO ()) -> IO Bool -> IO () forall a b. (a -> b) -> a -> b $ Handle -> String -> LockMode -> Bool -> IO Bool lockImpl Handle h String "hLock" LockMode mode Bool True -- | Non-blocking version of 'hLock'. -- -- Returns 'True' if taking the lock was successful and 'False' otherwise. -- -- @since base-4.10.0.0 hTryLock :: Handle -> LockMode -> IO Bool hTryLock :: Handle -> LockMode -> IO Bool hTryLock Handle h LockMode mode = Handle -> String -> LockMode -> Bool -> IO Bool lockImpl Handle h String "hTryLock" LockMode mode Bool False -- | Release a lock taken with 'hLock' or 'hTryLock'. -- -- @since base-4.11.0.0 hUnlock :: Handle -> IO () hUnlock :: Handle -> IO () hUnlock = Handle -> IO () unlockImpl ----------------------------------------