critical-section
critical-section copied to clipboard
Mitigate Miri violation
While testing an embassy project on Windows using Miri, I encountered a hard-to-diagnose violation involving a conflict between writing to and dropping critical-section's GLOBAL_GUARD.
I believe the change proposed in this PR is low-risk and should work exactly the same as before while appeasing Miri and potentially mitigating a program bug.
Minimal project to produce Miri complaint:
Cargo.toml:
// ...
[dependencies]
embassy-executor = { version = "0.5.0", features = ["task-arena-size-131072", "arch-std", "executor-thread", "integrated-timers"] }
embassy-time = { version = "0.3.0", features = ["std"] }
main.rs:
#[embassy_executor::main]
async fn main(_spawner: embassy_executor::Spawner) {
loop {
embassy_time::Timer::after_millis(1000).await;
}
}
Miri command (on Windows): cargo +nightly-2024-04-10 miri run
Sample output:
error: Undefined Behavior: not granting access to tag <39012> because that would remove [Unique for <38804>] which is strongly protected because it is an argument of call 8084
--> C:\...\lib\rustlib\src\rust\library\core\src\mem\maybe_uninit.rs:493:24
|
493 | pub const fn write(&mut self, val: T) -> &mut T {
| ^^^^^^^^^ not granting access to tag <39012> because that would remove [Unique for <38804>] which is strongly protected because it is an argument of call 8084
interesting.
do you have some understanding/explanation for why the original code causes a miri error and the change doesn't? Miri doesn't have false positives, so if the original code fails we definitely should fix it. However, it does have false negatives, so it's possible if we do this change without fully understanding why the original is bad and the new is good, we're just randomly changing the code to mask the issue (false negative) instead of actually fixing it.
Hi. I was looking at this with @Catamantaloedis earlier today, and had suggested that change on a hunch.
Without having a completely solid grasp of Rust's semantics in this area, my guess is that it comes down to assume_init_drop being an in-place drop, and the need for drop to hold exclusive mutable access to what is being dropped. In this case, dropping a MutexGuard unlocks the mutex during the drop, but the &mut bound to the MutexGuard lives on for the entirety of the drop operation. This means that there's a portion of execution (if not in practice, then at least semantically) where the mutex is unlocked but an &mut reference to the contents of GLOBAL_GUARD is still alive, which is "racy" insofar as that the mutex is itself being used to synchronize access to GLOBAL_GUARD.
The "fix" was based on the observation that there's no need to actually do the drop in-place; the drop is just for its side-effect of unlocking the mutex, and not for any mutation it may or may not perform to the guard object itself. The change to
let _ = GLOBAL_GUARD.assume_init_read();
means that the drop is instead performed on a temporary loaded out of GLOBAL_GUARD, so there's never a mutating reference bound to GLOBAL_GUARD in the first place.
I can't reproduce this, Miri is giving an ICE...
- Can you post the full miri error?
- Do you have a more reduced version to trigger this, that doesn't depend on embassy crates?
I'm hitting the same UB report on Linux too.
I can't reproduce this, Miri is giving an ICE...
Miri has a bug for clock for now. See https://github.com/rust-lang/miri/issues/3647 (with reproducible code in there but on top of embassy).
So miri should be run in host system environment instead of faked one via
MIRIFLAGS="-Zmiri-disable-isolation" cargo miri run
Full error with 1 sec tick
embassy-local ✗ MIRIFLAGS="-Zmiri-disable-isolation" cargo miri run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s
Running `/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner target/miri/x86_64-unknown-linux-gnu/debug/embassy-local`
[2024-06-05T02:15:37Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:38Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:39Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:40Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:41Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:42Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:43Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:45Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:46Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:47Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:48Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:49Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:50Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:51Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:52Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:54Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:55Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:56Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:57Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:58Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:15:59Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:00Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:02Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:03Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:04Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:05Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:06Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:07Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:08Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:10Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:11Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:12Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:13Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:14Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:15Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:16Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:17Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:19Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:20Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:21Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:22Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:23Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:24Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:25Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:27Z INFO embassy_local] tick for 1 sec
[2024-06-05T02:16:28Z INFO embassy_local] tick for 1 sec
error: Undefined Behavior: not granting access to tag <1457496> because that would remove [Unique for <1457358>] which is strongly protected because it is an argument of call 310298
--> /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/maybe_uninit.rs:493:24
|
493 | pub const fn write(&mut self, val: T) -> &mut T {
| ^^^^^^^^^ not granting access to tag <1457496> because that would remove [Unique for <1457358>] which is strongly protected because it is an argument of call 310298
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
help: <1457496> was created by a SharedReadWrite retag at offsets [0x0..0x10]
--> /root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/critical-section-1.1.2/src/std.rs:38:13
|
38 | GLOBAL_GUARD.write(guard);
| ^^^^^^^^^^^^
help: <1457358> is this argument
--> src/main.rs:20:1
|
20 | #[embassy_executor::main]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE (of the first span) on thread `unnamed-1`:
= note: inside `std::mem::MaybeUninit::<std::sync::MutexGuard<'_, ()>>::write` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/maybe_uninit.rs:493:24: 493:33
= note: inside closure at /root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/critical-section-1.1.2/src/std.rs:38:13: 38:38
= note: inside `std::thread::LocalKey::<std::cell::Cell<bool>>::try_with::<{closure@<critical_section::std::StdCriticalSection as critical_section::Impl>::acquire::{closure#0}}, bool>` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:286:12: 286:27
= note: inside `std::thread::LocalKey::<std::cell::Cell<bool>>::with::<{closure@<critical_section::std::StdCriticalSection as critical_section::Impl>::acquire::{closure#0}}, bool>` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:262:9: 262:25
= note: inside `<critical_section::std::StdCriticalSection as critical_section::Impl>::acquire` at /root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/critical-section-1.1.2/src/std.rs:18:9: 41:11
= note: inside `critical_section::std::_critical_section_1_0_acquire` at /root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/critical-section-1.1.2/src/lib.rs:282:13: 282:44
= note: inside `critical_section::acquire` at /root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/critical-section-1.1.2/src/lib.rs:183:18: 183:49
= note: inside `critical_section::with::<u64, {closure@embassy_time::driver_std::TimeDriver::alarm_thread::{closure#0}}>` at /root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/critical-section-1.1.2/src/lib.rs:226:26: 226:35
= note: inside `embassy_time::driver_std::TimeDriver::alarm_thread` at /root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/embassy-time-0.3.0/src/driver_std.rs:72:30: 103:15
= note: inside `<fn() {embassy_time::driver_std::TimeDriver::alarm_thread} as std::ops::FnOnce<()>>::call_once - shim(fn() {embassy_time::driver_std::TimeDriver::alarm_thread})` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5: 250:71
= note: inside `std::sys_common::backtrace::__rust_begin_short_backtrace::<fn() {embassy_time::driver_std::TimeDriver::alarm_thread}, ()>` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys_common/backtrace.rs:155:18: 155:21
= note: inside closure at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:542:17: 542:78
= note: inside `<std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, fn() {embassy_time::driver_std::TimeDriver::alarm_thread}, ()>::{closure#2}::{closure#0}}> as std::ops::FnOnce<()>>::call_once` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:272:9: 272:19
= note: inside `std::panicking::r#try::do_call::<std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, fn() {embassy_time::driver_std::TimeDriver::alarm_thread}, ()>::{closure#2}::{closure#0}}>, ()>` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:559:40: 559:43
= note: inside `std::panicking::r#try::<(), std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, fn() {embassy_time::driver_std::TimeDriver::alarm_thread}, ()>::{closure#2}::{closure#0}}>>` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:523:19: 523:88
= note: inside `std::panic::catch_unwind::<std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, fn() {embassy_time::driver_std::TimeDriver::alarm_thread}, ()>::{closure#2}::{closure#0}}>, ()>` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:149:14: 149:33
= note: inside closure at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:541:30: 543:16
= note: inside `<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, fn() {embassy_time::driver_std::TimeDriver::alarm_thread}, ()>::{closure#2}} as std::ops::FnOnce<()>>::call_once - shim(vtable)` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5: 250:71
= note: inside `<std::boxed::Box<dyn std::ops::FnOnce()> as std::ops::FnOnce<()>>::call_once` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2063:9: 2063:52
= note: inside `<std::boxed::Box<std::boxed::Box<dyn std::ops::FnOnce()>> as std::ops::FnOnce<()>>::call_once` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2063:9: 2063:52
= note: inside `std::sys::pal::unix::thread::Thread::new::thread_start` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/pal/unix/thread.rs:108:17: 108:64
= note: this error originates in the attribute macro `embassy_executor::main` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error
I tried to make backtrace readable as below
std::mem::MaybeUninit::<std::sync::MutexGuard<'_, ()>>::write
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/maybe_uninit.rs:493:24: 493:33
closure
/root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/critical-section-1.1.2/src/std.rs:38:13: 38:38
std::thread::LocalKey::<std::cell::Cell<bool>>::try_with::<{closure@<critical_section::std::StdCriticalSection as critical_section::Impl>::acquire::{closure#0}}, bool>
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:286:12: 286:27
std::thread::LocalKey::<std::cell::Cell<bool>>::with::<{closure@<critical_section::std::StdCriticalSection as critical_section::Impl>::acquire::{closure#0}}, bool>
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:262:9: 262:25
<critical_section::std::StdCriticalSection as critical_section::Impl>::acquire
/root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/critical-section-1.1.2/src/std.rs:18:9: 41:11
critical_section::std::_critical_section_1_0_acquire
/root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/critical-section-1.1.2/src/lib.rs:282:13: 282:44
critical_section::acquire
/root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/critical-section-1.1.2/src/lib.rs:183:18: 183:49
critical_section::with::<u64, {closure@embassy_time::driver_std::TimeDriver::alarm_thread::{closure#0}}>
/root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/critical-section-1.1.2/src/lib.rs:226:26: 226:35
embassy_time::driver_std::TimeDriver::alarm_thread
/root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/embassy-time-0.3.0/src/driver_std.rs:72:30: 103:15
<fn() {embassy_time::driver_std::TimeDriver::alarm_thread} as std::ops::FnOnce<()>>::call_once - shim(fn() {embassy_time::driver_std::TimeDriver::alarm_thread})
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5: 250:71
std::sys_common::backtrace::__rust_begin_short_backtrace::<fn() {embassy_time::driver_std::TimeDriver::alarm_thread}, ()>
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys_common/backtrace.rs:155:18: 155:21
closure
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:542:17: 542:78
<std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, fn() {embassy_time::driver_std::TimeDriver::alarm_thread}, ()>::{closure#2}::{closure#0}}> as std::ops::FnOnce<()>>::call_once
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:272:9: 272:19
std::panicking::r#try::do_call::<std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, fn() {embassy_time::driver_std::TimeDriver::alarm_thread}, ()>::{closure#2}::{closure#0}}>, ()>
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:559:40: 559:43
std::panicking::r#try::<(), std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, fn() {embassy_time::driver_std::TimeDriver::alarm_thread}, ()>::{closure#2}::{closure#0}}>>
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:523:19: 523:88
std::panic::catch_unwind::<std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, fn() {embassy_time::driver_std::TimeDriver::alarm_thread}, ()>::{closure#2}::{closure#0}}>, ()>
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:149:14: 149:33
closure
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:541:30: 543:16
<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, fn() {embassy_time::driver_std::TimeDriver::alarm_thread}, ()>::{closure#2}} as std::ops::FnOnce<()>>::call_once - shim(vtable)
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5: 250:71
<std::boxed::Box<dyn std::ops::FnOnce()> as std::ops::FnOnce<()>>::call_once
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2063:9: 2063:52
<std::boxed::Box<std::boxed::Box<dyn std::ops::FnOnce()>> as std::ops::FnOnce<()>>::call_once
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2063:9: 2063:52
std::sys::pal::unix::thread::Thread::new::thread_start
/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/pal/unix/thread.rs:108:17: 108:64
It basically says aliasing rules are violated. I agree with @distractedlambda that there are two mutable/exclusive reference caused by dropping, because when I tuned the tick frequency to 10 ms, miri points out drop removes Unique tag.
embassy-local ✗ MIRIFLAGS="-Zmiri-disable-isolation" cargo miri run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.43s
Running `/root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner target/miri/x86_64-unknown-linux-gnu/debug/embassy-local`
[2024-06-05T03:46:58Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:46:58Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:46:59Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:46:59Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:46:59Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:46:59Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:46:59Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:46:59Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:47:00Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:47:00Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:47:00Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:47:00Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:47:00Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:47:00Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:47:00Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:47:01Z INFO embassy_local] tick for 10 millis
[2024-06-05T03:47:01Z INFO embassy_local] tick for 10 millis
error: Undefined Behavior: not granting access to tag <526578> because that would remove [Unique for <526360>] which is strongly protected because it is an argument of call 112396
--> /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/maybe_uninit.rs:493:24
|
493 | pub const fn write(&mut self, val: T) -> &mut T {
| ^^^^^^^^^ not granting access to tag <526578> because that would remove [Unique for <526360>] which is strongly protected because it is an argument of call 112396
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
help: <526578> was created by a SharedReadWrite retag at offsets [0x0..0x10]
--> src/main.rs:20:1
|
20 | #[embassy_executor::main]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
help: <526360> is this argument
--> /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sync/mutex.rs:548:13
|
548 | fn drop(&mut self) {
| ^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `std::mem::MaybeUninit::<std::sync::MutexGuard<'_, ()>>::write` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/maybe_uninit.rs:493:24: 493:33
= note: inside closure at /root/.cargo/registry/src/rsproxy.cn-0dccff568467c15b/critical-section-1.1.2/src/std.rs:38:13: 38:38
= note: inside `std::thread::LocalKey::<std::cell::Cell<bool>>::try_with::<{closure@<critical_section::std::StdCriticalSection as critical_section::Impl>::acquire::{closure#0}}, bool>` at /root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:286:12: 286:27
...
With the code in this PR, miri doesn't complain any more.