diff --git a/System/FileLock.hs b/System/FileLock.hs
--- a/System/FileLock.hs
+++ b/System/FileLock.hs
@@ -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(..)
diff --git a/System/FileLock/Internal/Flock.hsc b/System/FileLock/Internal/Flock.hsc
--- a/System/FileLock/Internal/Flock.hsc
+++ b/System/FileLock/Internal/Flock.hsc
@@ -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 */
diff --git a/filelock.cabal b/filelock.cabal
--- a/filelock.cabal
+++ b/filelock.cabal
@@ -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
diff --git a/tests/interrupt.hs b/tests/interrupt.hs
new file mode 100644
--- /dev/null
+++ b/tests/interrupt.hs
@@ -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"
