packages feed

filelock 0.1.1.4 → 0.1.1.5

raw patch · 4 files changed

+53/−5 lines, 4 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

Files

System/FileLock.hs view
@@ -20,6 +20,10 @@ -- -- Note on the implementation: currently the module uses flock(2) on non-Windows -- platforms, and LockFileEx on Windows.+--+-- On non-Windows platforms, @InterruptibleFFI@ is used in the implementation to+-- ensures that blocking lock calls can be correctly interrupted by async+-- exceptions (e.g. functions like `timeout`).  This has been tested on Linux. module System.FileLock   ( FileLock   , SharedExclusive(..)
System/FileLock/Internal/Flock.hsc view
@@ -1,3 +1,5 @@+{-# LANGUAGE InterruptibleFFI #-}+ module System.FileLock.Internal.Flock #ifndef USE_FLOCK   () where@@ -7,6 +9,7 @@ #include <sys/file.h>  import Control.Applicative+import Control.Concurrent (yield) import qualified Control.Exception as E import Data.Bits import Foreign.C.Error@@ -64,8 +67,12 @@       case () of         _ | errno == eWOULDBLOCK             -> return False -- already taken-          | errno == eINTR-            -> flock (Fd fd) exclusive block+          | errno == eINTR -> do+              -- If InterruptibleFFI interrupted the syscall with EINTR,+              -- we need to give the accompanying Haskell exception a chance to bubble.+              -- See also https://gitlab.haskell.org/ghc/ghc/issues/8684#note_142404.+              E.interruptible yield+              flock (Fd fd) exclusive block           | otherwise -> throwErrno "flock"   where     modeOp = case exclusive of@@ -75,7 +82,9 @@       True -> 0       False -> #{const LOCK_NB} -foreign import ccall "flock"+-- `interruptible` so that async exceptions like `timeout` can stop it+-- when used in blocking mode (without `LOCK_NB`).+foreign import ccall interruptible "flock"   c_flock :: CInt -> CInt -> IO CInt  #endif /* USE_FLOCK */
filelock.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                filelock-version:             0.1.1.4+version:             0.1.1.5 synopsis:            Portable interface to file locking (flock / LockFileEx) description:         This package provides an interface to Windows and Unix                      file locking functionalities.@@ -17,13 +17,14 @@ -- extra-source-files:   cabal-version:       >=1.10 extra-source-files:  tests/lock.log.expected+tested-with:         GHC ==8.4.2 || ==8.6.5 || ==8.8.3  library   exposed-modules:     System.FileLock   other-modules:       System.FileLock.Internal.Flock                        System.FileLock.Internal.LockFileEx   -- other-extensions:    -  build-depends:       base >=4.5.1.0 && <5+  build-depends:       base >=4.9.0.0 && <5   -- hs-source-dirs:         default-language:    Haskell2010 @@ -42,6 +43,16 @@   build-depends:      filelock, process >= 1.2.1.0, async, base   ghc-options:        -threaded   default-language:   Haskell2010++test-suite interrupt+  type:               exitcode-stdio-1.0+  hs-source-dirs:     tests+  main-is:            interrupt.hs+  build-depends:      filelock, process >= 1.2.1.0, async, base+  ghc-options:        -threaded+  default-language:   Haskell2010+  if os(windows)+    buildable:        False  source-repository head   type: git
+ tests/interrupt.hs view
@@ -0,0 +1,24 @@+import Control.Concurrent+import Control.Exception+import Control.Monad+import System.FileLock+import System.Exit+import System.Timeout++main :: IO ()+main = withFileLock lockFilePath Exclusive $ \_ -> do+  mvar <- newMVar Nothing+  _ <- forkIO $ do+    -- The attempt to lock the file again should block, but it should be+    -- interrupted by the timeout, returning Nothing.+    --+    -- Also masking shouldn't change interruptibility.+    r <- timeout 1000000 $ mask $ \_ -> lockFile lockFilePath Exclusive+    _ <- swapMVar mvar (Just r)+    return ()+  threadDelay 2000000+  res <- readMVar mvar+  when (res /= Just Nothing) $+    die $ "unexpected result: " ++ show (fmap (const ()) <$> res)+  where+    lockFilePath = "interrupt_test.lock"