Bug in Weak::upgrade?


#1

Hi!

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();
...

#2

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

#3

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?


#4

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.

Thanks!


#5

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