Comments (7)
I was a little bit scared that exposing it would have a side effect when reviewing #38 .
I then decided it wasn't critical since usages like Channel
require the RawMutex
to be Sync
in order for the created construct to be thread-safe:
impl<MutexType: RawMutex + Sync, T: Send, A> Sync for GenericChannel<MutexType, T, A>
where
So as long as you use NoopLock
only with futures-intrusive it would be safe.
Passing a NoopLock
to another library requiring a RawMutex
might be an issue. But technically those should also require Sync
on the RawMutex
in order to to be able to use it for multi-threaded locking.
from futures-intrusive.
But you can also lock a mutex twice on the same thread and gain two simultaneous &mut
references.
from futures-intrusive.
Sample:
type BadLock<T> = lock_api::Mutex<futures_intrusive::NoopLock, T>;
fn main() {
let lock = BadLock::new(Some(String::from("hello world")));
let g1 = lock.lock();
let mut g2 = lock.lock();
let string = g1.as_ref().unwrap();
g2.take().unwrap();
eprintln!("boom: {}", string.to_string());
}
from futures-intrusive.
(I actually think this is "exploitable" without #38 too, since you can use generics to unify a LocalMutex<T>
with a GenericMutex<LockType, T>
and then create your own lock_api::Mutex<LockType, T>
, but that's a lot more contrived..)
from futures-intrusive.
I thought about this a bit more before pushing 0.4.
It seems like there doesn't exist any thread-safety issues, since lock-api
still requires RawMutex
to be Sync
for that. See https://docs.rs/lock_api/0.4.2/src/lock_api/mutex.rs.html#140-141
With that in mind the borrow-checking problem persists. That could be fixed by converting NoopLock
into a RefCell
like implementation. A potential compromise could be to do that only in debug mode, and avoid the extra storage space in release mode. I would be open for a CR for that.
from futures-intrusive.
I thought about this issue again. NoopLock is also technically unsound even when used with futures-intrusive data structures like LocalMutex, because reentrancy is possible if a nonstandard Waker
implementation is in use. This seems incredibly unlikely to happen in practice, but one could imagine e.g. a Waker
with some instrumentation attached to it.
Here's a contrived example:
use std::cell::Cell;
use std::future::Future;
use std::ptr;
use std::rc::Rc;
use std::task::{Context, RawWaker, RawWakerVTable, Waker};
use futures::pin_mut;
use futures_intrusive::sync::LocalMutex as Mutex;
thread_local! {
static MUTEX: Cell<Option<Rc<Mutex<()>>>> = Cell::new(None);
}
const VTABLE: RawWakerVTable = RawWakerVTable::new(
|_| {
MUTEX.with(|m| {
if let Some(m) = m.take() {
m.try_lock();
}
});
RawWaker::new(ptr::null(), &VTABLE)
},
|_| (),
|_| (),
|_| (),
);
fn main() {
let waker = RawWaker::new(ptr::null(), &VTABLE);
let waker = unsafe { Waker::from_raw(waker) }; // safety: VTABLE meets the RawWaker invariants
let mutex = Rc::new(Mutex::new((), true));
let _lock = mutex.try_lock().unwrap();
MUTEX.with(|m| {
m.set(Some(mutex.clone()));
});
let f = mutex.lock();
pin_mut!(f);
let mut cx = Context::from_waker(&waker);
assert!(f.as_mut().poll(&mut cx).is_pending());
}
This causes the MutexState to be locked twice simultaneously (you can tell because if you import the normal futures_intrusive::sync::Mutex
instead, it deadlocks).
from futures-intrusive.
Since I had to push a new major revision anyway due to the parking lot version stuff I now simply made NoopLock back private.
For the last example: This deadlocks happens because it tries to lock the synchronous parking lot Mutex 2 times in the same thread. With the singlethreaded variant (NoopLock) this doesn't happen, and the try_lock
will fail. The async Mutex is only allocated a single time and works as it should. Of course we discuss about the mutable reference things, but that seems the same discussion as #56.
from futures-intrusive.
Related Issues (20)
- Channels with growing capacity HOT 2
- GenericWaitForEventFuture doesn't handle task migration. HOT 3
- GenericSemaphoreAcquireFuture isn't Sync HOT 7
- `Semaphore` cost O(waiters) time to wake up on, and quadratic in total HOT 2
- Channel::close should return previous state
- Unwind safety HOT 4
- shared::OneshotReceiver and cancellation HOT 2
- GenericOneshotBroadcastReceiver incorrectly requires MutexType to be Clone HOT 4
- LocalChannel backed by non-ArrayBuf RingBuf HOT 2
- Update `parking_lot` and `lock_api` HOT 1
- Pulling out intrusive data structures into another crate HOT 2
- GenericMutexGuard should be marked !Sync HOT 3
- Cut New Release With Updated Dependencies HOT 1
- Does this crate alias mutable references? HOT 1
- Maintenance Status HOT 1
- Possible breaking change in 0.4.1 release HOT 2
- Test failures in Fedora packaging HOT 2
- Use alloc instead of std HOT 2
- Support a shared Semaphor HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from futures-intrusive.