Skip to content

Commit

Permalink
Be more defensive in pipes (#3098)
Browse files Browse the repository at this point in the history
  • Loading branch information
eholk committed Aug 3, 2012
1 parent 9e68966 commit 01ca0d1
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/libcore/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ fn swap_unwrap<T>(opt: &mut option<T>) -> T {
unwrap(util::replace(opt, none))
}

pure fn unwrap_expect<T>(-opt: option<T>, reason: ~str) -> T {
pure fn unwrap_expect<T>(-opt: option<T>, reason: &str) -> T {
//! As unwrap, but with a specified failure message.
if opt.is_none() { fail reason; }
if opt.is_none() { fail reason.to_unique(); }
unwrap(opt)
}

Expand Down
19 changes: 13 additions & 6 deletions src/libcore/pipes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ Fails if the sender closes the connection.
*/
fn recv<T: send, Tbuffer: send>(-p: recv_packet_buffered<T, Tbuffer>) -> T {
option::unwrap(try_recv(p))
option::unwrap_expect(try_recv(p), "connection closed")
}

/** Attempts to receive a message from a pipe.
Expand Down Expand Up @@ -391,10 +391,13 @@ fn try_recv<T: send, Tbuffer: send>(-p: recv_packet_buffered<T, Tbuffer>)
full {
let mut payload = none;
payload <-> p.payload;
p.header.blocked_task = none;

This comment has been minimized.

Copy link
@eholk

eholk Aug 3, 2012

Author Contributor

If we don't see #3098 show up again for a while, this line is probably the one that fixed it.

p.header.state = empty;
return some(option::unwrap(payload))
}
terminated {
// This assert detects when we've accidentally unsafely
// casted too big of a number to a state.
assert old_state == terminated;
return none;
}
Expand Down Expand Up @@ -428,10 +431,13 @@ fn sender_terminate<T: send>(p: *packet<T>) {
}
blocked {
// wake up the target
let target = p.header.blocked_task.get();
rustrt::task_signal_event(target,
ptr::addr_of(p.header) as *libc::c_void);

alt p.header.blocked_task {
some(target) =>
rustrt::task_signal_event(
target,
ptr::addr_of(p.header) as *libc::c_void),
none => { debug!{"receiver is already shutting down"} }
}
// The receiver will eventually clean up.
//unsafe { forget(p) }
}
Expand All @@ -448,6 +454,7 @@ fn sender_terminate<T: send>(p: *packet<T>) {
#[doc(hidden)]
fn receiver_terminate<T: send>(p: *packet<T>) {
let p = unsafe { &*p };
assert p.header.blocked_task == none;
alt swap_state_rel(p.header.state, terminated) {
empty {
// the sender will clean up
Expand Down Expand Up @@ -514,7 +521,7 @@ fn wait_many(pkts: &[*packet_header]) -> uint {

for pkts.each |p| { unsafe{ (*p).unblock()} }

debug!{"%?, %?", ready_packet, pkts[ready_packet]};
debug!("%?, %?", ready_packet, pkts[ready_packet]);

unsafe {
assert (*pkts[ready_packet]).state == full
Expand Down
3 changes: 3 additions & 0 deletions src/rt/rust_task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,9 @@ void
rust_task::signal_event(void *event) {
scoped_lock with(lifecycle_lock);

assert(task_state_blocked == state ||
task_state_running == state);

This comment has been minimized.

Copy link
@bblum

bblum Aug 3, 2012

Contributor

:)

This comment has been minimized.

Copy link
@eholk

eholk Aug 3, 2012

Author Contributor

@bblum interstingly, I didn't hit that assert once when I triggered the bug.

this->event = event;
event_reject = true;
if(task_state_blocked == state) {
Expand Down

0 comments on commit 01ca0d1

Please sign in to comment.