Skip to content

Commit cc20d60

Browse files
committed
rollup merge of rust-lang#19661: alexcrichton/mutex-result
All of the current std::sync primitives have poisoning enable which means that when a task fails inside of a write-access lock then all future attempts to acquire the lock will fail. This strategy ensures that stale data whose invariants are possibly not upheld are never viewed by other tasks to help propagate unexpected panics (bugs in a program) among tasks. Currently there is no way to test whether a mutex or rwlock is poisoned. One method would be to duplicate all the methods with a sister foo_catch function, for example. This pattern is, however, against our [error guidelines][errors]. As a result, this commit exposes the fact that a task has failed internally through the return value of a `Result`. [errors]: https://github.com/rust-lang/rfcs/blob/master/text/0236-error-conventions.md#do-not-provide-both-result-and-fail-variants All methods now return a `LockResult<T>` or a `TryLockResult<T>` which communicates whether the lock was poisoned or not. In a `LockResult`, both the `Ok` and `Err` variants contains the `MutexGuard<T>` that is being returned in order to allow access to the data if poisoning is not desired. This also means that the lock is *always* held upon returning from `.lock()`. A new type, `PoisonError`, was added with one method `into_guard` which can consume the assertion that a lock is poisoned to gain access to the underlying data. This is a breaking change because the signatures of these methods have changed, often incompatible ways. One major difference is that the `wait` methods on a condition variable now consume the guard and return it in as a `LockResult` to indicate whether the lock was poisoned while waiting. Most code can be updated by calling `.unwrap()` on the return value of `.lock()`. [breaking-change]
2 parents 94d82c1 + 35e63e3 commit cc20d60

20 files changed

+540
-390
lines changed

src/doc/intro.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ fn main() {
483483
for i in range(0u, 3u) {
484484
let number = numbers.clone();
485485
Thread::spawn(move || {
486-
let mut array = number.lock();
486+
let mut array = number.lock().unwrap();
487487
488488
(*array)[i] += 1;
489489

src/liballoc/arc.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
//! let five = five.clone();
5959
//!
6060
//! Thread::spawn(move || {
61-
//! let mut number = five.lock();
61+
//! let mut number = five.lock().unwrap();
6262
//!
6363
//! *number += 1;
6464
//!
@@ -722,7 +722,7 @@ mod tests {
722722

723723
let a = Arc::new(Cycle { x: Mutex::new(None) });
724724
let b = a.clone().downgrade();
725-
*a.x.lock() = Some(b);
725+
*a.x.lock().unwrap() = Some(b);
726726

727727
// hopefully we don't double-free (or leak)...
728728
}

src/librustc_trans/back/write.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ impl SharedEmitter {
9898
}
9999

100100
fn dump(&mut self, handler: &Handler) {
101-
let mut buffer = self.buffer.lock();
101+
let mut buffer = self.buffer.lock().unwrap();
102102
for diag in buffer.iter() {
103103
match diag.code {
104104
Some(ref code) => {
@@ -123,7 +123,7 @@ impl Emitter for SharedEmitter {
123123
msg: &str, code: Option<&str>, lvl: Level) {
124124
assert!(cmsp.is_none(), "SharedEmitter doesn't support spans");
125125

126-
self.buffer.lock().push(Diagnostic {
126+
self.buffer.lock().unwrap().push(Diagnostic {
127127
msg: msg.to_string(),
128128
code: code.map(|s| s.to_string()),
129129
lvl: lvl,
@@ -915,7 +915,7 @@ fn run_work_multithreaded(sess: &Session,
915915

916916
loop {
917917
// Avoid holding the lock for the entire duration of the match.
918-
let maybe_work = work_items_arc.lock().pop();
918+
let maybe_work = work_items_arc.lock().unwrap().pop();
919919
match maybe_work {
920920
Some(work) => {
921921
execute_work_item(&cgcx, work);

src/libstd/comm/shared.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl<T: Send> Packet<T> {
8686
// and that could cause problems on platforms where it is
8787
// represented by opaque data structure
8888
pub fn postinit_lock(&self) -> MutexGuard<()> {
89-
self.select_lock.lock()
89+
self.select_lock.lock().unwrap()
9090
}
9191

9292
// This function is used at the creation of a shared packet to inherit a
@@ -435,7 +435,7 @@ impl<T: Send> Packet<T> {
435435
// about looking at and dealing with to_wake. Once we have acquired the
436436
// lock, we are guaranteed that inherit_blocker is done.
437437
{
438-
let _guard = self.select_lock.lock();
438+
let _guard = self.select_lock.lock().unwrap();
439439
}
440440

441441
// Like the stream implementation, we want to make sure that the count

src/libstd/comm/sync.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ fn wait<'a, 'b, T: Send>(lock: &'a Mutex<State<T>>,
121121
NoneBlocked => {}
122122
_ => unreachable!(),
123123
}
124-
drop(guard); // unlock
125-
wait_token.wait(); // block
126-
lock.lock() // relock
124+
drop(guard); // unlock
125+
wait_token.wait(); // block
126+
lock.lock().unwrap() // relock
127127
}
128128

129129
/// Wakes up a thread, dropping the lock at the correct time
@@ -161,7 +161,7 @@ impl<T: Send> Packet<T> {
161161
fn acquire_send_slot(&self) -> MutexGuard<State<T>> {
162162
let mut node = Node { token: None, next: 0 as *mut Node };
163163
loop {
164-
let mut guard = self.lock.lock();
164+
let mut guard = self.lock.lock().unwrap();
165165
// are we ready to go?
166166
if guard.disconnected || guard.buf.size() < guard.buf.cap() {
167167
return guard;
@@ -202,7 +202,7 @@ impl<T: Send> Packet<T> {
202202
}
203203

204204
pub fn try_send(&self, t: T) -> Result<(), super::TrySendError<T>> {
205-
let mut guard = self.lock.lock();
205+
let mut guard = self.lock.lock().unwrap();
206206
if guard.disconnected {
207207
Err(super::RecvDisconnected(t))
208208
} else if guard.buf.size() == guard.buf.cap() {
@@ -239,7 +239,7 @@ impl<T: Send> Packet<T> {
239239
// When reading this, remember that there can only ever be one receiver at
240240
// time.
241241
pub fn recv(&self) -> Result<T, ()> {
242-
let mut guard = self.lock.lock();
242+
let mut guard = self.lock.lock().unwrap();
243243

244244
// Wait for the buffer to have something in it. No need for a while loop
245245
// because we're the only receiver.
@@ -258,7 +258,7 @@ impl<T: Send> Packet<T> {
258258
}
259259

260260
pub fn try_recv(&self) -> Result<T, Failure> {
261-
let mut guard = self.lock.lock();
261+
let mut guard = self.lock.lock().unwrap();
262262

263263
// Easy cases first
264264
if guard.disconnected { return Err(Disconnected) }
@@ -315,7 +315,7 @@ impl<T: Send> Packet<T> {
315315
}
316316

317317
// Not much to do other than wake up a receiver if one's there
318-
let mut guard = self.lock.lock();
318+
let mut guard = self.lock.lock().unwrap();
319319
if guard.disconnected { return }
320320
guard.disconnected = true;
321321
match mem::replace(&mut guard.blocker, NoneBlocked) {
@@ -326,7 +326,7 @@ impl<T: Send> Packet<T> {
326326
}
327327

328328
pub fn drop_port(&self) {
329-
let mut guard = self.lock.lock();
329+
let mut guard = self.lock.lock().unwrap();
330330

331331
if guard.disconnected { return }
332332
guard.disconnected = true;
@@ -372,14 +372,14 @@ impl<T: Send> Packet<T> {
372372
// If Ok, the value is whether this port has data, if Err, then the upgraded
373373
// port needs to be checked instead of this one.
374374
pub fn can_recv(&self) -> bool {
375-
let guard = self.lock.lock();
375+
let guard = self.lock.lock().unwrap();
376376
guard.disconnected || guard.buf.size() > 0
377377
}
378378

379379
// Attempts to start selection on this port. This can either succeed or fail
380380
// because there is data waiting.
381381
pub fn start_selection(&self, token: SignalToken) -> StartResult {
382-
let mut guard = self.lock.lock();
382+
let mut guard = self.lock.lock().unwrap();
383383
if guard.disconnected || guard.buf.size() > 0 {
384384
Abort
385385
} else {
@@ -397,7 +397,7 @@ impl<T: Send> Packet<T> {
397397
//
398398
// The return value indicates whether there's data on this port.
399399
pub fn abort_selection(&self) -> bool {
400-
let mut guard = self.lock.lock();
400+
let mut guard = self.lock.lock().unwrap();
401401
match mem::replace(&mut guard.blocker, NoneBlocked) {
402402
NoneBlocked => true,
403403
BlockedSender(token) => {
@@ -413,7 +413,7 @@ impl<T: Send> Packet<T> {
413413
impl<T: Send> Drop for Packet<T> {
414414
fn drop(&mut self) {
415415
assert_eq!(self.channels.load(atomic::SeqCst), 0);
416-
let mut guard = self.lock.lock();
416+
let mut guard = self.lock.lock().unwrap();
417417
assert!(guard.queue.dequeue().is_none());
418418
assert!(guard.canceled.is_none());
419419
}

src/libstd/io/stdio.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ impl StdinReader {
146146
/// ```
147147
pub fn lock<'a>(&'a mut self) -> StdinReaderGuard<'a> {
148148
StdinReaderGuard {
149-
inner: self.inner.lock()
149+
inner: self.inner.lock().unwrap()
150150
}
151151
}
152152

@@ -155,53 +155,53 @@ impl StdinReader {
155155
/// The read is performed atomically - concurrent read calls in other
156156
/// threads will not interleave with this one.
157157
pub fn read_line(&mut self) -> IoResult<String> {
158-
self.inner.lock().0.read_line()
158+
self.inner.lock().unwrap().0.read_line()
159159
}
160160

161161
/// Like `Buffer::read_until`.
162162
///
163163
/// The read is performed atomically - concurrent read calls in other
164164
/// threads will not interleave with this one.
165165
pub fn read_until(&mut self, byte: u8) -> IoResult<Vec<u8>> {
166-
self.inner.lock().0.read_until(byte)
166+
self.inner.lock().unwrap().0.read_until(byte)
167167
}
168168

169169
/// Like `Buffer::read_char`.
170170
///
171171
/// The read is performed atomically - concurrent read calls in other
172172
/// threads will not interleave with this one.
173173
pub fn read_char(&mut self) -> IoResult<char> {
174-
self.inner.lock().0.read_char()
174+
self.inner.lock().unwrap().0.read_char()
175175
}
176176
}
177177

178178
impl Reader for StdinReader {
179179
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
180-
self.inner.lock().0.read(buf)
180+
self.inner.lock().unwrap().0.read(buf)
181181
}
182182

183183
// We have to manually delegate all of these because the default impls call
184184
// read more than once and we don't want those calls to interleave (or
185185
// incur the costs of repeated locking).
186186

187187
fn read_at_least(&mut self, min: uint, buf: &mut [u8]) -> IoResult<uint> {
188-
self.inner.lock().0.read_at_least(min, buf)
188+
self.inner.lock().unwrap().0.read_at_least(min, buf)
189189
}
190190

191191
fn push_at_least(&mut self, min: uint, len: uint, buf: &mut Vec<u8>) -> IoResult<uint> {
192-
self.inner.lock().0.push_at_least(min, len, buf)
192+
self.inner.lock().unwrap().0.push_at_least(min, len, buf)
193193
}
194194

195195
fn read_to_end(&mut self) -> IoResult<Vec<u8>> {
196-
self.inner.lock().0.read_to_end()
196+
self.inner.lock().unwrap().0.read_to_end()
197197
}
198198

199199
fn read_le_uint_n(&mut self, nbytes: uint) -> IoResult<u64> {
200-
self.inner.lock().0.read_le_uint_n(nbytes)
200+
self.inner.lock().unwrap().0.read_le_uint_n(nbytes)
201201
}
202202

203203
fn read_be_uint_n(&mut self, nbytes: uint) -> IoResult<u64> {
204-
self.inner.lock().0.read_be_uint_n(nbytes)
204+
self.inner.lock().unwrap().0.read_be_uint_n(nbytes)
205205
}
206206
}
207207

src/libstd/sync/barrier.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,15 @@ impl Barrier {
6969
/// Barriers are re-usable after all threads have rendezvoused once, and can
7070
/// be used continuously.
7171
pub fn wait(&self) {
72-
let mut lock = self.lock.lock();
72+
let mut lock = self.lock.lock().unwrap();
7373
let local_gen = lock.generation_id;
7474
lock.count += 1;
7575
if lock.count < self.num_threads {
7676
// We need a while loop to guard against spurious wakeups.
7777
// http://en.wikipedia.org/wiki/Spurious_wakeup
7878
while local_gen == lock.generation_id &&
7979
lock.count < self.num_threads {
80-
self.cvar.wait(&lock);
80+
lock = self.cvar.wait(lock).unwrap();
8181
}
8282
} else {
8383
lock.count = 0;

0 commit comments

Comments
 (0)