Skip to content

Data race in multi-threaded runtime #6155

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jhpratt opened this issue Nov 18, 2023 · 6 comments · Fixed by #6179
Closed

Data race in multi-threaded runtime #6155

jhpratt opened this issue Nov 18, 2023 · 6 comments · Fixed by #6179
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug. M-runtime Module: tokio/runtime

Comments

@jhpratt
Copy link
Contributor

jhpratt commented Nov 18, 2023

Using tokio 1.34.0 with features macros and rt-multi-threaded (without default features enabled), I have a trivial async program:

#[tokio::main]
async fn main() {
    println!("Hello, world!");
}

Using the nightly-2023-11-16 toolchain with the miri component on the x86_64-unknown-linux-gnu target, I executed MIRIFLAGS="-Zmiri-num-cpus=2" cargo miri run. This results in a data race.

error: Undefined Behavior: Data race detected between (1) atomic load on thread `tokio-runtime-w` and (2) non-atomic read on thread `tokio-runtime-w` at alloc11161+0x20. (2) just happened here
    --> /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:1200:9
     |
1200 |         crate::intrinsics::read_via_copy(src)
     |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) atomic load on thread `tokio-runtime-w` and (2) non-atomic read on thread `tokio-runtime-w` at alloc11161+0x20. (2) just happened here
     |
help: and (1) occurred earlier here
    --> /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/sync/atomic.rs:3096:1
     |
3096 | / atomic_int! {
3097 | |     cfg(target_has_atomic = "32"),
3098 | |     cfg(target_has_atomic_equal_alignment = "32"),
3099 | |     stable(feature = "integer_atomics_stable", since = "1.34.0"),
...    |
3111 | |     u32 AtomicU32
3112 | | }
     | |_^
     = help: overlapping atomic and non-atomic accesses must be synchronized, even if both are read-only
     = help: see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model
     = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
     = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
     = note: BACKTRACE (of the first span):
     = note: inside `std::ptr::read::<u32>` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:1200:9: 1200:46
     = note: inside `tokio::loom::std::atomic_u32::AtomicU32::unsync_load` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/loom/std/atomic_u32.rs:26:9: 26:56
     = note: inside `tokio::runtime::scheduler::multi_thread::queue::Local::<std::sync::Arc<tokio::runtime::scheduler::multi_thread::handle::Handle>>::pop` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/multi_thread/queue.rs:354:33: 354:62
     = note: inside closure at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/multi_thread/worker.rs:810:42: 810:62
     = note: inside `std::option::Option::<tokio::runtime::task::Notified<std::sync::Arc<tokio::runtime::scheduler::multi_thread::handle::Handle>>>::or_else::<{closure@tokio::runtime::scheduler::multi_thread::worker::Core::next_local_task::{closure#0}}>` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:1506:21: 1506:24
     = note: inside `tokio::runtime::scheduler::multi_thread::worker::Core::next_local_task` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/multi_thread/worker.rs:810:9: 810:63
     = note: inside `tokio::runtime::scheduler::multi_thread::worker::Core::next_task` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/multi_thread/worker.rs:764:30: 764:52
     = note: inside `tokio::runtime::scheduler::multi_thread::worker::Context::run` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/multi_thread/worker.rs:525:33: 525:61
     = note: inside closure at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/multi_thread/worker.rs:491:21: 491:33
     = note: inside `tokio::runtime::context::scoped::Scoped::<tokio::runtime::scheduler::Context>::set::<{closure@tokio::runtime::scheduler::multi_thread::worker::run::{closure#0}::{closure#0}}, ()>` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/context/scoped.rs:40:9: 40:12
     = note: inside closure at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/context.rs:176:26: 176:47
     = note: inside `std::thread::LocalKey::<tokio::runtime::context::Context>::try_with::<{closure@tokio::runtime::context::set_scheduler<(), {closure@tokio::runtime::scheduler::multi_thread::worker::run::{closure#0}::{closure#0}}>::{closure#0}}, ()>` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:270:16: 270:31
     = note: inside `std::thread::LocalKey::<tokio::runtime::context::Context>::with::<{closure@tokio::runtime::context::set_scheduler<(), {closure@tokio::runtime::scheduler::multi_thread::worker::run::{closure#0}::{closure#0}}>::{closure#0}}, ()>` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:246:9: 246:25
     = note: inside `tokio::runtime::context::set_scheduler::<(), {closure@tokio::runtime::scheduler::multi_thread::worker::run::{closure#0}::{closure#0}}>` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/context.rs:176:9: 176:48
     = note: inside closure at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/multi_thread/worker.rs:486:9: 497:11
     = note: inside `tokio::runtime::context::runtime::enter_runtime::<{closure@tokio::runtime::scheduler::multi_thread::worker::run::{closure#0}}, ()>` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/context/runtime.rs:65:16: 65:38
     = note: inside `tokio::runtime::scheduler::multi_thread::worker::run` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/multi_thread/worker.rs:478:5: 498:7
     = note: inside closure at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/scheduler/multi_thread/worker.rs:447:45: 447:56
     = note: inside `<tokio::runtime::blocking::task::BlockingTask<{closure@tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{closure#0}}> as std::future::Future>::poll` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/blocking/task.rs:42:21: 42:27
     = note: inside closure at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/task/core.rs:328:17: 328:37
     = note: inside `tokio::loom::std::unsafe_cell::UnsafeCell::<tokio::runtime::task::core::Stage<tokio::runtime::blocking::task::BlockingTask<{closure@tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{closure#0}}>>>::with_mut::<std::task::Poll<()>, {closure@tokio::runtime::task::core::Core<tokio::runtime::blocking::task::BlockingTask<{closure@tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{closure#0}}>, tokio::runtime::blocking::schedule::BlockingSchedule>::poll::{closure#0}}>` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/loom/std/unsafe_cell.rs:16:9: 16:24
     = note: inside `tokio::runtime::task::core::Core::<tokio::runtime::blocking::task::BlockingTask<{closure@tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{closure#0}}>, tokio::runtime::blocking::schedule::BlockingSchedule>::poll` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/task/core.rs:317:13: 329:15
     = note: inside closure at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/task/harness.rs:485:19: 485:38
     = note: inside `<std::panic::AssertUnwindSafe<{closure@tokio::runtime::task::harness::poll_future<tokio::runtime::blocking::task::BlockingTask<{closure@tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{closure#0}}>, tokio::runtime::blocking::schedule::BlockingSchedule>::{closure#0}}> as std::ops::FnOnce<()>>::call_once` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-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@tokio::runtime::task::harness::poll_future<tokio::runtime::blocking::task::BlockingTask<{closure@tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{closure#0}}>, tokio::runtime::blocking::schedule::BlockingSchedule>::{closure#0}}>, std::task::Poll<()>>` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:552:40: 552:43
     = note: inside `std::panicking::r#try::<std::task::Poll<()>, std::panic::AssertUnwindSafe<{closure@tokio::runtime::task::harness::poll_future<tokio::runtime::blocking::task::BlockingTask<{closure@tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{closure#0}}>, tokio::runtime::blocking::schedule::BlockingSchedule>::{closure#0}}>>` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:516:19: 516:81
     = note: inside `std::panic::catch_unwind::<std::panic::AssertUnwindSafe<{closure@tokio::runtime::task::harness::poll_future<tokio::runtime::blocking::task::BlockingTask<{closure@tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{closure#0}}>, tokio::runtime::blocking::schedule::BlockingSchedule>::{closure#0}}>, std::task::Poll<()>>` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:142:14: 142:33
     = note: inside `tokio::runtime::task::harness::poll_future::<tokio::runtime::blocking::task::BlockingTask<{closure@tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{closure#0}}>, tokio::runtime::blocking::schedule::BlockingSchedule>` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/task/harness.rs:473:18: 488:8
     = note: inside `tokio::runtime::task::harness::Harness::<tokio::runtime::blocking::task::BlockingTask<{closure@tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{closure#0}}>, tokio::runtime::blocking::schedule::BlockingSchedule>::poll_inner` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/task/harness.rs:208:27: 208:55
     = note: inside `tokio::runtime::task::harness::Harness::<tokio::runtime::blocking::task::BlockingTask<{closure@tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{closure#0}}>, tokio::runtime::blocking::schedule::BlockingSchedule>::poll` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/task/harness.rs:153:15: 153:32
     = note: inside `tokio::runtime::task::raw::poll::<tokio::runtime::blocking::task::BlockingTask<{closure@tokio::runtime::scheduler::multi_thread::worker::Launch::launch::{closure#0}}>, tokio::runtime::blocking::schedule::BlockingSchedule>` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/task/raw.rs:271:5: 271:19
     = note: inside `tokio::runtime::task::raw::RawTask::poll` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/task/raw.rs:201:18: 201:41
     = note: inside `tokio::runtime::task::UnownedTask::<tokio::runtime::blocking::schedule::BlockingSchedule>::run` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/task/mod.rs:445:9: 445:19
     = note: inside `tokio::runtime::blocking::pool::Task::run` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/blocking/pool.rs:159:9: 159:24
     = note: inside `tokio::runtime::blocking::pool::Inner::run` at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/blocking/pool.rs:513:17: 513:27
     = note: inside closure at /home/jhpratt/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.34.0/src/runtime/blocking/pool.rs:471:13: 471:54
     = note: inside `std::sys_common::backtrace::__rust_begin_short_backtrace::<{closure@tokio::runtime::blocking::pool::Spawner::spawn_thread::{closure#0}}, ()>` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys_common/backtrace.rs:154:18: 154:21
     = note: inside closure at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:529:17: 529:78
     = note: inside `<std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, {closure@tokio::runtime::blocking::pool::Spawner::spawn_thread::{closure#0}}, ()>::{closure#1}::{closure#0}}> as std::ops::FnOnce<()>>::call_once` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-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_<'_, '_, {closure@tokio::runtime::blocking::pool::Spawner::spawn_thread::{closure#0}}, ()>::{closure#1}::{closure#0}}>, ()>` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:552:40: 552:43
     = note: inside `std::panicking::r#try::<(), std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, {closure@tokio::runtime::blocking::pool::Spawner::spawn_thread::{closure#0}}, ()>::{closure#1}::{closure#0}}>>` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:516:19: 516:81
     = note: inside `std::panic::catch_unwind::<std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, {closure@tokio::runtime::blocking::pool::Spawner::spawn_thread::{closure#0}}, ()>::{closure#1}::{closure#0}}>, ()>` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:142:14: 142:33
     = note: inside closure at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:528:30: 530:16
     = note: inside `<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, {closure@tokio::runtime::blocking::pool::Spawner::spawn_thread::{closure#0}}, ()>::{closure#1}} as std::ops::FnOnce<()>>::call_once - shim(vtable)` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-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 /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2007:9: 2007:52
     = note: inside `<std::boxed::Box<std::boxed::Box<dyn std::ops::FnOnce()>> as std::ops::FnOnce<()>>::call_once` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2007:9: 2007:52
     = note: inside `std::sys::unix::thread::Thread::new::thread_start` at /home/jhpratt/.rustup/toolchains/nightly-2023-11-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/unix/thread.rs:108:17: 108:64
     = note: this error originates in the macro `atomic_int` (in Nightly builds, run with -Z macro-backtrace for more info)

For completeness, this is Cargo.lock.

Cargo.lock contents

# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3

[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]

[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"

[[package]]
name = "backtrace"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]

[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]

[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"

[[package]]
name = "gimli"
version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"

[[package]]
name = "hermit-abi"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"

[[package]]
name = "libc"
version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"

[[package]]
name = "memchr"
version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"

[[package]]
name = "miniz_oxide"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"adler",
]

[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]

[[package]]
name = "object"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
dependencies = [
"memchr",
]

[[package]]
name = "pin-project-lite"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"

[[package]]
name = "proc-macro2"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [
"unicode-ident",
]

[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]

[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"

[[package]]
name = "syn"
version = "2.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]

[[package]]
name = "tokio"
version = "1.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9"
dependencies = [
"backtrace",
"num_cpus",
"pin-project-lite",
"tokio-macros",
]

[[package]]
name = "tokio-data-race"
version = "0.1.0"
dependencies = [
"tokio",
]

[[package]]
name = "tokio-macros"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"

From @Darksonn via email (in part)

It appears that the issue is that miri currently does not allow a race between two loads when one is atomic and the other is non-atomic.

[W]e will not consider this to be a security issue. It is not something that actually leads to miscompilations on any existing compilers, and it is also extremely unlikely to lead to miscompilations on future compilers.

@jhpratt jhpratt added A-tokio Area: The main tokio crate C-bug Category: This is a bug. labels Nov 18, 2023
@Darksonn Darksonn added the M-runtime Module: tokio/runtime label Nov 18, 2023
@Darksonn
Copy link
Contributor

As I mentioned in the email you quoted, this isn't something that we will consider to be a security vulnerability. Still, thank you for following our process to disclose potential security issues privately first.

The easiest way to fix the MIRI failure is to change this function to do a relaxed load instead:

/// Performs an unsynchronized load.
///
/// # Safety
///
/// All mutations must have happened before the unsynchronized load.
/// Additionally, there must be no concurrent mutations.
pub(crate) unsafe fn unsync_load(&self) -> usize {
core::ptr::read(self.inner.get() as *const usize)
}

We could even do that conditionally only on MIRI if this turns out to matter for performance.

Either way, we probably want to keep it as an unsynchronized load under loom to keep code valid under that assumption.

cc @RalfJung

@RalfJung
Copy link

We could even do that conditionally only on MIRI if this turns out to matter for performance.

I'd rather offer a flag in Miri that allows read-read races. We currently reject them because they are documented as forbidden, which follows C++.

If making this load synchronized is an issue for Tokio, that's a good argument for working towards allowing such code. We shouldn't just paper over the fact that Tokio breaks rules that are written down explicitly in our docs. :) (The docs change is fairly new, but that's because until recently there wasn't even any way to cause such read-read races without basically transmuting the memory.)

@CAD97
Copy link

CAD97 commented Nov 18, 2023

"no sane compiler would optimize atomics," but note that this race AIUI would still be considered UB at the LLVM level; an "unordered atomic" load has stronger guarantees than a "not atomic" load. On the other hand, my very quick scan suggested the only codegen difference is that "unordered" won't compile if it could tear, but otherwise lower identically to "not."

Since Rust doesn't expose access to "unordered atomic", using a "not atomic" read (when it only ever races with atomic reads) is still formally incorrect but does seem at least a reasonable concession to reality.

Personally I would just use a relaxed load to avoid needing to answer the weird questions and avoid giving LLVM justification to dislike me. But asserting the stronger proof under loom still remains useful even if it doesn't get communicated to the codegen.

@Darksonn
Copy link
Contributor

@CAD97 Did you miss that no actual writes are involved? It's a "race" between two loads. And when I read the LangRef, it appears to me that we would get defined behavior and non-undef values from this situation at the LLVM level.

@Darksonn
Copy link
Contributor

I'd rather offer a flag in Miri that allows read-read races.

That would have the unfortunate effect that you would no longer be able to run programs using Tokio under miri in the playground. I think there is a lot of value for Tokio to work under the default miri configuration.

@RalfJung
Copy link

but note that this race AIUI would still be considered UB at the LLVM level

I don't think so. LLVM has no UB from data races. It considers read-write races to make the read return undef, and write-write races to change the memory contents to undef.

Reading the LLVM docs on this, I think this is completely well-defined. A read that is part of such a read-read race still sees only a single possible write, so we end up in this clause:

"Otherwise, if Rbyte may see exactly one write, Rbyte returns the value written by that write."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug. M-runtime Module: tokio/runtime
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants