Fix a deadlock in channels, again.

This deadlock was caused when the channel was closed at just the right time, so
the extra `self.cnt.fetch_add` actually should have preserved the DISCONNECTED
state of the channel. by modifying this the channel entered a state such that
the port would never succeed in dropping.

This also moves the increment of self.steals until after the MAX_STEALS block.
The reason for this is that in 'fn recv()' the steals variable is decremented
immediately after the try_recv(), which could in theory set steals to -1 if it
was previously set to 0 in try_recv().

Closes #12340
This commit is contained in:
Alex Crichton 2014-02-17 13:59:25 -08:00
parent 47c31831a3
commit 9c05c1c236
2 changed files with 4 additions and 4 deletions

View File

@ -305,7 +305,6 @@ impl<T: Send> Packet<T> {
// See the discussion in the stream implementation for why we we
// might decrement steals.
Some(data) => {
self.steals += 1;
if self.steals > MAX_STEALS {
match self.cnt.swap(0, atomics::SeqCst) {
DISCONNECTED => {
@ -314,11 +313,12 @@ impl<T: Send> Packet<T> {
n => {
let m = cmp::min(n, self.steals);
self.steals -= m;
self.cnt.fetch_add(n - m, atomics::SeqCst);
self.bump(n - m);
}
}
assert!(self.steals >= 0);
}
self.steals += 1;
Ok(data)
}

View File

@ -213,7 +213,6 @@ impl<T: Send> Packet<T> {
// down as much as possible (without going negative), and then
// adding back in whatever we couldn't factor into steals.
Some(data) => {
self.steals += 1;
if self.steals > MAX_STEALS {
match self.cnt.swap(0, atomics::SeqCst) {
DISCONNECTED => {
@ -222,11 +221,12 @@ impl<T: Send> Packet<T> {
n => {
let m = cmp::min(n, self.steals);
self.steals -= m;
self.cnt.fetch_add(n - m, atomics::SeqCst);
self.bump(n - m);
}
}
assert!(self.steals >= 0);
}
self.steals += 1;
match data {
Data(t) => Ok(t),
GoUp(up) => Err(Upgraded(up)),