[commit: ghc] master: Keep the list of DLLs that we dlopen (be497c2)

Ian Lynagh <[email protected]>
Newsgroups gmane.comp.lang.haskell.cvs.ghc
Message-ID <[email protected]>
Repository : ssh://darcs.haskell.org//srv/darcs/ghc

On branch  : master

http://hackage.haskell.org/trac/ghc/changeset/be497c202b790999c3fd0ddc4a4176b8cf6acf7e

>---------------------------------------------------------------

commit be497c202b790999c3fd0ddc4a4176b8cf6acf7e
Author: Ian Lynagh <[email protected]>
Date:   Sat Oct 13 16:18:41 2012 +0100

    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.

>---------------------------------------------------------------

 rts/Linker.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/rts/Linker.c b/rts/Linker.c
index 4ae9193..2d7e7d7 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);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.