diff options
author | Simon Marlow <smarlow@fb.com> | 2018-07-12 04:45:35 -0700 |
---|---|---|
committer | Ray Shih <rayshih@fb.com> | 2020-07-14 07:52:53 -0700 |
commit | b51e4b4304d5cb6cd77642c534146213382ec0ef (patch) | |
tree | 5d349295ab59a444750adac0bd64074c66ae1457 | |
parent | ca0e0edcc5cc5395aa1314a225aea107cc9bde15 (diff) | |
download | haskell-b51e4b4304d5cb6cd77642c534146213382ec0ef.tar.gz |
loadNativeObj: fail if we attempt to load an object that is already loaded
Summary:
Test Plan:
Reviewers:
Subscribers:
Tasks:
Tags:
(cherry picked from commit 74d8cadeef8a509f1ee612795f5af6142edb006c)
-rw-r--r-- | rts/Linker.c | 20 | ||||
-rw-r--r-- | testsuite/tests/rts/linker_unload_native.c | 13 |
2 files changed, 32 insertions, 1 deletions
diff --git a/rts/Linker.c b/rts/Linker.c index 33af36c356..62959b6707 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -1926,6 +1926,26 @@ static void * loadNativeObj_ELF (pathchar *path, char **errmsg) IF_DEBUG(linker, debugBelch("loadNativeObj_ELF %" PATH_FMT "\n", path)); + // Loading the same object multiple times will lead to chaos + // because we will have two NativeCodes but one underlying handle, + // so let's fail if this happens. + for (nc = native_objects; nc; nc = nc->next) { + if (!pathcmp(nc->fileName,path)) { + copyErrmsg(errmsg, "native object already loaded"); + return NULL; + } + } + + // We also cannot load the same object if we are in the process of + // unloading it. We cannot resurrect it because we've already + // released the StablePtrs. + for (nc = unloaded_native_objects; nc; nc = nc->next) { + if (!pathcmp(nc->fileName,path)) { + copyErrmsg(errmsg, "unload in progress"); + return NULL; + } + } + retval = NULL; ACQUIRE_LOCK(&dl_mutex); diff --git a/testsuite/tests/rts/linker_unload_native.c b/testsuite/tests/rts/linker_unload_native.c index 14e7e2c44a..65e8a42259 100644 --- a/testsuite/tests/rts/linker_unload_native.c +++ b/testsuite/tests/rts/linker_unload_native.c @@ -41,7 +41,6 @@ int main (int argc, char *argv[]) for (i=0; i < ITERATIONS; i++) { char* errmsg; - // load 2 libraries at once void* handle = loadNativeObj(OBJPATH, &errmsg); if (!handle) { errorBelch("loadNativeObj(%s) failed: %s", OBJPATH, errmsg); @@ -49,6 +48,18 @@ int main (int argc, char *argv[]) exit(1); } + // loading the same library again should fail + void* handle1 = loadNativeObj(OBJPATH, &errmsg); + if (!handle1) { + // don't spam the output file: + // errorBelch("loadNativeObj(%s) failed: %s", OBJPATH, errmsg); + free(errmsg); + } else { + errorBelch("loadNativeObj(%s) should have failed", OBJPATH); + exit(1); + } + + // load 2 libraries at once void* handle2 = loadNativeObj(OBJPATH2, &errmsg); if (!handle2) { errorBelch("loadNativeObj(%s) failed: %s", OBJPATH2, errmsg); |