[GHC] #8684: hWaitForInput cannot be interrupted by async exceptions on unix
GHC
ghc-devs at haskell.org
Mon Feb 3 17:58:22 UTC 2014
#8684: hWaitForInput cannot be interrupted by async exceptions on unix
-------------------------------------+------------------------------------
Reporter: nh2 | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: libraries/base | Version: 7.6.3
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture: Unknown/Multiple
Type of failure: None/Unknown | Difficulty: Unknown
Test Case: | Blocked By:
Blocking: | Related Tickets:
-------------------------------------+------------------------------------
Comment (by lnandor):
I have tried to fix the bug by replacing select with pselect to ignore the
SIGVTALRM signal sent by the runtime, but to properly terminate when
SIGPIPE is received.
[https://github.com/nandor/packages-base/compare/fix-8684?expand=1]
{{{
diff --git a/GHC/IO/FD.hs b/GHC/IO/FD.hs
index 2023526..0b0b1de 100644
--- a/GHC/IO/FD.hs
+++ b/GHC/IO/FD.hs
@@ -3,6 +3,7 @@
, NoImplicitPrelude
, BangPatterns
, DeriveDataTypeable
+ , InterruptibleFFI
#-}
{-# OPTIONS_GHC -fno-warn-identities #-}
-- Whether there are identities depends on the platform
@@ -395,7 +396,7 @@ setNonBlockingMode fd set = do
ready :: FD -> Bool -> Int -> IO Bool
ready fd write msecs = do
- r <- throwErrnoIfMinus1Retry "GHC.IO.FD.ready" $
+ r <- throwErrnoIfMinus1 "GHC.IO.FD.ready" $
fdReady (fdFD fd) (fromIntegral $ fromEnum $ write)
(fromIntegral msecs)
#if defined(mingw32_HOST_OS)
@@ -405,7 +406,7 @@ ready fd write msecs = do
#endif
return (toEnum (fromIntegral r))
-foreign import ccall safe "fdReady"
+foreign import ccall interruptible "fdReady"
fdReady :: CInt -> CInt -> CInt -> CInt -> IO CInt
--
---------------------------------------------------------------------------
@@ -502,7 +503,7 @@ indicates that there's no data, we call
threadWaitRead.
readRawBufferPtr :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO Int
readRawBufferPtr loc !fd buf off len
| isNonBlocking fd = unsafe_read -- unsafe is ok, it can't block
- | otherwise = do r <- throwErrnoIfMinus1 loc
+ | otherwise = do r <- throwErrnoIfMinus1Retry loc
(unsafe_fdReady (fdFD fd) 0 0 0)
if r /= 0
then read
diff --git a/GHC/IO/Handle/Text.hs b/GHC/IO/Handle/Text.hs
index f182e7f..31f2cac 100644
--- a/GHC/IO/Handle/Text.hs
+++ b/GHC/IO/Handle/Text.hs
@@ -106,7 +106,6 @@ hWaitForInput h msecs = do
writeIORef haCharBuffer cbuf'
if not (isEmptyBuffer cbuf') then return True else do
-
r <- IODevice.ready haDevice False{-read-} msecs
if r then do -- Call hLookAhead' to throw an EOF
-- exception if appropriate
diff --git a/cbits/inputReady.c b/cbits/inputReady.c
index 51f278f..9d51750 100644
--- a/cbits/inputReady.c
+++ b/cbits/inputReady.c
@@ -22,9 +22,10 @@ fdReady(int fd, int write, int msecs, int isSock)
#else
( 1 ) {
#endif
- int maxfd, ready;
+ int maxfd;
fd_set rfd, wfd;
- struct timeval tv;
+ struct timespec tv;
+ sigset_t set;
FD_ZERO(&rfd);
FD_ZERO(&wfd);
@@ -39,16 +40,14 @@ fdReady(int fd, int write, int msecs, int isSock)
*/
maxfd = fd + 1;
tv.tv_sec = msecs / 1000;
- tv.tv_usec = (msecs % 1000) * 1000;
+ tv.tv_nsec = (msecs % 1000) * 1000000;
- while ((ready = select(maxfd, &rfd, &wfd, NULL, &tv)) < 0 ) {
- if (errno != EINTR ) {
- return -1;
- }
- }
+ /* Block SIGVTALRM */
+ sigprocmask(SIG_BLOCK, NULL, &set);
+ sigaddset(&set, SIGVTALRM);
/* 1 => Input ready, 0 => not ready, -1 => error */
- return (ready);
+ return pselect(maxfd, &rfd, &wfd, NULL, &tv, &set);
}
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)
else {
}}}
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8684#comment:3>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list