summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rts/RaiseAsync.c8
-rw-r--r--rts/RaiseAsync.h6
-rw-r--r--rts/posix/Select.c10
-rw-r--r--testsuite/tests/rts/T10590.hs37
-rw-r--r--testsuite/tests/rts/all.T5
5 files changed, 57 insertions, 9 deletions
diff --git a/rts/RaiseAsync.c b/rts/RaiseAsync.c
index 3b206ffa7e..267707cefb 100644
--- a/rts/RaiseAsync.c
+++ b/rts/RaiseAsync.c
@@ -23,12 +23,6 @@
#include "win32/IOManager.h"
#endif
-static StgTSO* raiseAsync (Capability *cap,
- StgTSO *tso,
- StgClosure *exception,
- rtsBool stop_at_atomically,
- StgUpdateFrame *stop_here);
-
static void removeFromQueues(Capability *cap, StgTSO *tso);
static void removeFromMVarBlockedQueue (StgTSO *tso);
@@ -777,7 +771,7 @@ removeFromQueues(Capability *cap, StgTSO *tso)
*
* -------------------------------------------------------------------------- */
-static StgTSO *
+StgTSO *
raiseAsync(Capability *cap, StgTSO *tso, StgClosure *exception,
rtsBool stop_at_atomically, StgUpdateFrame *stop_here)
{
diff --git a/rts/RaiseAsync.h b/rts/RaiseAsync.h
index 6bfed8d6ca..1f939d4000 100644
--- a/rts/RaiseAsync.h
+++ b/rts/RaiseAsync.h
@@ -19,6 +19,12 @@
void blockedThrowTo (Capability *cap,
StgTSO *target, MessageThrowTo *msg);
+StgTSO* raiseAsync (Capability *cap,
+ StgTSO *tso,
+ StgClosure *exception,
+ rtsBool stop_at_atomically,
+ StgUpdateFrame *stop_here);
+
void throwToSingleThreaded (Capability *cap,
StgTSO *tso,
StgClosure *exception);
diff --git a/rts/posix/Select.c b/rts/posix/Select.c
index 4b1923504b..d5c9b553cb 100644
--- a/rts/posix/Select.c
+++ b/rts/posix/Select.c
@@ -375,6 +375,12 @@ awaitEvent(rtsBool wait)
prev = NULL;
{
+ /*
+ * The queue is being rebuilt in this loop:
+ * 'blocked_queue_hd' will contain already
+ * traversed blocked TSOs. As a result you
+ * can't use functions accessing 'blocked_queue_hd'.
+ */
for(tso = blocked_queue_hd; tso != END_TSO_QUEUE; tso = next) {
next = tso->_link;
int fd;
@@ -412,8 +418,8 @@ awaitEvent(rtsBool wait)
IF_DEBUG(scheduler,
debugBelch("Killing blocked thread %lu on bad fd=%i\n",
(unsigned long)tso->id, fd));
- throwToSingleThreaded(&MainCapability, tso,
- (StgClosure *)blockedOnBadFD_closure);
+ raiseAsync(&MainCapability, tso,
+ (StgClosure *)blockedOnBadFD_closure, rtsFalse, NULL);
break;
case RTS_FD_IS_READY:
IF_DEBUG(scheduler,
diff --git a/testsuite/tests/rts/T10590.hs b/testsuite/tests/rts/T10590.hs
new file mode 100644
index 0000000000..24198abb30
--- /dev/null
+++ b/testsuite/tests/rts/T10590.hs
@@ -0,0 +1,37 @@
+import Foreign.C
+import Foreign.Marshal.Array
+import Foreign.Storable
+import Control.Concurrent
+
+-- The test works only on UNIX like.
+-- unportable bits:
+import qualified System.Posix.Internals as SPI
+import qualified System.Posix.Types as SPT
+
+pipe :: IO (CInt, CInt)
+pipe = allocaArray 2 $ \fds -> do
+ throwErrnoIfMinus1_ "pipe" $ SPI.c_pipe fds
+ rd <- peekElemOff fds 0
+ wr <- peekElemOff fds 1
+ return (rd, wr)
+
+main :: IO ()
+main = do
+ (r1, w1) <- pipe
+ (r2, _w2) <- pipe
+ _ <- forkIO $ do -- thread A
+ threadWaitRead (SPT.Fd r1)
+ _ <- forkIO $ do -- thread B
+ threadWaitRead (SPT.Fd r2)
+ yield -- switch to A, then B
+ -- now both are blocked
+ _ <- SPI.c_close w1 -- unblocking thread A fd
+ _ <- SPI.c_close r2 -- breaking thread B fd
+ yield -- kick RTS IO manager
+
+{-
+ Trac #10590 exposed a bug as:
+ T10590: internal error: removeThreadFromDeQueue: not found
+ (GHC version 7.11.20150702 for x86_64_unknown_linux)
+ Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
+ -}
diff --git a/testsuite/tests/rts/all.T b/testsuite/tests/rts/all.T
index 8f6137f9d4..0e892499e0 100644
--- a/testsuite/tests/rts/all.T
+++ b/testsuite/tests/rts/all.T
@@ -318,3 +318,8 @@ test('T9839_05', [ only_ways(prof_ways), ignore_output, exit_code(1), extra_run_
test('T9839_06', [ only_ways(prof_ways), ignore_output, exit_code(1), extra_run_opts('+RTS -xtx')],
compile_and_run,
[''])
+
+# ignore_output as RTS reports slightly different error messages
+# in 'epoll' and 'select' backends on reading from EBADF
+# mingw32 skip as UNIX pipe and close(fd) is used to exercise the problem
+test('T10590', [ignore_output, when(opsys('mingw32'),skip)], compile_and_run, [''])