-
Notifications
You must be signed in to change notification settings - Fork 90
/
error_handler.rs
79 lines (63 loc) · 2.13 KB
/
error_handler.rs
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
use std::{
ffi::CString,
sync::{Arc, Mutex},
};
use gdal::{config, errors::CplErrType};
use gdal_sys::{CPLErr, CPLError};
#[test]
fn test_error_handler() {
// We cannot test different error handler scenarios in parallel since we modify a global error handler in GDAL.
// Therefore, we test the error handler behavior sequentially to avoid data races.
use_error_handler();
error_handler_interleaved();
}
fn use_error_handler() {
let errors: Arc<Mutex<Vec<(CplErrType, i32, String)>>> = Arc::new(Mutex::new(vec![]));
let errors_clone = errors.clone();
config::set_error_handler(move |a, b, c| {
errors_clone.lock().unwrap().push((a, b, c.to_string()));
});
unsafe {
let msg = CString::new("foo".as_bytes()).unwrap();
CPLError(CPLErr::CE_Failure, 42, msg.as_ptr());
};
unsafe {
let msg = CString::new("bar".as_bytes()).unwrap();
CPLError(std::mem::transmute(CplErrType::Warning), 1, msg.as_ptr());
};
config::remove_error_handler();
let result: Vec<(CplErrType, i32, String)> = errors.lock().unwrap().clone();
assert_eq!(
result,
vec![
(CplErrType::Failure, 42, "foo".to_string()),
(CplErrType::Warning, 1, "bar".to_string())
]
);
}
fn error_handler_interleaved() {
use std::thread;
// Two racing threads trying to set error handlers
// First one
thread::spawn(move || loop {
config::set_error_handler(move |_a, _b, _c| {});
});
// Second one
thread::spawn(move || loop {
config::set_error_handler(move |_a, _b, _c| {});
});
// A thread that provokes potential race conditions
let join_handle = thread::spawn(move || {
for _ in 0..100 {
unsafe {
let msg = CString::new("foo".as_bytes()).unwrap();
CPLError(CPLErr::CE_Failure, 42, msg.as_ptr());
};
unsafe {
let msg = CString::new("bar".as_bytes()).unwrap();
CPLError(std::mem::transmute(CplErrType::Warning), 1, msg.as_ptr());
};
}
});
join_handle.join().unwrap();
}