summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marlow <smarlow@fb.com>2018-07-12 04:45:35 -0700
committerRay Shih <rayshih@fb.com>2020-07-14 07:52:53 -0700
commitb51e4b4304d5cb6cd77642c534146213382ec0ef (patch)
tree5d349295ab59a444750adac0bd64074c66ae1457
parentca0e0edcc5cc5395aa1314a225aea107cc9bde15 (diff)
downloadhaskell-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.c20
-rw-r--r--testsuite/tests/rts/linker_unload_native.c13
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);