summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--includes/RtsAPI.h4
-rw-r--r--rts/Prelude.h2
-rw-r--r--rts/RtsAPI.c29
-rw-r--r--rts/RtsSymbols.c1
-rw-r--r--rts/Schedule.c5
-rw-r--r--rts/package.conf.in2
-rw-r--r--testsuite/tests/rts/T12903.hs10
-rw-r--r--testsuite/tests/rts/T12903.stdout1
-rw-r--r--testsuite/tests/rts/all.T1
9 files changed, 54 insertions, 1 deletions
diff --git a/includes/RtsAPI.h b/includes/RtsAPI.h
index 3b6e1dc117..4dccb84fd2 100644
--- a/includes/RtsAPI.h
+++ b/includes/RtsAPI.h
@@ -282,6 +282,10 @@ void rts_evalIO (/* inout */ Capability **,
/* in */ HaskellObj p,
/* out */ HaskellObj *ret);
+void rts_evalStableIOMain (/* inout */ Capability **,
+ /* in */ HsStablePtr s,
+ /* out */ HsStablePtr *ret);
+
void rts_evalStableIO (/* inout */ Capability **,
/* in */ HsStablePtr s,
/* out */ HsStablePtr *ret);
diff --git a/rts/Prelude.h b/rts/Prelude.h
index 16881eb423..0186b5092b 100644
--- a/rts/Prelude.h
+++ b/rts/Prelude.h
@@ -52,6 +52,7 @@ PRELUDE_CLOSURE(base_GHCziConcziIO_ioManagerCapabilitiesChanged_closure);
PRELUDE_CLOSURE(base_GHCziConcziSignal_runHandlersPtr_closure);
PRELUDE_CLOSURE(base_GHCziTopHandler_flushStdHandles_closure);
+PRELUDE_CLOSURE(base_GHCziTopHandler_runMainIO_closure);
PRELUDE_INFO(ghczmprim_GHCziTypes_Czh_con_info);
PRELUDE_INFO(ghczmprim_GHCziTypes_Izh_con_info);
@@ -84,6 +85,7 @@ PRELUDE_INFO(base_GHCziStable_StablePtr_con_info);
#define runHandlersPtr_closure DLL_IMPORT_DATA_REF(base_GHCziConcziSignal_runHandlersPtr_closure)
#define flushStdHandles_closure DLL_IMPORT_DATA_REF(base_GHCziTopHandler_flushStdHandles_closure)
+#define runMainIO_closure DLL_IMPORT_DATA_REF(base_GHCziTopHandler_runMainIO_closure)
#define stackOverflow_closure DLL_IMPORT_DATA_REF(base_GHCziIOziException_stackOverflow_closure)
#define heapOverflow_closure DLL_IMPORT_DATA_REF(base_GHCziIOziException_heapOverflow_closure)
diff --git a/rts/RtsAPI.c b/rts/RtsAPI.c
index f009de7b64..2ca5dc437f 100644
--- a/rts/RtsAPI.c
+++ b/rts/RtsAPI.c
@@ -461,6 +461,35 @@ void rts_evalIO (/* inout */ Capability **cap,
}
/*
+ * rts_evalStableIOMain() is suitable for calling main Haskell thread
+ * stored in (StablePtr (IO a)) it calls rts_evalStableIO but wraps
+ * function in GHC.TopHandler.runMainIO that installs top_handlers.
+ * See Trac #12903.
+ */
+void rts_evalStableIOMain(/* inout */ Capability **cap,
+ /* in */ HsStablePtr s,
+ /* out */ HsStablePtr *ret)
+{
+ StgTSO* tso;
+ StgClosure *p, *r, *w;
+ SchedulerStatus stat;
+
+ p = (StgClosure *)deRefStablePtr(s);
+ w = rts_apply(*cap, &base_GHCziTopHandler_runMainIO_closure, p);
+ tso = createStrictIOThread(*cap, RtsFlags.GcFlags.initialStkSize, w);
+ // async exceptions are always blocked by default in the created
+ // thread. See #1048.
+ tso->flags |= TSO_BLOCKEX | TSO_INTERRUPTIBLE;
+ scheduleWaitThread(tso,&r,cap);
+ stat = rts_getSchedStatus(*cap);
+
+ if (stat == Success && ret != NULL) {
+ ASSERT(r != NULL);
+ *ret = getStablePtr((StgPtr)r);
+ }
+}
+
+/*
* rts_evalStableIO() is suitable for calling from Haskell. It
* evaluates a value of the form (StablePtr (IO a)), forcing the
* action's result to WHNF before returning. The result is returned
diff --git a/rts/RtsSymbols.c b/rts/RtsSymbols.c
index 60ffedbfc1..e50159642d 100644
--- a/rts/RtsSymbols.c
+++ b/rts/RtsSymbols.c
@@ -666,6 +666,7 @@
SymI_HasProto(rts_eval) \
SymI_HasProto(rts_evalIO) \
SymI_HasProto(rts_evalLazyIO) \
+ SymI_HasProto(rts_evalStableIOMain) \
SymI_HasProto(rts_evalStableIO) \
SymI_HasProto(rts_eval_) \
SymI_HasProto(rts_getBool) \
diff --git a/rts/Schedule.c b/rts/Schedule.c
index 2c862af848..49687b577a 100644
--- a/rts/Schedule.c
+++ b/rts/Schedule.c
@@ -2103,7 +2103,10 @@ forkProcess(HsStablePtr *entry
ioManagerStartCap(&cap);
#endif
- rts_evalStableIO(&cap, entry, NULL); // run the action
+ // Install toplevel exception handlers, so interruption
+ // signal will be sent to the main thread.
+ // See Trac #12903
+ rts_evalStableIOMain(&cap, entry, NULL); // run the action
rts_checkSchedStatus("forkProcess",cap);
rts_unlock(cap);
diff --git a/rts/package.conf.in b/rts/package.conf.in
index 17d579fc7b..1da44a4cd1 100644
--- a/rts/package.conf.in
+++ b/rts/package.conf.in
@@ -104,6 +104,7 @@ ld-options:
, "-Wl,-u,_base_GHCziTopHandler_flushStdHandles_closure"
, "-Wl,-u,_base_GHCziTopHandler_runIO_closure"
, "-Wl,-u,_base_GHCziTopHandler_runNonIO_closure"
+ , "-Wl,-u,_base_GHCziTopHandler_runMainIO_closure"
, "-Wl,-u,_base_GHCziConcziIO_ensureIOManagerIsRunning_closure"
, "-Wl,-u,_base_GHCziConcziIO_ioManagerCapabilitiesChanged_closure"
, "-Wl,-u,_base_GHCziConcziSync_runSparks_closure"
@@ -195,6 +196,7 @@ ld-options:
, "-Wl,-u,base_GHCziTopHandler_flushStdHandles_closure"
, "-Wl,-u,base_GHCziTopHandler_runIO_closure"
, "-Wl,-u,base_GHCziTopHandler_runNonIO_closure"
+ , "-Wl,-u,base_GHCziTopHandler_runMainIO_closure"
, "-Wl,-u,base_GHCziConcziIO_ensureIOManagerIsRunning_closure"
, "-Wl,-u,base_GHCziConcziIO_ioManagerCapabilitiesChanged_closure"
, "-Wl,-u,base_GHCziConcziSync_runSparks_closure"
diff --git a/testsuite/tests/rts/T12903.hs b/testsuite/tests/rts/T12903.hs
new file mode 100644
index 0000000000..ddaf8b97e8
--- /dev/null
+++ b/testsuite/tests/rts/T12903.hs
@@ -0,0 +1,10 @@
+import Control.Concurrent
+import Control.Exception
+import System.Posix
+
+main = do
+ pid <- forkProcess $ do
+ handle (\UserInterrupt{} -> putStrLn "caught")
+ $ threadDelay 2000000
+ signalProcess sigINT pid
+ threadDelay 2000000
diff --git a/testsuite/tests/rts/T12903.stdout b/testsuite/tests/rts/T12903.stdout
new file mode 100644
index 0000000000..cad99e1222
--- /dev/null
+++ b/testsuite/tests/rts/T12903.stdout
@@ -0,0 +1 @@
+caught
diff --git a/testsuite/tests/rts/all.T b/testsuite/tests/rts/all.T
index 9c55b21341..f9c4b8ee6e 100644
--- a/testsuite/tests/rts/all.T
+++ b/testsuite/tests/rts/all.T
@@ -375,4 +375,5 @@ test('numa001', [ extra_run_opts('8'), extra_ways(['debug_numa']) ]
test('T12497', [ unless(opsys('mingw32'), skip)
],
run_command, ['$MAKE -s --no-print-directory T12497'])
+test('T12903', [ when(opsys('mingw32'), skip)], compile_and_run, [''])