Commit 92c93544 authored by AndreasVoellmy's avatar AndreasVoellmy

Fix #10017

Summary:
In the threaded RTS, a signal is delivered from the RTS to Haskell
user code by writing to file that one of the IO managers watches (via
an instance of GHC.Event.Control.Control). When the IO manager
receives the signal, it calls GHC.Conc.Signal.runHandlers to invoke
Haskell signal handler. In the move from a single IO manager to one IO
manager per capability, the behavior was (wrongly) extended so that a
signal is delivered to every event manager (see #9423), each of which
invoke Haskell signal handlers, leading to multiple invocations of
Haskell signal handlers for a single signal. This change fixes this
problem by having the RTS (in generic_handler()) notify only the
Control instance used by the TimerManager, rather than all the
per-capability IO managers.

Reviewers: austin, hvr, simonmar, Mikolaj

Reviewed By: simonmar, Mikolaj

Subscribers: thomie

Differential Revision: https://phabricator.haskell.org/D641
parent 07ee96fa
......@@ -72,7 +72,6 @@ import Data.Maybe (maybe)
import Data.OldList (partition)
import GHC.Arr (Array, (!), listArray)
import GHC.Base
import GHC.Conc.Signal (runHandlers)
import GHC.Conc.Sync (yield)
import GHC.List (filter, replicate)
import GHC.Num (Num(..))
......@@ -163,7 +162,7 @@ handleControlEvent mgr fd _evt = do
case msg of
CMsgWakeup -> return ()
CMsgDie -> writeIORef (emState mgr) Finished
CMsgSignal fp s -> runHandlers fp s
_ -> return ()
newDefaultBackend :: IO Backend
#if defined(HAVE_KQUEUE)
......
......@@ -251,18 +251,6 @@ generic_handler(int sig USED_IF_THREADS,
}
}
nat i;
int fd;
for (i=0; i < n_capabilities; i++) {
fd = capabilities[i]->io_manager_control_wr_fd;
if (0 <= fd) {
r = write(fd, buf, sizeof(siginfo_t)+1);
if (r == -1 && errno == EAGAIN) {
errorBelch("lost signal due to full pipe: %d\n", sig);
}
}
}
// If the IO manager hasn't told us what the FD of the write end
// of its pipe is, there's not much we can do here, so just ignore
// the signal..
......
import Control.Concurrent
import System.Posix.Signals
main :: IO ()
main = do
_ <- flip (installHandler sig) Nothing $ Catch $
putStrLn $ "Received my signal"
raiseSignal sig
threadDelay 100000
where
sig = sigUSR2
......@@ -238,6 +238,8 @@ test('T9045', [ omit_ways(['ghci']), extra_run_opts('10000 +RTS -A8k -RTS') ], c
# with the non-threaded one.
test('T9078', [ omit_ways(threaded_ways) ], compile_and_run, ['-with-rtsopts="-DS" -debug'])
test('T10017', [ only_ways(threaded_ways), extra_run_opts('+RTS -N2 -RTS') ], compile_and_run, [''])
test('rdynamic', [ unless(opsys('linux') or opsys('mingw32'), skip)
# this needs runtime infrastructure to do in ghci:
# '-rdynamic' ghc, load modules only via dlopen(RTLD_BLOBAL) and more.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment