diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-08-05 22:20:16 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-08-05 22:20:45 +0200 |
| commit | aaa0d1419cca754add76950ac9bae8a3dd526964 (patch) | |
| tree | bf10936b0b92eacb7a125db3f5b739f1d47c0d91 | |
| parent | 8a65128cfed335e637ee80c91b1efc7b3c58ba10 (diff) | |
util: fix unsoundness when dropping ThreadModeMutex outside thread mode.
Fixes #283
| -rw-r--r-- | embassy/src/util/mutex.rs | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/embassy/src/util/mutex.rs b/embassy/src/util/mutex.rs index 0506ffe6f..9a00a409e 100644 --- a/embassy/src/util/mutex.rs +++ b/embassy/src/util/mutex.rs | |||
| @@ -82,9 +82,7 @@ impl<T> ThreadModeMutex<T> { | |||
| 82 | inner: UnsafeCell::new(value), | 82 | inner: UnsafeCell::new(value), |
| 83 | } | 83 | } |
| 84 | } | 84 | } |
| 85 | } | ||
| 86 | 85 | ||
| 87 | impl<T> ThreadModeMutex<T> { | ||
| 88 | /// Borrows the data | 86 | /// Borrows the data |
| 89 | pub fn borrow(&self) -> &T { | 87 | pub fn borrow(&self) -> &T { |
| 90 | assert!( | 88 | assert!( |
| @@ -107,6 +105,21 @@ impl<T> Mutex for ThreadModeMutex<T> { | |||
| 107 | } | 105 | } |
| 108 | } | 106 | } |
| 109 | 107 | ||
| 108 | impl<T> Drop for ThreadModeMutex<T> { | ||
| 109 | fn drop(&mut self) { | ||
| 110 | // Only allow dropping from thread mode. Dropping calls drop on the inner `T`, so | ||
| 111 | // `drop` needs the same guarantees as `lock`. `ThreadModeMutex<T>` is Send even if | ||
| 112 | // T isn't, so without this check a user could create a ThreadModeMutex in thread mode, | ||
| 113 | // send it to interrupt context and drop it there, which would "send" a T even if T is not Send. | ||
| 114 | assert!( | ||
| 115 | in_thread_mode(), | ||
| 116 | "ThreadModeMutex can only be dropped from thread mode." | ||
| 117 | ); | ||
| 118 | |||
| 119 | // Drop of the inner `T` happens after this. | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 110 | pub fn in_thread_mode() -> bool { | 123 | pub fn in_thread_mode() -> bool { |
| 111 | #[cfg(feature = "std")] | 124 | #[cfg(feature = "std")] |
| 112 | return Some("main") == std::thread::current().name(); | 125 | return Some("main") == std::thread::current().name(); |
