From 3501ac6af749ada0afcaf84f112ab2e4bf9120b9 Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Tue, 3 Nov 2009 16:05:47 +0000 Subject: [PATCH] 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. --- rts/Linker.c | 53 +++++++++++++++++++++++++++++++++++++++++++++------ rts/Schedule.c | 4 ++++ rts/package.conf.in | 16 ++++++++++++++++ rts/posix/Signals.c | 8 +++++++- rts/posix/Signals.h | 2 ++ 5 files changed, 76 insertions(+), 7 deletions(-) diff --git a/rts/Linker.c b/rts/Linker.c index a2b69f9..1d955a3 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -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 diff --git a/rts/Schedule.c b/rts/Schedule.c index 539e006..998d846 100644 --- a/rts/Schedule.c +++ b/rts/Schedule.c @@ -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); diff --git a/rts/package.conf.in b/rts/package.conf.in index 087a7e9..131f1e3 100644 --- a/rts/package.conf.in +++ b/rts/package.conf.in @@ -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 diff --git a/rts/posix/Signals.c b/rts/posix/Signals.c index 6600657..aa78774 100644 --- a/rts/posix/Signals.c +++ b/rts/posix/Signals.c @@ -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); } } diff --git a/rts/posix/Signals.h b/rts/posix/Signals.h index 4d0a5a5..b80f711 100644 --- a/rts/posix/Signals.h +++ b/rts/posix/Signals.h @@ -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 -- 1.7.10.4