diff options
| author | Ian Lynagh <ian@well-typed.com> | 2012-10-13 16:18:41 +0100 |
|---|---|---|
| committer | Ian Lynagh <ian@well-typed.com> | 2012-10-13 16:18:41 +0100 |
| commit | be497c202b790999c3fd0ddc4a4176b8cf6acf7e (patch) | |
| tree | 8e3185027c6ee8e6ffa06120bbd6aba37094afa0 | |
| parent | 76410f7face73050551b28f92e45e523f4dabdae (diff) | |
| download | haskell-be497c202b790999c3fd0ddc4a4176b8cf6acf7e.tar.gz | |
Keep the list of DLLs that we dlopen
Unfortunately, dlsym finds the first symbol loaded, while when we reload
a compiled module in GHCi it's the last symbol that we want. Therefore
we remember the list of loaded DLLs ourselves and go through them in
order.
| -rw-r--r-- | rts/Linker.c | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/rts/Linker.c b/rts/Linker.c index 4ae9193a11..2d7e7d78a7 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -1588,9 +1588,32 @@ static OpenedDLL* opened_dlls = NULL; # if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO) +/* Suppose in ghci we load a temporary SO for a module containing + f = 1 + and then modify the module, recompile, and load another temporary + SO with + f = 2 + Then as we don't unload the first SO, dlsym will find the + f = 1 + symbol whereas we want the + f = 2 + symbol. We therefore need to keep our own SO handle list, and + try SOs in the right order. */ + +typedef + struct _OpenedSO { + struct _OpenedSO* next; + void *handle; + } + OpenedSO; + +/* A list thereof. */ +static OpenedSO* openedSOs = NULL; + static const char * internal_dlopen(const char *dll_name) { + OpenedSO* o_so; void *hdl; const char *errmsg; char *errmsg_copy; @@ -1618,11 +1641,36 @@ internal_dlopen(const char *dll_name) strcpy(errmsg_copy, errmsg); errmsg = errmsg_copy; } + o_so = stgMallocBytes(sizeof(OpenedSO), "addDLL"); + o_so->handle = hdl; + o_so->next = openedSOs; + openedSOs = o_so; + RELEASE_LOCK(&dl_mutex); //--------------- End critical section ------------------- return errmsg; } + +static void * +internal_dlsym(void *hdl, const char *symbol) { + OpenedSO* o_so; + void *v; + + // We acquire dl_mutex as concurrent dl* calls may alter dlerror + ACQUIRE_LOCK(&dl_mutex); + dlerror(); + for (o_so = openedSOs; o_so != NULL; o_so = o_so->next) { + v = dlsym(o_so->handle, symbol); + if (dlerror() == NULL) { + RELEASE_LOCK(&dl_mutex); + return v; + } + } + v = dlsym(hdl, symbol) + RELEASE_LOCK(&dl_mutex); + return v; +} # endif const char * @@ -1798,7 +1846,7 @@ lookupSymbol( char *lbl ) if (val == NULL) { IF_DEBUG(linker, debugBelch("lookupSymbol: symbol not found\n")); # if defined(OBJFORMAT_ELF) - return dlsym(dl_prog_handle, lbl); + return internal_dlsym(dl_prog_handle, lbl); # elif defined(OBJFORMAT_MACHO) # if HAVE_DLFCN_H /* On OS X 10.3 and later, we use dlsym instead of the old legacy @@ -1812,7 +1860,7 @@ lookupSymbol( char *lbl ) */ IF_DEBUG(linker, debugBelch("lookupSymbol: looking up %s with dlsym\n", lbl)); ASSERT(lbl[0] == '_'); - return dlsym(dl_prog_handle, lbl + 1); + return internal_dlsym(dl_prog_handle, lbl + 1); # else if (NSIsSymbolNameDefined(lbl)) { NSSymbol symbol = NSLookupAndBindSymbol(lbl); |
