Commit 3501ac6a authored by Simon Marlow's avatar Simon Marlow

Fix #1185 (RTS part, also needs corresponding change to libraries/base)

GHC.Conc.ensureIOManagerIsRunning now creates an IO manager thread if
one does not exist or has died/exited.

Unfortunately this exposed a problem caused by the fact that we have
two base packages, and hence two IO managers, in GHCi: see NOTE
[io-manager-ghci] in rts/Linker.c.  The workaround can go away if/when
we switch to a dynamically linked GHCi.
parent 7068f60c
......@@ -957,6 +957,37 @@ typedef struct _RtsSymbolVal {
#define RTS_LIBGCC_SYMBOLS
#endif
/* NOTE [io-manager-ghci]
When GHCi loads the base package, it gets another copy of the CAFs
in GHC.Conc that record the IO manager's ThreadId, and the blocking
queues, so we get another IO manager. This is bad enough, but what
is worse is that GHCi by default reverts all CAFs on every :load,
so we'll get *another* IO manager thread (and an associated pipe)
every time the user does :load. Miraculously, this actually
manages to just about work in GHC 6.10 and earlier, but broke when
I tried to fix #1185 (restarting the IO manager after a fork()).
To work around it and ensure that we only have a single IO manager,
we map the CAFs in the dynamically-loaded GHC.Conc to the
statically-linked GHC.Conc. This is an ugly hack, but it's the
least ugly hack that I could think of (SDM 3/11/2009)
*/
#define RTS_GHC_CONC_SYMBOLS \
SymI_NeedsProto(base_GHCziConc_pendingDelays_closure) \
SymI_NeedsProto(base_GHCziConc_pendingEvents_closure) \
SymI_NeedsProto(base_GHCziConc_ioManagerThread_closure)
#ifdef mingw32_HOST_OS
#define RTS_GHC_CONC_OS_SYMBOLS /* empty */
#else
#define RTS_GHC_CONC_OS_SYMBOLS \
SymI_NeedsProto(base_GHCziConc_prodding_closure) \
SymI_NeedsProto(base_GHCziConc_sync_closure) \
SymI_NeedsProto(base_GHCziConc_stick_closure)
#endif
#if defined(darwin_HOST_OS) && defined(powerpc_HOST_ARCH)
// Symbols that don't have a leading underscore
// on Mac OS X. They have to receive special treatment,
......@@ -985,6 +1016,8 @@ RTS_CYGWIN_ONLY_SYMBOLS
RTS_DARWIN_ONLY_SYMBOLS
RTS_LIBGCC_SYMBOLS
RTS_LIBFFI_SYMBOLS
RTS_GHC_CONC_SYMBOLS
RTS_GHC_CONC_OS_SYMBOLS
#undef SymI_NeedsProto
#undef SymI_HasProto
#undef SymI_HasProto_redirect
......@@ -1020,6 +1053,8 @@ static RtsSymbolVal rtsSyms[] = {
RTS_DARWIN_ONLY_SYMBOLS
RTS_LIBGCC_SYMBOLS
RTS_LIBFFI_SYMBOLS
RTS_GHC_CONC_SYMBOLS
RTS_GHC_CONC_OS_SYMBOLS
#if defined(darwin_HOST_OS) && defined(i386_HOST_ARCH)
// dyld stub code contains references to this,
// but it should never be called because we treat
......@@ -1041,12 +1076,18 @@ static void ghciInsertStrHashTable ( char* obj_name,
void *data
)
{
if (lookupHashTable(table, (StgWord)key) == NULL)
{
#define GHC_CONC "base_GHCziConc"
if (lookupHashTable(table, (StgWord)key) == NULL)
{
insertStrHashTable(table, (StgWord)key, data);
return;
}
debugBelch(
}
if (strncmp(key, GHC_CONC, strlen(GHC_CONC)) == 0) {
/* see NOTE [io-manager-ghci] */
return;
}
debugBelch(
"\n\n"
"GHCi runtime linker: fatal error: I found a duplicate definition for symbol\n"
" %s\n"
......@@ -1061,8 +1102,8 @@ static void ghciInsertStrHashTable ( char* obj_name,
"\n",
(char*)key,
obj_name
);
exit(1);
);
exit(1);
}
/* -----------------------------------------------------------------------------
* initialize the object linker
......
......@@ -1683,6 +1683,10 @@ forkProcess(HsStablePtr *entry
initTimer();
startTimer();
#if defined(THREADED_RTS)
cap = ioManagerStartCap(cap);
#endif
cap = rts_evalStableIO(cap, entry, NULL); // run the action
rts_checkSchedStatus("forkProcess",cap);
......
......@@ -99,6 +99,14 @@ ld-options:
, "-u", "_base_GHCziConc_ensureIOManagerIsRunning_closure"
, "-u", "_base_GHCziConc_runSparks_closure"
, "-u", "_base_GHCziConc_runHandlers_closure"
, "-u", "_base_GHCziConc_pendingDelays_closure"
, "-u", "_base_GHCziConc_pendingEvents_closure"
, "-u", "_base_GHCziConc_ioManagerThread_closure"
#if !defined(mingw32_HOST_OS)
, "-u", "_base_GHCziConc_prodding_closure"
, "-u", "_base_GHCziConc_sync_closure"
, "-u", "_base_GHCziConc_stick_closure"
#endif
#else
"-u", "ghczmprim_GHCziTypes_Izh_static_info"
, "-u", "ghczmprim_GHCziTypes_Czh_static_info"
......@@ -137,6 +145,14 @@ ld-options:
, "-u", "base_GHCziConc_ensureIOManagerIsRunning_closure"
, "-u", "base_GHCziConc_runSparks_closure"
, "-u", "base_GHCziConc_runHandlers_closure"
, "-u", "base_GHCziConc_pendingDelays_closure"
, "-u", "base_GHCziConc_pendingEvents_closure"
, "-u", "base_GHCziConc_ioManagerThread_closure"
#if !defined(mingw32_HOST_OS)
, "-u", "base_GHCziConc_prodding_closure"
, "-u", "base_GHCziConc_sync_closure"
, "-u", "base_GHCziConc_stick_closure"
#endif
#endif
/* Pick up static libraries in preference over dynamic if in earlier search
......
......@@ -124,6 +124,12 @@ ioManagerDie (void)
}
}
Capability *
ioManagerStartCap (Capability *cap)
{
return rts_evalIO(cap,&base_GHCziConc_ensureIOManagerIsRunning_closure,NULL);
}
void
ioManagerStart (void)
{
......@@ -131,7 +137,7 @@ ioManagerStart (void)
Capability *cap;
if (io_manager_pipe < 0) {
cap = rts_lock();
cap = rts_evalIO(cap,&base_GHCziConc_ensureIOManagerIsRunning_closure,NULL);
cap = ioManagerStartCap(cap);
rts_unlock(cap);
}
}
......
......@@ -24,6 +24,8 @@ extern siginfo_t *next_pending_handler;
void startSignalHandlers(Capability *cap);
#endif
Capability *ioManagerStartCap (Capability *cap);
extern StgInt *signal_handlers;
END_RTS_PRIVATE
......
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