unix 2.8.0.0 → 2.8.1.0
raw patch · 22 files changed
+312/−55 lines, 22 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
+ System.Posix.Semaphore: semWaitInterruptible :: Semaphore -> IO Bool
Files
- System/Posix/Directory.hsc +4/−7
- System/Posix/Directory/ByteString.hsc +4/−7
- System/Posix/Directory/Common.hsc +15/−0
- System/Posix/Directory/PosixPath.hsc +4/−14
- System/Posix/DynamicLinker/Module.hsc +12/−3
- System/Posix/DynamicLinker/Prim.hsc +10/−2
- System/Posix/Files.hsc +11/−1
- System/Posix/Files/ByteString.hsc +11/−1
- System/Posix/Files/Common.hsc +31/−5
- System/Posix/Files/PosixString.hsc +24/−0
- System/Posix/Semaphore.hsc +34/−5
- System/Posix/Signals.hsc +1/−1
- System/Posix/Temp/PosixString.hsc +15/−0
- System/Posix/Terminal/Common.hsc +16/−1
- changelog.md +27/−0
- configure +17/−5
- configure.ac +1/−0
- include/HsUnixConfig.h.in +9/−0
- tests/Semaphore001.hs +1/−1
- tests/Semaphore002.hs +15/−0
- tests/SemaphoreInterrupt.hs +32/−0
- unix.cabal +18/−2
System/Posix/Directory.hsc view
@@ -49,7 +49,6 @@ ) where import Data.Maybe-import System.IO.Error import System.Posix.Error import System.Posix.Types import Foreign@@ -157,18 +156,16 @@ -- the current working directory to @dir@. changeWorkingDirectory :: FilePath -> IO () changeWorkingDirectory path =- modifyIOError (`ioeSetFileName` path) $- withFilePath path $ \s ->- throwErrnoIfMinus1Retry_ "changeWorkingDirectory" (c_chdir s)+ withFilePath path $ \s ->+ throwErrnoPathIfMinus1Retry_ "changeWorkingDirectory" path (c_chdir s) foreign import ccall unsafe "chdir" c_chdir :: CString -> IO CInt removeDirectory :: FilePath -> IO () removeDirectory path =- modifyIOError (`ioeSetFileName` path) $- withFilePath path $ \s ->- throwErrnoIfMinus1Retry_ "removeDirectory" (c_rmdir s)+ withFilePath path $ \s ->+ throwErrnoPathIfMinus1Retry_ "removeDirectory" path (c_rmdir s) foreign import ccall unsafe "rmdir" c_rmdir :: CString -> IO CInt
System/Posix/Directory/ByteString.hsc view
@@ -49,7 +49,6 @@ ) where import Data.Maybe-import System.IO.Error import System.Posix.Types import Foreign import Foreign.C@@ -158,18 +157,16 @@ -- the current working directory to @dir@. changeWorkingDirectory :: RawFilePath -> IO () changeWorkingDirectory path =- modifyIOError (`ioeSetFileName` (BC.unpack path)) $- withFilePath path $ \s ->- throwErrnoIfMinus1Retry_ "changeWorkingDirectory" (c_chdir s)+ withFilePath path $ \s ->+ throwErrnoPathIfMinus1Retry_ "changeWorkingDirectory" path (c_chdir s) foreign import ccall unsafe "chdir" c_chdir :: CString -> IO CInt removeDirectory :: RawFilePath -> IO () removeDirectory path =- modifyIOError (`ioeSetFileName` BC.unpack path) $- withFilePath path $ \s ->- throwErrnoIfMinus1Retry_ "removeDirectory" (c_rmdir s)+ withFilePath path $ \s ->+ throwErrnoPathIfMinus1Retry_ "removeDirectory" path (c_rmdir s) foreign import ccall unsafe "rmdir" c_rmdir :: CString -> IO CInt
System/Posix/Directory/Common.hsc view
@@ -36,6 +36,11 @@ import Foreign hiding (void) import Foreign.C +#if !defined(HAVE_FCHDIR)+import System.IO.Error ( ioeSetLocation )+import GHC.IO.Exception ( unsupportedOperation )+#endif+ newtype DirStream = DirStream (Ptr CDir) data {-# CTYPE "DIR" #-} CDir@@ -111,9 +116,19 @@ c_telldir :: Ptr CDir -> IO CLong #endif +#if defined(HAVE_FCHDIR)+ changeWorkingDirectoryFd :: Fd -> IO () changeWorkingDirectoryFd (Fd fd) = throwErrnoIfMinus1Retry_ "changeWorkingDirectoryFd" (c_fchdir fd) foreign import ccall unsafe "fchdir" c_fchdir :: CInt -> IO CInt++#else++{-# WARNING changeWorkingDirectoryFd "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_FCHDIR@)" #-}+changeWorkingDirectoryFd :: Fd -> IO ()+changeWorkingDirectoryFd _ = ioError (ioeSetLocation unsupportedOperation "changeWorkingDirectoryFd")++#endif // HAVE_FCHDIR
System/Posix/Directory/PosixPath.hsc view
@@ -46,15 +46,11 @@ changeWorkingDirectoryFd, ) where -import System.IO.Error import System.Posix.Types import Foreign import Foreign.C import System.OsPath.Types-import GHC.IO.Encoding.UTF8 ( mkUTF8 )-import GHC.IO.Encoding.Failure ( CodingFailureMode(..) )-import System.OsPath.Posix import System.Posix.Directory hiding (createDirectory, openDirStream, readDirStream, getWorkingDirectory, changeWorkingDirectory, removeDirectory) import qualified System.Posix.Directory.Common as Common import System.Posix.PosixPath.FilePath@@ -145,22 +141,16 @@ -- the current working directory to @dir@. changeWorkingDirectory :: PosixPath -> IO () changeWorkingDirectory path =- modifyIOError (`ioeSetFileName` (_toStr path)) $- withFilePath path $ \s ->- throwErrnoIfMinus1Retry_ "changeWorkingDirectory" (c_chdir s)+ withFilePath path $ \s ->+ throwErrnoPathIfMinus1Retry_ "changeWorkingDirectory" path (c_chdir s) foreign import ccall unsafe "chdir" c_chdir :: CString -> IO CInt removeDirectory :: PosixPath -> IO () removeDirectory path =- modifyIOError (`ioeSetFileName` _toStr path) $- withFilePath path $ \s ->- throwErrnoIfMinus1Retry_ "removeDirectory" (c_rmdir s)+ withFilePath path $ \s ->+ throwErrnoPathIfMinus1Retry_ "removeDirectory" path (c_rmdir s) foreign import ccall unsafe "rmdir" c_rmdir :: CString -> IO CInt--_toStr :: PosixPath -> String-_toStr fp = either (error . show) id $ decodeWith (mkUTF8 TransliterateCodingFailure) fp-
System/Posix/DynamicLinker/Module.hsc view
@@ -56,6 +56,7 @@ #include "HsUnix.h" +import Prelude hiding (head, tail) import System.Posix.DynamicLinker import System.Posix.DynamicLinker.Common import Foreign.Ptr ( Ptr, nullPtr, FunPtr )@@ -101,9 +102,10 @@ withModule mdir file flags p = do let modPath = case mdir of Nothing -> file- Just dir -> dir ++ if ((head (reverse dir)) == '/')- then file- else ('/':file)+ Just dir -> dir ++ case unsnoc dir of+ Just (_, '/') -> file+ Just{} -> '/' : file+ Nothing -> error "System.Posix.DynamicLinker.Module.withModule: directory should not be Just \"\", pass Nothing instead" modu <- moduleOpen modPath flags result <- p modu moduleClose modu@@ -115,3 +117,10 @@ -> (Module -> IO a) -> IO () withModule_ dir file flags p = withModule dir file flags p >>= \ _ -> return ()++-- Dual to 'Data.List.uncons'.+unsnoc :: [a] -> Maybe ([a], a)+unsnoc = foldr go Nothing+ where+ go x Nothing = Just ([], x)+ go x (Just (xs, lst)) = Just (x : xs, lst)
System/Posix/DynamicLinker/Prim.hsc view
@@ -1,3 +1,4 @@+{-# LANGUAGE CApiFFI #-} {-# LANGUAGE Trustworthy #-} {-# OPTIONS_GHC -Wno-trustworthy-safe #-} @@ -84,10 +85,17 @@ | RTLD_LOCAL deriving (Show, Read) -foreign import ccall unsafe "dlopen" c_dlopen :: CString -> CInt -> IO (Ptr ())+#if defined(HAVE_DLFCN_H)+foreign import capi safe "dlfcn.h dlopen" c_dlopen :: CString -> CInt -> IO (Ptr ())+foreign import capi unsafe "dlfcn.h dlsym" c_dlsym :: Ptr () -> CString -> IO (FunPtr a)+foreign import capi unsafe "dlfcn.h dlerror" c_dlerror :: IO CString+foreign import capi safe "dlfcn.h dlclose" c_dlclose :: (Ptr ()) -> IO CInt+#else+foreign import ccall safe "dlopen" c_dlopen :: CString -> CInt -> IO (Ptr ()) foreign import ccall unsafe "dlsym" c_dlsym :: Ptr () -> CString -> IO (FunPtr a) foreign import ccall unsafe "dlerror" c_dlerror :: IO CString-foreign import ccall unsafe "dlclose" c_dlclose :: (Ptr ()) -> IO CInt+foreign import ccall safe "dlclose" c_dlclose :: (Ptr ()) -> IO CInt+#endif // HAVE_DLFCN_H packRTLDFlags :: [RTLDFlags] -> CInt packRTLDFlags flags = foldl (\ s f -> (packRTLDFlag f) .|. s) 0 flags
System/Posix/Files.hsc view
@@ -108,7 +108,7 @@ import Data.Time.Clock.POSIX (POSIXTime) -#if !defined(HAVE_MKNOD)+#if !defined(HAVE_MKNOD) || !defined(HAVE_CHOWN) import System.IO.Error ( ioeSetLocation ) import GHC.IO.Exception ( unsupportedOperation ) #endif@@ -323,6 +323,8 @@ -- ----------------------------------------------------------------------------- -- chown() +#if defined(HAVE_CHOWN)+ -- | @setOwnerAndGroup path uid gid@ changes the owner and group of @path@ to -- @uid@ and @gid@, respectively. --@@ -336,6 +338,14 @@ foreign import ccall unsafe "chown" c_chown :: CString -> CUid -> CGid -> IO CInt++#else++{-# WARNING setOwnerAndGroup "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_CHOWN@)" #-}+setOwnerAndGroup :: FilePath -> UserID -> GroupID -> IO ()+setOwnerAndGroup _ _ _ = ioError (ioeSetLocation unsupportedOperation "setOwnerAndGroup")++#endif // HAVE_CHOWN #if HAVE_LCHOWN -- | Acts as 'setOwnerAndGroup' but does not follow symlinks (and thus
System/Posix/Files/ByteString.hsc view
@@ -109,7 +109,7 @@ import Data.Time.Clock.POSIX (POSIXTime) -#if !defined(HAVE_MKNOD)+#if !defined(HAVE_MKNOD) || !defined(HAVE_CHOWN) import System.IO.Error ( ioeSetLocation ) import GHC.IO.Exception ( unsupportedOperation ) #endif@@ -319,6 +319,8 @@ -- ----------------------------------------------------------------------------- -- chown() +#if defined(HAVE_CHOWN)+ -- | @setOwnerAndGroup path uid gid@ changes the owner and group of @path@ to -- @uid@ and @gid@, respectively. --@@ -332,6 +334,14 @@ foreign import ccall unsafe "chown" c_chown :: CString -> CUid -> CGid -> IO CInt++#else++{-# WARNING setOwnerAndGroup "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_CHOWN@)" #-}+setOwnerAndGroup :: RawFilePath -> UserID -> GroupID -> IO ()+setOwnerAndGroup _ _ _ = ioError (ioeSetLocation unsupportedOperation "setOwnerAndGroup")++#endif // HAVE_CHOWN #if HAVE_LCHOWN -- | Acts as 'setOwnerAndGroup' but does not follow symlinks (and thus
System/Posix/Files/Common.hsc view
@@ -1,3 +1,4 @@+{-# LANGUAGE CApiFFI #-} {-# LANGUAGE Trustworthy #-} -----------------------------------------------------------------------------@@ -97,6 +98,11 @@ import Foreign.Ptr import Foreign.Storable +#if !defined(HAVE_FCHMOD) || !defined(HAVE_CHOWN)+import System.IO.Error ( ioeSetLocation )+import GHC.IO.Exception ( unsupportedOperation )+#endif+ -- ----------------------------------------------------------------------------- -- POSIX file modes @@ -207,6 +213,8 @@ socketMode :: FileMode socketMode = (#const S_IFSOCK) +#if defined(HAVE_FCHMOD)+ -- | @setFdMode fd mode@ acts like 'setFileMode' but uses a file descriptor -- @fd@ instead of a 'FilePath'. --@@ -218,6 +226,14 @@ foreign import ccall unsafe "fchmod" c_fchmod :: CInt -> CMode -> IO CInt +#else++{-# WARNING setFdMode "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_FCHMOD@)" #-}+setFdMode :: Fd -> FileMode -> IO ()+setFdMode _ _ = ioError (ioeSetLocation unsupportedOperation "setFdMode")++#endif // HAVE_FCHMOD+ -- | @setFileCreationMask mode@ sets the file mode creation mask to @mode@. -- Modes set by this operation are subtracted from files and directories upon -- creation. The previous file creation mask is returned.@@ -452,12 +468,12 @@ #endif #ifdef HAVE_UTIMENSAT-foreign import ccall unsafe "utimensat"+foreign import capi unsafe "sys/stat.h utimensat" c_utimensat :: CInt -> CString -> Ptr CTimeSpec -> CInt -> IO CInt #endif #if HAVE_FUTIMENS-foreign import ccall unsafe "futimens"+foreign import capi unsafe "sys/stat.h futimens" c_futimens :: CInt -> Ptr CTimeSpec -> IO CInt #endif @@ -480,16 +496,16 @@ (sec, frac) = if (frac' < 0) then (sec' - 1, frac' + 1) else (sec', frac') (sec', frac') = properFraction $ toRational t -foreign import ccall unsafe "utimes"+foreign import capi unsafe "sys/time.h utimes" c_utimes :: CString -> Ptr CTimeVal -> IO CInt #ifdef HAVE_LUTIMES-foreign import ccall unsafe "lutimes"+foreign import capi unsafe "sys/time.h lutimes" c_lutimes :: CString -> Ptr CTimeVal -> IO CInt #endif #if HAVE_FUTIMES-foreign import ccall unsafe "futimes"+foreign import capi unsafe "sys/time.h futimes" c_futimes :: CInt -> Ptr CTimeVal -> IO CInt #endif @@ -539,6 +555,8 @@ -- ----------------------------------------------------------------------------- -- fchown() +#if defined(HAVE_CHOWN)+ -- | Acts as 'setOwnerAndGroup' but uses a file descriptor instead of a -- 'FilePath'. --@@ -549,6 +567,14 @@ foreign import ccall unsafe "fchown" c_fchown :: CInt -> CUid -> CGid -> IO CInt++#else++{-# WARNING setFdOwnerAndGroup "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_CHOWN@)" #-}+setFdOwnerAndGroup :: Fd -> UserID -> GroupID -> IO ()+setFdOwnerAndGroup _ _ _ = ioError (ioeSetLocation unsupportedOperation "setFdOwnerAndGroup")++#endif // HAVE_CHOWN -- ----------------------------------------------------------------------------- -- ftruncate()
System/Posix/Files/PosixString.hsc view
@@ -107,6 +107,11 @@ import Data.Time.Clock.POSIX (POSIXTime) +#if !defined(HAVE_MKNOD) || !defined(HAVE_CHOWN)+import System.IO.Error ( ioeSetLocation )+import GHC.IO.Exception ( unsupportedOperation )+#endif+ -- ----------------------------------------------------------------------------- -- chmod() @@ -205,6 +210,13 @@ withFilePath name $ \s -> throwErrnoPathIfMinus1_ "createNamedPipe" name (c_mkfifo s mode) +#if !defined(HAVE_MKNOD)++{-# WARNING createDevice "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_MKNOD@)" #-}+createDevice :: PosixPath -> FileMode -> DeviceID -> IO ()+createDevice _ _ _ = ioError (ioeSetLocation unsupportedOperation "createDevice")++#else -- | @createDevice path mode dev@ creates either a regular or a special file -- depending on the value of @mode@ (and @dev@). @mode@ will normally be either -- 'blockSpecialMode' or 'characterSpecialMode'. May fail with@@ -221,6 +233,8 @@ foreign import capi unsafe "HsUnix.h mknod" c_mknod :: CString -> CMode -> CDev -> IO CInt +#endif // HAVE_MKNOD+ -- ----------------------------------------------------------------------------- -- Hard links @@ -302,6 +316,8 @@ -- ----------------------------------------------------------------------------- -- chown() +#if defined(HAVE_CHOWN)+ -- | @setOwnerAndGroup path uid gid@ changes the owner and group of @path@ to -- @uid@ and @gid@, respectively. --@@ -315,6 +331,14 @@ foreign import ccall unsafe "chown" c_chown :: CString -> CUid -> CGid -> IO CInt++#else++{-# WARNING setOwnerAndGroup "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_CHOWN@)" #-}+setOwnerAndGroup :: PosixPath -> UserID -> GroupID -> IO ()+setOwnerAndGroup _ _ _ = ioError (ioeSetLocation unsupportedOperation "setOwnerAndGroup")++#endif // HAVE_CHOWN #if HAVE_LCHOWN -- | Acts as 'setOwnerAndGroup' but does not follow symlinks (and thus
System/Posix/Semaphore.hsc view
@@ -1,5 +1,6 @@ {-# LANGUAGE Safe #-} {-# LANGUAGE CApiFFI #-}+{-# LANGUAGE InterruptibleFFI #-} ----------------------------------------------------------------------------- -- | -- Module : System.Posix.Semaphore@@ -16,7 +17,7 @@ module System.Posix.Semaphore (OpenSemFlags(..), Semaphore(),- semOpen, semUnlink, semWait, semTryWait, semThreadWait,+ semOpen, semUnlink, semWait, semWaitInterruptible, semTryWait, semThreadWait, semPost, semGetValue) where @@ -39,6 +40,13 @@ import Foreign.Storable #endif +#if __GLASGOW_HASKELL__ >= 902+import System.Posix.Internals (hostIsThreaded)+#else+hostIsThreaded :: Bool+hostIsThreaded = False+#endif+ data OpenSemFlags = OpenSemFlags { semCreate :: Bool, -- ^ If true, create the semaphore if it -- does not yet exist.@@ -79,6 +87,20 @@ where semWait' sem = throwErrnoIfMinus1Retry_ "semWait" $ sem_wait sem +-- | Lock the semaphore, blocking until it becomes available.+--+-- Unlike 'semWait', this wait operation can be interrupted with+-- an asynchronous exception (e.g. a call to 'throwTo' from another thread).+semWaitInterruptible :: Semaphore -> IO Bool+semWaitInterruptible (Semaphore fptr) = withForeignPtr fptr semWait'+ where semWait' sem =+ do res <- sem_wait_interruptible sem+ if res == 0 then return True+ else do errno <- getErrno+ if errno == eINTR+ then return False+ else throwErrno "semWaitInterrruptible"+ -- | Attempt to lock the semaphore without blocking. Immediately return -- False if it is not available. semTryWait :: Semaphore -> IO Bool@@ -96,9 +118,15 @@ -- semWait, this will block only the current thread rather than the -- entire process. semThreadWait :: Semaphore -> IO ()-semThreadWait sem = do res <- semTryWait sem- (if res then return ()- else ( do { yield; semThreadWait sem } ))+semThreadWait sem+ -- N.B. semWait can be safely used in the case of the threaded runtime, where+ -- the safe foreign call will be performed in its own thread, thereby not+ -- blocking the process.+ | hostIsThreaded = semWait sem+ | otherwise = do+ res <- semTryWait sem+ if res then return ()+ else do yield >> semThreadWait sem -- | Unlock the semaphore. semPost :: Semaphore -> IO ()@@ -132,9 +160,10 @@ sem_close :: Ptr () -> IO CInt foreign import capi safe "semaphore.h sem_unlink" sem_unlink :: CString -> IO CInt- foreign import capi safe "semaphore.h sem_wait" sem_wait :: Ptr () -> IO CInt+foreign import capi interruptible "semaphore.h sem_wait"+ sem_wait_interruptible :: Ptr () -> IO CInt foreign import capi safe "semaphore.h sem_trywait" sem_trywait :: Ptr () -> IO CInt foreign import capi safe "semaphore.h sem_post"
System/Posix/Signals.hsc view
@@ -101,7 +101,7 @@ import Foreign.Marshal import Foreign.Ptr import Foreign.Storable-#if !defined(HAVE_SIGNAL_H)+#if !defined(HAVE_SIGNAL_H) || !defined(HAVE_ALARM) import System.IO.Error ( ioeSetLocation ) import GHC.IO.Exception ( unsupportedOperation ) #endif
System/Posix/Temp/PosixString.hsc view
@@ -35,6 +35,19 @@ import System.Posix.IO.PosixString import System.Posix.Types +#if !defined(HAVE_MKSTEMP)+import System.IO.Error ( ioeSetLocation )+import GHC.IO.Exception ( unsupportedOperation )+#endif++#if !defined(HAVE_MKSTEMP)++{-# WARNING mkstemp "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_MKSTEMP@)" #-}+mkstemp :: PosixString -> IO (PosixPath, Handle)+mkstemp _ = ioError (ioeSetLocation unsupportedOperation "mkstemp")++#else+ foreign import capi unsafe "HsUnix.h mkstemp" c_mkstemp :: CString -> IO CInt @@ -53,6 +66,8 @@ name <- peekFilePath ptr h <- fdToHandle (Fd fd) return (name, h)++#endif // HAVE_MKSTEMP #if HAVE_MKSTEMPS foreign import capi unsafe "HsUnix.h mkstemps"
System/Posix/Terminal/Common.hsc view
@@ -216,13 +216,16 @@ | ReturnMeansLF -- ^ @ONLRET@ - (XSI) NL performs CR function -- -- @since 2.8.0.0+#ifdef TAB0 | TabDelayMask0 -- ^ @TABDLY(TAB0)@ - (XSI) Select horizontal-tab delays: type 0 -- -- @since 2.8.0.0+#endif+#ifdef TAB3 | TabDelayMask3 -- ^ @TABDLY(TAB3)@ - (XSI) Select horizontal-tab delays: type 3 -- -- @since 2.8.0.0-+#endif -- control flags | LocalMode -- ^ @CLOCAL@ - Ignore modem status lines | ReadEnable -- ^ @CREAD@ - Enable receiver@@ -289,8 +292,12 @@ withoutMode termios OutputMapCRtoLF = clearOutputFlag (#const OCRNL) termios withoutMode termios NoCRAtColumnZero = clearOutputFlag (#const ONOCR) termios withoutMode termios ReturnMeansLF = clearOutputFlag (#const ONLRET) termios+#ifdef TAB0 withoutMode termios TabDelayMask0 = clearOutputFlag (#const TAB0) termios+#endif+#ifdef TAB3 withoutMode termios TabDelayMask3 = clearOutputFlag (#const TAB3) termios+#endif withoutMode termios LocalMode = clearControlFlag (#const CLOCAL) termios withoutMode termios ReadEnable = clearControlFlag (#const CREAD) termios withoutMode termios TwoStopBits = clearControlFlag (#const CSTOPB) termios@@ -325,8 +332,12 @@ withMode termios OutputMapCRtoLF = setOutputFlag (#const OCRNL) termios withMode termios NoCRAtColumnZero = setOutputFlag (#const ONOCR) termios withMode termios ReturnMeansLF = setOutputFlag (#const ONLRET) termios+#ifdef TAB0 withMode termios TabDelayMask0 = setOutputFlag (#const TAB0) termios+#endif+#ifdef TAB3 withMode termios TabDelayMask3 = setOutputFlag (#const TAB3) termios+#endif withMode termios LocalMode = setControlFlag (#const CLOCAL) termios withMode termios ReadEnable = setControlFlag (#const CREAD) termios withMode termios TwoStopBits = setControlFlag (#const CSTOPB) termios@@ -361,8 +372,12 @@ terminalMode OutputMapCRtoLF = testOutputFlag (#const OCRNL) terminalMode NoCRAtColumnZero = testOutputFlag (#const ONOCR) terminalMode ReturnMeansLF = testOutputFlag (#const ONLRET)+#ifdef TAB0 terminalMode TabDelayMask0 = testOutputFlag (#const TAB0)+#endif+#ifdef TAB3 terminalMode TabDelayMask3 = testOutputFlag (#const TAB3)+#endif terminalMode LocalMode = testControlFlag (#const CLOCAL) terminalMode ReadEnable = testControlFlag (#const CREAD) terminalMode TwoStopBits = testControlFlag (#const CSTOPB)
changelog.md view
@@ -1,5 +1,32 @@ # Changelog for [`unix` package](http://hackage.haskell.org/package/unix) +## 2.8.1.0 *Feb 2023*+ * Fix build if HAVE_ALARM is undefined++ * Add missing autoconf checks for chown/fchdir/fchmod++ * Make TABX constructors and code conditional on underlying #defines++ * Bump bounds to accomodate base-4.18++ * Add semWaitInterruptible++ * semaphore: Teach semThreadWait to use semWait with threaded RTS++ * make the foreign imports of dlopen & dlclose safe++ * do not use capi for dlfcn.h stuff under wasm-wasi++ * Use capi for syscalls that break under musl's handling of 64-bit `time_t`++ * Replace `last` with `unsnoc`++ * Avoid Data.List.{head,tail}++ * Consistently use `throwErrnoPathIf*`++ * Fix WASI build+ ## 2.8.0.0 *August 2022* * Use ByteString for GroupEntry/UserEntry
configure view
@@ -3824,7 +3824,7 @@ We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1];@@ -3870,7 +3870,7 @@ We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1];@@ -3894,7 +3894,7 @@ We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1];@@ -3939,7 +3939,7 @@ We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1];@@ -3963,7 +3963,7 @@ We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1];@@ -4230,6 +4230,18 @@ if test "x$ac_cv_func_times" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_TIMES 1+_ACEOF++fi+done++for ac_func in chown fchdir fchmod+do :+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :+ cat >>confdefs.h <<_ACEOF+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi
configure.ac view
@@ -42,6 +42,7 @@ AC_CHECK_FUNCS([mkstemp]) AC_CHECK_FUNCS([pipe]) AC_CHECK_FUNCS([times])+AC_CHECK_FUNCS([chown fchdir fchmod]) AC_CHECK_TYPE([struct rlimit],[AC_DEFINE([HAVE_STRUCT_RLIMIT],[1],[HAVE_STRUCT_RLIMIT])],[],[#include <sys/resource.h>])
include/HsUnixConfig.h.in view
@@ -105,6 +105,9 @@ /* Define to 1 if you have the <bsd/libutil.h> header file. */ #undef HAVE_BSD_LIBUTIL_H +/* Define to 1 if you have the `chown' function. */+#undef HAVE_CHOWN+ /* Define to 1 if you have the `clearenv' function. */ #undef HAVE_CLEARENV @@ -155,6 +158,12 @@ /* Define to 1 if you have the `execvpe' function. */ #undef HAVE_EXECVPE++/* Define to 1 if you have the `fchdir' function. */+#undef HAVE_FCHDIR++/* Define to 1 if you have the `fchmod' function. */+#undef HAVE_FCHMOD /* Define to 1 if you have the <fcntl.h> header file. */ #undef HAVE_FCNTL_H
tests/Semaphore001.hs view
@@ -4,6 +4,6 @@ main :: IO () main = do- sem <- semOpen "/test" OpenSemFlags {semCreate = True, semExclusive = False} stdFileMode 1+ sem <- semOpen "/test-001" OpenSemFlags {semCreate = True, semExclusive = False} stdFileMode 1 semThreadWait sem semPost sem
+ tests/Semaphore002.hs view
@@ -0,0 +1,15 @@+module Main (main) where++import Control.Concurrent+import System.Posix++main :: IO ()+main = do+ sem <- semOpen "/test-002" OpenSemFlags {semCreate = True, semExclusive = False} stdFileMode 0+ _ <- forkIO $ do+ threadDelay (1000*1000)+ semPost sem++ -- This should succeed after 1 second.+ semThreadWait sem+ semPost sem
+ tests/SemaphoreInterrupt.hs view
@@ -0,0 +1,32 @@+module Main (main) where++import Control.Concurrent+import Control.Monad+import Data.IORef+import System.Posix++main :: IO ()+main = do++ sem <- semOpen "/test-interrupt" OpenSemFlags {semCreate = True, semExclusive = False} stdFileMode 0+ ref <- newIORef False+ _ <- forkIO $ do+ res <- semWaitInterruptible sem+ writeIORef ref res+ threadDelay 100000 -- 100 ms+ semPost sem+ threadDelay 100000 -- 100 ms+ succ1 <- readIORef ref+ unless succ1 $+ error "SemaphoreInterrupt: semWaitInterruptible failed"++ writeIORef ref False+ tid <- forkIO $ do+ res <- semWaitInterruptible sem+ writeIORef ref res+ threadDelay 100000 -- 100 ms+ killThread tid+ threadDelay 100000 -- 100 ms+ succ2 <- readIORef ref+ when succ2 $+ error "SemaphoreInterrupt: semWaitInterruptible not interrupted"
unix.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.12 name: unix-version: 2.8.0.0+version: 2.8.1.0 -- NOTE: Don't forget to update ./changelog.md license: BSD3@@ -69,7 +69,7 @@ buildable: False build-depends:- base >= 4.10 && < 4.18,+ base >= 4.10 && < 4.19, bytestring >= 0.9.2 && < 0.12, filepath >= 1.4.100.0 && < 1.5, time >= 1.2 && < 1.13@@ -262,3 +262,19 @@ default-language: Haskell2010 build-depends: base, unix ghc-options: -Wall++test-suite Semaphore002+ hs-source-dirs: tests+ main-is: Semaphore002.hs+ type: exitcode-stdio-1.0+ default-language: Haskell2010+ build-depends: base, unix+ ghc-options: -Wall -threaded++test-suite SemaphoreInterrupt+ hs-source-dirs: tests+ main-is: SemaphoreInterrupt.hs+ type: exitcode-stdio-1.0+ default-language: Haskell2010+ build-depends: base, unix+ ghc-options: -Wall -threaded