summaryrefslogtreecommitdiff
path: root/testsuite
diff options
context:
space:
mode:
authorSergei Trofimovich <slyfox@gentoo.org>2015-07-07 17:00:23 +0200
committerBen Gamari <ben@smart-cactus.org>2015-07-07 19:17:43 +0200
commit5857e0afb5823987e84e6d3dd8d0b269b7546166 (patch)
tree41c3b179e139a19a09dbf605e3a1d4aac6d8b0d7 /testsuite
parent9a3e1657db4c0292fc06d6183a802af631c3666a (diff)
downloadhaskell-5857e0afb5823987e84e6d3dd8d0b269b7546166.tar.gz
fix EBADF unqueueing in select backend (Trac #10590)
Alexander found a interesting case: 1. We have a queue of two waiters in a blocked_queue 2. first file descriptor changes state to RUNNABLE, second changes to INVALID 3. awaitEvent function dequeued RUNNABLE thread to a run queue and attempted to dequeue INVALID descriptor to a run queue. Unqueueing INVALID fails thusly: #3 0x000000000045cf1c in barf (s=0x4c1cb0 "removeThreadFromDeQueue: not found") at rts/RtsMessages.c:42 #4 0x000000000046848b in removeThreadFromDeQueue (...) at rts/Threads.c:249 #5 0x000000000049a120 in removeFromQueues (...) at rts/RaiseAsync.c:719 #6 0x0000000000499502 in throwToSingleThreaded__ (...) at rts/RaiseAsync.c:67 #7 0x0000000000499555 in throwToSingleThreaded (..) at rts/RaiseAsync.c:75 #8 0x000000000047c27d in awaitEvent (wait=rtsFalse) at rts/posix/Select.c:415 The problem here is a throwToSingleThreaded function that tries to unqueue a TSO from blocked_queue, but awaitEvent function leaves blocked_queue in a inconsistent state while traverses over blocked_queue: case RTS_FD_IS_READY: IF_DEBUG(scheduler, debugBelch("Waking up blocked thread %lu\n", (unsigned long)tso->id)); tso->why_blocked = NotBlocked; tso->_link = END_TSO_QUEUE; // Here we break the queue head pushOnRunQueue(&MainCapability,tso); break; Signed-off-by: Sergei Trofimovich <siarheit@google.com> Test Plan: tested on a sample from T10590 Reviewers: austin, bgamari, simonmar Reviewed By: bgamari, simonmar Subscribers: qnikst, thomie, bgamari Differential Revision: https://phabricator.haskell.org/D1024 GHC Trac Issues: #10590, #4934
Diffstat (limited to 'testsuite')
-rw-r--r--testsuite/tests/rts/T10590.hs37
-rw-r--r--testsuite/tests/rts/all.T5
2 files changed, 42 insertions, 0 deletions
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, [''])