12
12
13
13
Dynamic library facilities.
14
14
15
- A simple wrapper over the platforms dynamic library facilities
15
+ A simple wrapper over the platform's dynamic library facilities
16
16
17
17
*/
18
18
use c_str:: ToCStr ;
@@ -80,7 +80,6 @@ impl DynamicLibrary {
80
80
}
81
81
}
82
82
83
-
84
83
#[ cfg( test) ]
85
84
mod test {
86
85
use super :: * ;
@@ -90,8 +89,7 @@ mod test {
90
89
use libc;
91
90
92
91
#[ test]
93
- // #[ignore(cfg(windows))] // FIXME #8818
94
- #[ ignore] // FIXME #9137 this library isn't thread-safe
92
+ #[ ignore( cfg( windows) ) ] // FIXME #8818
95
93
fn test_loading_cosine ( ) {
96
94
// The math library does not need to be loaded since it is already
97
95
// statically linked in
@@ -100,8 +98,6 @@ mod test {
100
98
Ok ( libm) => libm
101
99
} ;
102
100
103
- // Unfortunately due to issue #6194 it is not possible to call
104
- // this as a C function
105
101
let cosine: extern fn ( libc:: c_double ) -> libc:: c_double = unsafe {
106
102
match libm. symbol ( "cos" ) {
107
103
Err ( error) => fail2 ! ( "Could not load function cos: {}" , error) ,
@@ -114,15 +110,14 @@ mod test {
114
110
let result = cosine ( argument) ;
115
111
if result != expected_result {
116
112
fail2 ! ( "cos({:?}) != {:?} but equaled {:?} instead" , argument,
117
- expected_result, result)
113
+ expected_result, result)
118
114
}
119
115
}
120
116
121
117
#[ test]
122
118
#[ cfg( target_os = "linux" ) ]
123
119
#[ cfg( target_os = "macos" ) ]
124
120
#[ cfg( target_os = "freebsd" ) ]
125
- #[ ignore] // FIXME #9137 this library isn't thread-safe
126
121
fn test_errors_do_not_crash ( ) {
127
122
// Open /dev/null as a library to get an error, and make sure
128
123
// that only causes an error, and not a crash.
@@ -164,17 +159,25 @@ pub mod dl {
164
159
#[ fixed_stack_segment] ; #[ inline( never) ] ;
165
160
166
161
unsafe {
162
+ // dlerror isn't thread safe, so we need to lock around this entire
163
+ // sequence. `atomically` asserts that we don't do anything that
164
+ // would cause this task to be descheduled, which could deadlock
165
+ // the scheduler if it happens while the lock is held.
166
+ // FIXME #9105 use a Rust mutex instead of C++ mutexes.
167
167
do atomically {
168
+ rust_take_dlerror_lock( ) ;
168
169
let _old_error = dlerror ( ) ;
169
170
170
171
let result = f ( ) ;
171
172
172
173
let last_error = dlerror ( ) ;
173
- if ptr:: null ( ) == last_error {
174
+ let ret = if ptr:: null ( ) == last_error {
174
175
Ok ( result)
175
176
} else {
176
177
Err ( str:: raw:: from_c_str ( last_error) )
177
- }
178
+ } ;
179
+ rust_drop_dlerror_lock ( ) ;
180
+ ret
178
181
}
179
182
}
180
183
}
@@ -197,6 +200,11 @@ pub mod dl {
197
200
Local = 0 ,
198
201
}
199
202
203
+ extern {
204
+ fn rust_take_dlerror_lock ( ) ;
205
+ fn rust_drop_dlerror_lock ( ) ;
206
+ }
207
+
200
208
#[ link_name = "dl" ]
201
209
extern {
202
210
fn dlopen ( filename : * libc:: c_char , flag : libc:: c_int ) -> * libc:: c_void ;
@@ -246,6 +254,7 @@ pub mod dl {
246
254
}
247
255
}
248
256
}
257
+
249
258
pub unsafe fn symbol ( handle : * libc:: c_void , symbol : * libc:: c_char ) -> * libc:: c_void {
250
259
#[ fixed_stack_segment] ; #[ inline( never) ] ;
251
260
GetProcAddress ( handle, symbol)
0 commit comments