Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ci/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ case $HOST_TARGET in
# Partially supported targets (tier 2)
BASIC="empty_main integer heap_alloc libc-mem vec string btreemap" # ensures we have the basics: pre-main code, system allocator
UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random thread sync concurrency epoll eventfd
TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random thread sync concurrency epoll eventfd prctl
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std
TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std
;;
Expand Down
101 changes: 54 additions & 47 deletions src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ pub fn report_result<'tcx>(
StackedBorrowsUb { .. } | TreeBorrowsUb { .. } | DataRace { .. } =>
Some("Undefined Behavior"),
LocalDeadlock => {
labels.push(format!("this thread got stuck here"));
labels.push(format!("thread got stuck here"));
None
}
GlobalDeadlock => {
Expand All @@ -264,10 +264,7 @@ pub fn report_result<'tcx>(
report_msg(
DiagLevel::Error,
format!("the evaluated program deadlocked"),
vec![format!(
"thread `{}` got stuck here",
ecx.machine.threads.get_thread_display_name(thread)
)],
vec![format!("thread got stuck here")],
vec![],
vec![],
&stacktrace,
Expand Down Expand Up @@ -558,34 +555,24 @@ pub fn report_msg<'tcx>(
thread: Option<ThreadId>,
machine: &MiriMachine<'tcx>,
) {
let span = match stacktrace.first() {
Some(fi) => fi.span,
None =>
match thread {
Some(thread_id) => machine.threads.thread_ref(thread_id).origin_span,
None => DUMMY_SP,
},
};
let sess = machine.tcx.sess;
let origin_span = thread.map(|t| machine.threads.thread_ref(t).origin_span).unwrap_or(DUMMY_SP);
let span = stacktrace.first().map(|fi| fi.span).unwrap_or(origin_span);
// The only time we do not have an origin span is for `main`, and there we check the signature
// upfront. So we should always have a span here.
assert!(!span.is_dummy());

let tcx = machine.tcx;
let level = match diag_level {
DiagLevel::Error => Level::Error,
DiagLevel::Warning => Level::Warning,
DiagLevel::Note => Level::Note,
};
let mut err = Diag::<()>::new(sess.dcx(), level, title);
let mut err = Diag::<()>::new(tcx.sess.dcx(), level, title);
err.span(span);

// Show main message.
if !span.is_dummy() {
for line in span_msg {
err.span_label(span, line);
}
} else {
// Make sure we show the message even when it is a dummy span.
for line in span_msg {
err.note(line);
}
err.note("(no span available)");
for line in span_msg {
err.span_label(span, line);
}

// Show note and help messages.
Expand All @@ -608,36 +595,56 @@ pub fn report_msg<'tcx>(
}

// Add backtrace
if stacktrace.len() > 1 {
let mut backtrace_title = String::from("BACKTRACE");
if extra_span {
write!(backtrace_title, " (of the first span)").unwrap();
if let Some((first, rest)) = stacktrace.split_first() {
// Start with the function and thread that contain the first span.
let mut fn_and_thread = String::new();
// Only print thread name if there are multiple threads.
if let Some(thread) = thread
&& machine.threads.get_total_thread_count() > 1
{
write!(
fn_and_thread,
"on thread `{}`",
machine.threads.get_thread_display_name(thread)
)
.unwrap();
}
if let Some(thread) = thread {
let thread_name = machine.threads.get_thread_display_name(thread);
if thread_name != "main" {
// Only print thread name if it is not `main`.
write!(backtrace_title, " on thread `{thread_name}`").unwrap();
};
// Only print function name if we show a backtrace
if rest.len() > 0 || !origin_span.is_dummy() {
if !fn_and_thread.is_empty() {
fn_and_thread.push_str(", ");
}
write!(fn_and_thread, "{first}").unwrap();
}
write!(backtrace_title, ":").unwrap();
err.note(backtrace_title);
for (idx, frame_info) in stacktrace.iter().enumerate() {
if !fn_and_thread.is_empty() {
if extra_span && rest.len() > 0 {
// Print a `span_note` as otherwise the backtrace looks attached to the last
// `span_help`. We somewhat arbitrarily use the span of the surrounding function.
err.span_note(
tcx.def_span(first.instance.def_id()),
format!("{level} occurred {fn_and_thread}"),
);
} else {
err.note(format!("this is {fn_and_thread}"));
}
}
// Continue with where that function got called.
for frame_info in rest.iter() {
let is_local = machine.is_local(frame_info.instance);
// No span for non-local frames and the first frame (which is the error site).
if is_local && idx > 0 {
err.subdiagnostic(frame_info.as_note(machine.tcx));
if is_local {
err.span_note(frame_info.span, format!("which got called {frame_info}"));
} else {
let sm = sess.source_map();
let sm = tcx.sess.source_map();
let span = sm.span_to_embeddable_string(frame_info.span);
err.note(format!("{frame_info} at {span}"));
err.note(format!("which got called {frame_info} (at {span})"));
}
}
} else if stacktrace.len() == 0 && !span.is_dummy() {
err.note(format!(
"this {} occurred while pushing a call frame onto an empty stack",
level.to_str()
));
if !origin_span.is_dummy() {
err.span_note(origin_span, format!("which got called indirectly due to this code"));
}
} else if !span.is_dummy() {
err.note(format!("this {level} occurred while pushing a call frame onto an empty stack"));
err.note("the span indicates which code caused the function to be called, but may not be the literal call site");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ LL | let _val = atomic_ref.load(Ordering::Relaxed);
|
= 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: this is on thread `unnamed-ID`, inside closure
note: which got called indirectly due to this code
--> tests/fail-dep/concurrency/apple_os_unfair_lock_move_with_queue.rs:LL:CC
|
LL | / ... s.spawn(|| {
LL | | ... let atomic_ref = unsafe { &*lock.get().cast::<AtomicU32>() };
LL | | ... let _val = atomic_ref.load(Ordering::Relaxed);
LL | | ... });
| |________^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
5 changes: 2 additions & 3 deletions tests/fail-dep/concurrency/libc_pthread_cond_move.init.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ LL | libc::pthread_cond_destroy(cond2.as_mut_ptr());
|
= 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:
= note: inside `check` at tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC
note: inside `main`
= note: this is inside `check`
note: which got called inside `main`
--> tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC
|
LL | check()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ LL | libc::pthread_cond_destroy(&mut cond2 as *mut _);
|
= 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:
= note: inside `check` at tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC
note: inside `main`
= note: this is inside `check`
note: which got called inside `main`
--> tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC
|
LL | check()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ LL | assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0);
|
= 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: this is on thread `main`

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
1 change: 1 addition & 0 deletions tests/fail-dep/concurrency/libc_pthread_join_joined.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ LL | ... assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0);
|
= 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: this is on thread `main`

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
11 changes: 11 additions & 0 deletions tests/fail-dep/concurrency/libc_pthread_join_main.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ LL | ... assert_eq!(libc::pthread_join(thread_id, ptr::null_mut()), 0);
|
= 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: this is on thread `unnamed-ID`, inside closure
note: which got called indirectly due to this code
--> tests/fail-dep/concurrency/libc_pthread_join_main.rs:LL:CC
|
LL | let handle = thread::spawn(move || {
| __________________^
LL | | unsafe {
LL | | assert_eq!(libc::pthread_join(thread_id, ptr::null_mut()), 0);
LL | | }
LL | | });
| |______^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
9 changes: 9 additions & 0 deletions tests/fail-dep/concurrency/libc_pthread_join_multiple.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ LL | ... assert_eq!(libc::pthread_join(native_copy, ptr::null_mut()), 0);
|
= 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: this is on thread `unnamed-ID`, inside closure
note: which got called indirectly due to this code
--> tests/fail-dep/concurrency/libc_pthread_join_multiple.rs:LL:CC
|
LL | ... let handle = thread::spawn(move || {
| ____________________^
LL | | ... assert_eq!(libc::pthread_join(native_copy, ptr::null_mut()), 0);
LL | | ... });
| |________^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
12 changes: 12 additions & 0 deletions tests/fail-dep/concurrency/libc_pthread_join_self.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ LL | assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0);
|
= 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: this is on thread `unnamed-ID`, inside closure
note: which got called indirectly due to this code
--> tests/fail-dep/concurrency/libc_pthread_join_self.rs:LL:CC
|
LL | let handle = thread::spawn(|| {
| __________________^
LL | | unsafe {
LL | | let native: libc::pthread_t = libc::pthread_self();
LL | | assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0);
LL | | }
LL | | });
| |______^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
22 changes: 15 additions & 7 deletions tests/fail-dep/concurrency/libc_pthread_mutex_deadlock.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ error: the evaluated program deadlocked
--> RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC
|
LL | let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) };
| ^ thread `main` got stuck here
| ^ thread got stuck here
|
= note: BACKTRACE:
= note: inside `std::sys::thread::PLATFORM::Thread::join` at RUSTLIB/std/src/sys/thread/PLATFORM.rs:LL:CC
= note: inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC
= note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/join_handle.rs:LL:CC
note: inside `main`
= note: this is on thread `main`, inside `std::sys::thread::PLATFORM::Thread::join`
= note: which got called inside `std::thread::lifecycle::JoinInner::<'_, ()>::join` (at RUSTLIB/std/src/thread/lifecycle.rs:LL:CC)
= note: which got called inside `std::thread::JoinHandle::<()>::join` (at RUSTLIB/std/src/thread/join_handle.rs:LL:CC)
note: which got called inside `main`
--> tests/fail-dep/concurrency/libc_pthread_mutex_deadlock.rs:LL:CC
|
LL | / thread::spawn(move || {
Expand All @@ -21,7 +20,16 @@ error: the evaluated program deadlocked
--> tests/fail-dep/concurrency/libc_pthread_mutex_deadlock.rs:LL:CC
|
LL | assert_eq!(libc::pthread_mutex_lock(lock_copy.0.get() as *mut _), 0);
| ^ thread `unnamed-ID` got stuck here
| ^ thread got stuck here
|
= note: this is on thread `unnamed-ID`, inside closure
note: which got called indirectly due to this code
--> tests/fail-dep/concurrency/libc_pthread_mutex_deadlock.rs:LL:CC
|
LL | / thread::spawn(move || {
LL | | assert_eq!(libc::pthread_mutex_lock(lock_copy.0.get() as *mut _), 0);
LL | | })
| |__________^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,23 @@ LL | self.1.deallocate(From::from(ptr.cast()), layout);
|
= 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 on thread `unnamed-ID`:
= note: inside `<std::boxed::Box<Mutex> as std::ops::Drop>::drop` at RUSTLIB/alloc/src/boxed.rs:LL:CC
= note: inside `std::ptr::drop_in_place::<std::boxed::Box<Mutex>> - shim(Some(std::boxed::Box<Mutex>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
= note: inside `std::mem::drop::<std::boxed::Box<Mutex>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
note: inside closure
= note: this is on thread `unnamed-ID`, inside `<std::boxed::Box<Mutex> as std::ops::Drop>::drop`
= note: which got called inside `std::ptr::drop_in_place::<std::boxed::Box<Mutex>> - shim(Some(std::boxed::Box<Mutex>))` (at RUSTLIB/core/src/ptr/mod.rs:LL:CC)
= note: which got called inside `std::mem::drop::<std::boxed::Box<Mutex>>` (at RUSTLIB/core/src/mem/mod.rs:LL:CC)
note: which got called inside closure
--> tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.rs:LL:CC
|
LL | drop(unsafe { Box::from_raw(m.get().cast::<Mutex>()) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: which got called indirectly due to this code
--> tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.rs:LL:CC
|
LL | / s.spawn(|| {
LL | | // Ensure we happen-after the initialization write.
LL | | assert!(initialized.load(Ordering::Acquire));
... |
LL | | });
| |__________^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ LL | libc::pthread_mutex_lock(&mut m2 as *mut _);
|
= 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:
= note: inside `check` at tests/fail-dep/concurrency/libc_pthread_mutex_move.rs:LL:CC
note: inside `main`
= note: this is inside `check`
note: which got called inside `main`
--> tests/fail-dep/concurrency/libc_pthread_mutex_move.rs:LL:CC
|
LL | check();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ LL | libc::pthread_mutex_unlock(&mut m2 as *mut _);
|
= 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:
= note: inside `check` at tests/fail-dep/concurrency/libc_pthread_mutex_move.rs:LL:CC
note: inside `main`
= note: this is inside `check`
note: which got called inside `main`
--> tests/fail-dep/concurrency/libc_pthread_mutex_move.rs:LL:CC
|
LL | check();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error: a thread deadlocked
--> tests/fail-dep/concurrency/libc_pthread_mutex_normal_reentrant.rs:LL:CC
|
LL | libc::pthread_mutex_lock(&mut mutex as *mut _);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this thread got stuck here
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ thread got stuck here

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ LL | ... let _val = atomic_ref.load(Ordering::Relaxed);
|
= 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: this is on thread `unnamed-ID`, inside closure
note: which got called indirectly due to this code
--> tests/fail-dep/concurrency/libc_pthread_mutex_read_while_queued.rs:LL:CC
|
LL | / ... s.spawn(|| {
LL | | ... let atomic_ref = unsafe { &*m.get().byte_add(OFFSET).cast::<AtomicU32>() };
LL | | ... let _val = atomic_ref.load(Ordering::Relaxed);
LL | | ... });
| |________^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ LL | atomic_ref.store(0, Ordering::Relaxed);
|
= 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: this is on thread `unnamed-ID`, inside closure
note: which got called indirectly due to this code
--> tests/fail-dep/concurrency/libc_pthread_mutex_write_while_queued.rs:LL:CC
|
LL | / s.spawn(|| {
LL | | let atomic_ref = unsafe { &*m.get().byte_add(OFFSET).cast::<AtomicU32>() };
LL | | atomic_ref.store(0, Ordering::Relaxed);
LL | | });
| |__________^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

Expand Down
Loading