]> git.lizzy.rs Git - rust.git/commitdiff
Be more defensive in pipes (#3098)
authorEric Holk <eric.holk@gmail.com>
Fri, 3 Aug 2012 18:43:10 +0000 (11:43 -0700)
committerEric Holk <eric.holk@gmail.com>
Fri, 3 Aug 2012 19:04:18 +0000 (12:04 -0700)
src/libcore/option.rs
src/libcore/pipes.rs
src/rt/rust_task.cpp

index bb5cca90cd09464cdb772ea380ac9eb3115962af..935d22fbaae4a04572285122f78e6fa897c087b0 100644 (file)
@@ -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)
 }
 
index c1f39a9470ca686279c05a35f0b5bc1889d5e837..6df6df9a6bb20249cb50b453b50fb108b1d3f4d0 100644 (file)
@@ -343,7 +343,7 @@ fn send<T: send, Tbuffer: send>(-p: send_packet_buffered<T, Tbuffer>,
 
 */
 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.
@@ -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;
             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;
           }
@@ -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) }
       }
@@ -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
@@ -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
index 061e87ebff82d32f129eb9119a2b60ec594ba166..ad2e8a71ae5f58ecf7b930ddc21fd545148d3d4b 100644 (file)
@@ -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->event = event;
     event_reject = true;
     if(task_state_blocked == state) {