1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
#2020/01/30 Patch has not yet been accepted upstream
From 87b1eca2b719fb5e2d6f10352dcdb86f4d389ca9 Mon Sep 17 00:00:00 2001
From: Eric Timmons <etimmons@mit.edu>
Date: Sat, 1 Feb 2020 17:33:59 -0500
Subject: [PATCH 3/5] Teach foreign.test.sh about noop dlclose implementations
Musl libc's implementation of dlclose(3) is (intentionally) a noop (see:
https://wiki.musl-libc.org/functional-differences-from-glibc.html). When
running regression tests, test if dlclose is a noop and if so, skip all tests
that depend on objects being unmapped.
---
src/code/foreign-load.lisp | 2 +-
tests/foreign.test.sh | 67 ++++++++++++++++++++++++++++----------
2 files changed, 51 insertions(+), 18 deletions(-)
diff --git a/src/code/foreign-load.lisp b/src/code/foreign-load.lisp
index ada107c36..4510f2ccf 100644
--- a/src/code/foreign-load.lisp
+++ b/src/code/foreign-load.lisp
@@ -48,7 +48,7 @@ (defun load-shared-object (pathname &key dont-save)
definitions; if a symbol was previously referenced through the object and
is not present in the reloaded version an error will be signalled. Reloading
may not work as expected if user or library-code has called dlopen(3) on the
-same shared object.
+same shared object or running on a system where dlclose(3) is a noop.
LOAD-SHARED-OBJECT interacts with SB-EXT:SAVE-LISP-AND-DIE:
diff --git a/tests/foreign.test.sh b/tests/foreign.test.sh
index fabba1246..53131bdd2 100755
--- a/tests/foreign.test.sh
+++ b/tests/foreign.test.sh
@@ -140,6 +140,28 @@ echo 'int late_foo = 43;' > $TEST_FILESTEM-c.c
echo 'int late_bar() { return 14; }' >> $TEST_FILESTEM-c.c
build_so $TEST_FILESTEM-c
+cat > $TEST_FILESTEM-noop-dlclose-test.c <<EOF
+#include <dlfcn.h>
+#include <stddef.h>
+
+int dlclose_is_noop () {
+ void * handle = dlopen("./$TEST_FILESTEM-noop-dlclose-test-helper.so", RTLD_NOW | RTLD_GLOBAL);
+ dlclose(handle);
+
+ handle = dlopen("./$TEST_FILESTEM-noop-dlclose-test-helper.so", RTLD_NOW | RTLD_NOLOAD);
+ if (handle != NULL) {
+ return 1;
+ }
+ return 0;
+}
+EOF
+build_so $TEST_FILESTEM-noop-dlclose-test
+
+cat > $TEST_FILESTEM-noop-dlclose-test-helper.c <<EOF
+int sbcl_dlclose_test = 42;
+EOF
+build_so $TEST_FILESTEM-noop-dlclose-test-helper
+
## Foreign definitions & load
cat > $TEST_FILESTEM.base.lisp <<EOF
@@ -246,20 +268,28 @@ cat > $TEST_FILESTEM.test.lisp <<EOF
(note "/initial assertions ok")
+ ;; determine if dlclose is a noop.
+ (load-shared-object (truename "$TEST_FILESTEM-noop-dlclose-test.so"))
+ (define-alien-routine dlclose-is-noop int)
+ (defparameter *dlclose-noop-p* (plusp (dlclose-is-noop)))
+
;; test reloading object file with new definitions
(assert (= 13 foo))
(assert (= 42 (bar)))
(note "/original definitions ok")
- (rename-file "$TEST_FILESTEM-b.so" "$TEST_FILESTEM-b.bak")
- (rename-file "$TEST_FILESTEM-b2.so" "$TEST_FILESTEM-b.so")
- (load-shared-object (truename "$TEST_FILESTEM-b.so"))
- (note "/reloading ok")
- (assert (= 42 foo))
- (assert (= 13 (bar)))
- (note "/redefined versions ok")
- (rename-file "$TEST_FILESTEM-b.so" "$TEST_FILESTEM-b2.so")
- (rename-file "$TEST_FILESTEM-b.bak" "$TEST_FILESTEM-b.so")
- (note "/renamed back to originals")
+ (if *dlclose-noop-p*
+ (note "/skipping reloading tests")
+ (progn
+ (rename-file "$TEST_FILESTEM-b.so" "$TEST_FILESTEM-b.bak")
+ (rename-file "$TEST_FILESTEM-b2.so" "$TEST_FILESTEM-b.so")
+ (load-shared-object (truename "$TEST_FILESTEM-b.so"))
+ (note "/reloading ok")
+ (assert (= 42 foo))
+ (assert (= 13 (bar)))
+ (note "/redefined versions ok")
+ (rename-file "$TEST_FILESTEM-b.so" "$TEST_FILESTEM-b2.so")
+ (rename-file "$TEST_FILESTEM-b.bak" "$TEST_FILESTEM-b.so")
+ (note "/renamed back to originals")))
;; test late resolution
#+linkage-table
@@ -276,13 +306,16 @@ cat > $TEST_FILESTEM.test.lisp <<EOF
(load-shared-object (truename "$TEST_FILESTEM-c.so"))
(assert (= 43 late-foo))
(assert (= 14 (late-bar)))
- (unload-shared-object (truename "$TEST_FILESTEM-c.so"))
- (multiple-value-bind (val err) (ignore-errors late-foo)
- (assert (not val))
- (assert (typep err 'undefined-alien-error)))
- (multiple-value-bind (val err) (ignore-errors (late-bar))
- (assert (not val))
- (assert (typep err 'undefined-alien-error)))
+ (if *dlclose-noop-p*
+ (note "/skipping linkage table unloading tests")
+ (progn
+ (unload-shared-object (truename "$TEST_FILESTEM-c.so"))
+ (multiple-value-bind (val err) (ignore-errors late-foo)
+ (assert (not val))
+ (assert (typep err 'undefined-alien-error)))
+ (multiple-value-bind (val err) (ignore-errors (late-bar))
+ (assert (not val))
+ (assert (typep err 'undefined-alien-error)))))
(note "/linkage table ok"))
(sb-ext:exit :code $EXIT_LISP_WIN) ; success convention for Lisp program
--
2.25.0
|