Bug in Weak::upgrade?


I've made a component similar to sync_channel where I want to guarantee all messages on the Receiver side are used before the channel is discarded. The SyncSender side contains a Weak which on every .send() is upgraded to an Arc.

In this stack trace SyncSender is my implementation, not std.

pub struct SyncSender<T> {
    state: Weak<(Mutex<State<T>>, Condvar)>,
    name: String,

Occasionally my program crashes with this, and I'm a bit perplexed. I don't have any unsafe code here, and the docs don't mention that upgrade() has any panic situations.

Are there situations that Weak wrapping a Mutex/Condvar could fail?

* thread #2, name = 'vtc_dec', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
  * frame #0: 0x00000001001af6ce umar`core::sync::atomic::atomic_load<usize>(dst=0x646e6553636e7953, order=Relaxed) at atomic.rs:1498
    frame #1: 0x00000001001af53c umar`core::sync::atomic::{{impl}}::load(self=0x646e6553636e7953, order=Relaxed) at atomic.rs:1078
    frame #2: 0x00000001001ea33d umar`alloc::arc::{{impl}}::upgrade<(std::sync::mutex::Mutex<umar::chan::State<umar::shovel::Parcel<umar::video::Picture>>>, std::sync::condvar::Condvar)>(self=0x0000000107667060) at arc.rs:1039
    frame #3: 0x00000001000e1e0d umar`umar::chan::{{impl}}::send<umar::shovel::Parcel<umar::video::Picture>>(self=0x0000000107667060, t=Parcel<umar::video::Picture> @ 0x000070000bf3ddd0) at chan.rs:39

The implementation:

impl<T: Send> SyncSender<T> {
    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
        match self.state.upgrade() {
            Some(state) => {
                let &(ref mutex, ref cvar) = &*state;
                let mut state = mutex.lock().unwrap();

Well. The problem must lie elsewhere. I decided to run a plain Arc and I still got problems :confused:

* thread #2, name = 'vtc_dec', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
  * frame #0: 0x0000000100116ea3 umar`std::sync::mutex::{{impl}}::lock<umar::chan::State<umar::shovel::Parcel<umar::video::Picture>>>(self=0x646e6553636e7963) at mutex.rs:230
    frame #1: 0x00000001000e68fa umar`umar::chan::{{impl}}::send<umar::shovel::Parcel<umar::video::Picture>>(self=0x000000010420d060, t=Parcel<umar::video::Picture> @ 0x0000700010deddd0) at chan.rs:40

This isn’t a panic but rather a memory violation. If you really don’t have unsafe code then this would imply a bug.

What platform (OS and cpu) is it? Looks like windows on x86. What version of rustc? Can you show more of your code?

Hi Vitalyd!

It's on OSX. Thank you so much for answering. I think I worked out what's going on. It is my unsafe code that is the problem, but not exactly in this module.

My SyncSender was being held in a callback from C, that was used after rust dropped it. The problem was elsewhere, but showed up here.


Ah ok - then all is still right with the world :slight_smile: