summaryrefslogtreecommitdiff
path: root/libraries
diff options
context:
space:
mode:
authorBen Gamari <bgamari.foss@gmail.com>2017-08-29 14:45:08 -0400
committerBen Gamari <ben@smart-cactus.org>2017-08-29 19:08:07 -0400
commita27bb1bd6206bdd5e6004ec1f7e95144a0fcc4d4 (patch)
tree618592f531d99245f1cf13e2d56d6fa6fb4d17d7 /libraries
parentf86de44dac0a6ca40c5fcd65f3a1944c45fa6011 (diff)
downloadhaskell-a27bb1bd6206bdd5e6004ec1f7e95144a0fcc4d4.tar.gz
base: Add support for file unlocking
Reviewers: austin, hvr Subscribers: rwbarton, thomie Differential Revision: https://phabricator.haskell.org/D3875
Diffstat (limited to 'libraries')
-rw-r--r--libraries/base/GHC/IO/Handle/Lock.hsc30
1 files changed, 30 insertions, 0 deletions
diff --git a/libraries/base/GHC/IO/Handle/Lock.hsc b/libraries/base/GHC/IO/Handle/Lock.hsc
index ec62f86cc9..daf407c881 100644
--- a/libraries/base/GHC/IO/Handle/Lock.hsc
+++ b/libraries/base/GHC/IO/Handle/Lock.hsc
@@ -8,6 +8,7 @@ module GHC.IO.Handle.Lock (
, LockMode(..)
, hLock
, hTryLock
+ , hUnlock
) where
#include "HsBaseConfig.h"
@@ -97,6 +98,10 @@ hLock h mode = void $ lockImpl h "hLock" mode True
hTryLock :: Handle -> LockMode -> IO Bool
hTryLock h mode = lockImpl h "hTryLock" mode False
+-- | Release a lock taken with 'hLock' or 'hTryLock'.
+hUnlock :: Handle -> IO ()
+hUnlock = unlockImpl
+
----------------------------------------
#if HAVE_FLOCK
@@ -116,6 +121,11 @@ lockImpl h ctx mode block = do
SharedLock -> #{const LOCK_SH}
ExclusiveLock -> #{const LOCK_EX}
+unlockImpl :: Handle -> IO ()
+unlockImpl h = do
+ FD{fdFD = fd} <- handleToFd h
+ throwErrnoIfMinus1_ "flock" $ c_flock fd #{const LOCK_UN}
+
foreign import ccall interruptible "flock"
c_flock :: CInt -> CInt -> IO CInt
@@ -146,6 +156,18 @@ lockImpl h ctx mode block = do
SharedLock -> 0
ExclusiveLock -> #{const LOCKFILE_EXCLUSIVE_LOCK}
+unlockImpl :: Handle -> IO ()
+unlockImpl h = do
+ FD{fdFD = fd} <- handleToFd h
+ wh <- throwErrnoIf (== iNVALID_HANDLE_VALUE) "hUnlock" $ c_get_osfhandle fd
+ allocaBytes sizeof_OVERLAPPED $ \ovrlpd -> do
+ fillBytes ovrlpd 0 sizeof_OVERLAPPED
+ c_UnlockFileEx wh 0 0xffffffff 0xffffffff ovrlpd >>= \case
+ True -> return ()
+ False -> getLastError >>= failWith "hUnlock"
+ where
+ sizeof_OVERLAPPED = #{size OVERLAPPED}
+
-- https://msdn.microsoft.com/en-us/library/aa297958.aspx
foreign import ccall unsafe "_get_osfhandle"
c_get_osfhandle :: CInt -> IO HANDLE
@@ -154,10 +176,18 @@ foreign import ccall unsafe "_get_osfhandle"
foreign import WINDOWS_CCONV interruptible "LockFileEx"
c_LockFileEx :: HANDLE -> DWORD -> DWORD -> DWORD -> DWORD -> Ptr () -> IO BOOL
+-- https://msdn.microsoft.com/en-us/library/windows/desktop/aa365716.aspx
+foreign import WINDOWS_CCONV interruptible "UnlockFileEx"
+ c_UnlockFileEx :: HANDLE -> DWORD -> DWORD -> DWORD -> Ptr () -> IO BOOL
+
#else
-- | No-op implementation.
lockImpl :: Handle -> String -> LockMode -> Bool -> IO Bool
lockImpl _ _ _ _ = throwIO FileLockingNotSupported
+-- | No-op implementation.
+unlockImpl :: Handle -> IO ()
+unlockImpl _ = throwIO FileLockingNotSupported
+
#endif