Program hangs when using `println!` but not with `eprintln!`
⚓ Rust 📅 2025-12-16 👤 surdeus 👁️ 2I am working through this year's Advent of Code and ran into a weird issue when I briefly added some println!s to check something on one of the puzzles.
When I use println! the program hangs and does not finish or print anything to the terminal even after a few minutes.
When I use eprintln! everything works fine and as expected: the eprintln! output shows up in the terminal and the whole program finishes in less than 700 ms.
Without any println! or eprintln! the program also works as expected.
When the program hangs and I check my CPU usage I don't see any cores spinning at 100% or anything like that. In fact it looks like my system is mostly idle.
This issue appears both in debug and release modes.
Printing to the terminal from other parts of the program works fine.
The problematic println!s are inside a function that is run on multiple threads.
The threads are spawned like this:
pub fn solve_puzzle_b(input: &str) -> usize {
let machines: Vec<Machine> = input.lines().map(|l| l.into()).collect();
// My laptop has 8C/16T, but the issue appears even when I hardcode
// `thread_count` to 1
let thread_count = std::thread::available_parallelism().unwrap().get();
let chunk_size = (machines.len() / thread_count) + 1;
let chunks = machines.chunks(chunk_size);
std::thread::scope(|s| {
let mut join_handles = Vec::with_capacity(thread_count);
for chunk in chunks {
let handle = s.spawn(|| chunk.iter().map(|m| m.configure_joltage()).sum::<usize>());
join_handles.push(handle);
}
join_handles.into_iter().map(|h| h.join().unwrap()).sum()
})
}
The configure_joltage function is the problematic one. The issue disappears when I run everything on the main thread instead of spawning a separate thread to do the work. Note that the issue appears even when I only spawn one thread.
The input is split up and processed in parallel and doesn't need any locks or other synchronization, so there should be no deadlocks.
I know the threads all need to get access to stdout/stderr and that will slow them down, but I'd expected to see at least some output, because one of the threads should always succeed in getting the lock on stdout/stderr, right? The fact that this problem appears even when I only spawn a single thread to do all the work is very confusing to me.
Is there something about printing to stdout vs stderr that is different when doing it from a thread other than the main thread?
The configure_joltage function is a bit long and messy, so I'll only paste the sections around the print statements here:
fn configure_joltage(&self) -> usize {
// [omitted for brevity]
// essentially we build a matrix like
// `let mut matrix: Vec<i32> = Vec::with_capacity(rows * cols);`
// and fill it with data.
// Check if we can immediately spot a solution
for row in 0..rows {
if (0..(cols - 1))
.map(|col| matrix[row * cols + col])
.all(|e| e == 1)
{
let result = matrix[row * cols + cols - 1];
debug_assert!(result >= 0);
// PROBLEMATIC `println!` vvvv
println!("Found a fast solution for machine: `{result}`. Yay! :)");
return result as usize;
}
}
// [omitted for brevity]
// The code here does gaussian elimination on the matrix.
if free_vars_curr.is_empty() {
// All variables are fully determined. We can return.
let sum = (0..rows)
.map(|row| matrix[row * cols + cols - 1])
.sum::<i32>();
debug_assert!(sum >= 0);
// ANOTHER PROBLEMATIC one vvvv
println!("Found a result for machine without brute force: `{sum}`. Yay! :)");
return sum as usize;
}
// [omitted again]
// ALSO PROBLEMATIC
println!("Found solution for machine: {solution}");
solution as usize
The println!s were just meant as a quick check to see if any of the early return cases are actually hit, but now I'm really curious to see why they cause my program to hang while eprintln! does not.
Can anyone enlighten me as to what might be causing this?
I am on Linux and using Rust 1.91.1
4 posts - 2 participants
🏷️ Rust_feed