Skip to content
Snippets Groups Projects
Commit fd65f338 authored by Gav's avatar Gav
Browse files

Avoid using reentrancy issues.

parent b48003b6
Branches
No related merge requests found
......@@ -22,9 +22,21 @@ pub fn using_environment<'a, T: 'a, R, S, F: FnOnce() -> R>(
protected: &'a mut T,
f: F
) -> R {
global.with(|r| *r.borrow_mut() = protected as *mut T as *mut S);
// store the `protected` reference as a pointer so we can provide it to logic running within
// `f`.
// while re record this pointer (while it's non-zero) we guarantee:
// - it will only be used once at any time (no reentrancy);
// - that no other thread will use it; and
// - that we do not use the original mutating reference while the pointer.
// exists.
let original = global.with(|r| {
let mut b = r.borrow_mut();
let o = *b;
*b = protected as *mut T as *mut S;
o
});
let r = f();
global.with(|r| *r.borrow_mut() = 0 as *mut S);
global.with(|r| *r.borrow_mut() = original);
r
}
......@@ -35,8 +47,8 @@ pub fn with_environment<'r, R, S, T: 'r, F: FnOnce(&'r mut T) -> R>(
global.with(|r| {
let br = r.borrow_mut();
if *br != 0 as *mut S {
// safe because it's only non-zero when it in with_environment, which
// is holding on to the underlying reference safely
// safe because it's only non-zero when it's being called from using_environment, which
// is holding on to the underlying reference (and not using it itself) safely.
unsafe {
Some(mutator(&mut *(*br as *mut S as *mut T)))
}
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment