Skip to content

Commit 800dbff

Browse files
committed
auto merge of #8219 : sstewartgallus/rust/fix_dynamic_lib, r=graydon
A test case was also created for this situation to prevent the problem occuring again. A similar problem was also fixed for the symbol method. There was some minor code cleanup. I am unsatisfied with using /dev/null as an invalid dynamic library. It is not cross platform.
2 parents 34101d2 + 2047026 commit 800dbff

File tree

1 file changed

+70
-36
lines changed

1 file changed

+70
-36
lines changed

src/libstd/unstable/dynamic_lib.rs

+70-36
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ impl Drop for DynamicLibrary {
3131
dl::close(self.handle)
3232
}
3333
} {
34-
Ok(()) => { },
34+
Ok(()) => {},
3535
Err(str) => fail!(str)
3636
}
3737
}
@@ -41,14 +41,20 @@ impl DynamicLibrary {
4141
/// Lazily open a dynamic library. When passed None it gives a
4242
/// handle to the calling process
4343
pub fn open(filename: Option<&path::Path>) -> Result<DynamicLibrary, ~str> {
44-
do dl::check_for_errors_in {
45-
unsafe {
46-
DynamicLibrary { handle:
47-
match filename {
48-
Some(name) => dl::open_external(name),
49-
None => dl::open_internal()
50-
}
44+
unsafe {
45+
let maybe_library = do dl::check_for_errors_in {
46+
match filename {
47+
Some(name) => dl::open_external(name),
48+
None => dl::open_internal()
5149
}
50+
};
51+
52+
// The dynamic library must not be constructed if there is
53+
// an error opening the library so the destructor does not
54+
// run.
55+
match maybe_library {
56+
Err(err) => Err(err),
57+
Ok(handle) => Ok(DynamicLibrary { handle: handle })
5258
}
5359
}
5460
}
@@ -58,41 +64,69 @@ impl DynamicLibrary {
5864
// This function should have a lifetime constraint of 'self on
5965
// T but that feature is still unimplemented
6066

61-
do dl::check_for_errors_in {
62-
let symbol_value = do symbol.as_c_str |raw_string| {
67+
let maybe_symbol_value = do dl::check_for_errors_in {
68+
do symbol.as_c_str |raw_string| {
6369
dl::symbol(self.handle, raw_string)
64-
};
70+
}
71+
};
6572

66-
cast::transmute(symbol_value)
73+
// The value must not be constructed if there is an error so
74+
// the destructor does not run.
75+
match maybe_symbol_value {
76+
Err(err) => Err(err),
77+
Ok(symbol_value) => Ok(cast::transmute(symbol_value))
6778
}
6879
}
6980
}
7081

71-
#[test]
72-
#[ignore(cfg(windows))]
73-
priv fn test_loading_cosine () {
74-
// The math library does not need to be loaded since it is already
75-
// statically linked in
76-
let libm = match DynamicLibrary::open(None) {
77-
Err (error) => fail!("Could not load self as module: %s", error),
78-
Ok (libm) => libm
79-
};
80-
81-
// Unfortunately due to issue #6194 it is not possible to call
82-
// this as a C function
83-
let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
84-
match libm.symbol("cos") {
85-
Err (error) => fail!("Could not load function cos: %s", error),
86-
Ok (cosine) => cosine
82+
83+
#[cfg(test)]
84+
mod test {
85+
use super::*;
86+
use option::*;
87+
use result::*;
88+
use path::*;
89+
use libc;
90+
91+
#[test]
92+
fn test_loading_cosine() {
93+
// The math library does not need to be loaded since it is already
94+
// statically linked in
95+
let libm = match DynamicLibrary::open(None) {
96+
Err(error) => fail!("Could not load self as module: %s", error),
97+
Ok(libm) => libm
98+
};
99+
100+
// Unfortunately due to issue #6194 it is not possible to call
101+
// this as a C function
102+
let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
103+
match libm.symbol("cos") {
104+
Err(error) => fail!("Could not load function cos: %s", error),
105+
Ok(cosine) => cosine
106+
}
107+
};
108+
109+
let argument = 0.0;
110+
let expected_result = 1.0;
111+
let result = cosine(argument);
112+
if result != expected_result {
113+
fail!("cos(%?) != %? but equaled %? instead", argument,
114+
expected_result, result)
115+
}
116+
}
117+
118+
#[test]
119+
#[cfg(target_os = "linux")]
120+
#[cfg(target_os = "macos")]
121+
#[cfg(target_os = "freebsd")]
122+
fn test_errors_do_not_crash() {
123+
// Open /dev/null as a library to get an error, and make sure
124+
// that only causes an error, and not a crash.
125+
let path = GenericPath::from_str("/dev/null");
126+
match DynamicLibrary::open(Some(&path)) {
127+
Err(_) => {}
128+
Ok(_) => fail!("Successfully opened the empty library.")
87129
}
88-
};
89-
90-
let argument = 0.0;
91-
let expected_result = 1.0;
92-
let result = cosine(argument);
93-
if result != expected_result {
94-
fail!("cos(%?) != %? but equaled %? instead", argument,
95-
expected_result, result)
96130
}
97131
}
98132

0 commit comments

Comments
 (0)