Discovered by @Amanieu on IRLO. Quoting their report:
Arc::drop contains this code:
if self.inner().strong.fetch_sub(1, Release) != 1 {
return;
}
Once the current thread (Thread A) has decremented the reference count, Thread B could come in and free the ArcInner.
The problem becomes apparent when you look at the implementation of fetch_sub:
pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
unsafe { atomic_sub(self.v.get(), val, order) }
// HERE
}
Note the point marked HERE: at this point we have released our claim to the Arc (as in, decremented the count), which means that Thread B might have freed the ArcInner. However the &self still points to the strong reference count in the ArcInner -- so &self dangles.
Other instances of this:
Discovered by @Amanieu on IRLO. Quoting their report:
Arc::dropcontains this code:Once the current thread (Thread A) has decremented the reference count, Thread B could come in and free the
ArcInner.The problem becomes apparent when you look at the implementation of
fetch_sub:Note the point marked HERE: at this point we have released our claim to the
Arc(as in, decremented the count), which means that Thread B might have freed theArcInner. However the&selfstill points to the strong reference count in theArcInner-- so&selfdangles.Other instances of this: