-
Notifications
You must be signed in to change notification settings - Fork 190
Description
Description
I’m seeing a heap corruption crash when using glommio::channels::spsc_queue from multiple producer and consumer threads.
The code only uses safe Rust and the public glommio::channels::spsc_queue API, but at runtime it fails with:
Avvio demo Glommio Multi-Thread...
malloc(): chunk size mismatch in fastbin
malloc(): chunk size mismatch in fastbin
Aborted (core dumped) cargo run
This looks like memory corruption / unsoundness in safe code.
I realize this is an SPSC queue and that my sample intentionally uses multiple producers and multiple consumers, but since the API is fully safe, it shouldn’t be possible to trigger heap corruption (ideally the type system or runtime checks would prevent this usage, or at worst it should fail cleanly without UB).
Environment
- Glommio version:
0.9.0(from github) - Rust version:
rustc 1.xx.x (stable) - OS: Linux x86_64 Fedora
- Build:
cargo run --releaseandcargo runboth affected
Minimal reproducible example
use std::error::Error;
use glommio::channels::spsc_queue;
fn main() -> Result<(), Box<dyn Error>> {
println!("Avvio demo Glommio Multi-Thread...");
let (sender, mut receiver) = spsc_queue::make::<String>(4096);
let mut producers = Vec::new();
let mut consumers = Vec::new();
// 2 producers
for i in 0..2 {
let sender = sender.clone();
producers.push(std::thread::spawn(move || {
for j in 0..500_000 {
let msg = format!("Messaggio {} dal produttore {}\n", j, i);
// ignoring the return value for simplicity
let _ = sender.try_push(msg);
}
}));
}
// 2 consumers
for _ in 0..2 {
let receiver = receiver.clone();
consumers.push(std::thread::spawn(move || {
for _ in 0..500_000 {
let _ = receiver.try_pop();
}
}));
}
for producer in producers {
producer.join().unwrap();
}
for consumer in consumers {
consumer.join().unwrap();
}
Ok(())
}Running this with cargo run produces:
Avvio demo Glommio Multi-Thread...
malloc(): chunk size mismatch in fastbin
malloc(): chunk size mismatch in fastbin
Aborted (core dumped) cargo run
Expected behavior
Even if using spsc_queue in a way that violates its logical “single producer / single consumer” design, the use of safe APIs should not result in undefined behavior or heap corruption.
Ideally one of the following would happen instead:
- The type system prevents this misuse (e.g.
Producer/Consumernot beingClone, or being more constrained), or - There are documented guarantees that misusing the queue can cause UB, or
- The queue detects this situation and fails in a defined way (panic, error, etc.), rather than corrupting memory.
Actual behavior
-
Program prints
Avvio demo Glommio Multi-Thread... -
Then glibc reports:
malloc(): chunk size mismatch in fastbin malloc(): chunk size mismatch in fastbin Aborted (core dumped) -
This suggests memory corruption happening internally, triggered only through safe
Producer::try_pushandConsumer::try_popcalls.
Additional notes
Producer<T>andConsumer<T>areSendbut!Sync, and they areClone. This allows creating multiple cloned producers/consumers that operate concurrently on the same underlying queue from different threads.- The module name
spsc_queuesuggests single-producer/single-consumer behavior, but the current API surface (especiallyClone+Send) makes it easy to use it in multi-producer/multi-consumer scenarios without any compiler errors or warnings. - Even if this usage is considered invalid, the fact that it leads to heap corruption in safe Rust feels like at least a documentation or soundness issue.
If this usage is explicitly unsupported and considered undefined behavior, it might be helpful to:
- Clarify that in the documentation for
spsc_queue::make,Producer, andConsumer, and/or - Tighten the API (e.g. remove
Cloneor add runtime checks) so that this pattern doesn’t compile or at least doesn’t lead to memory corruption.