about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-05-15 11:51:24 -0700
committerBrian Anderson <banderson@mozilla.com>2012-05-15 16:13:42 -0700
commitc424b7f847bbec50d01b00a89e044d80b8eb59f8 (patch)
tree138ad7b123d1737556634abc66879d5485367265
parent7277cd71984e6a09bc2f8a8a828a5e213b485d00 (diff)
downloadrust-c424b7f847bbec50d01b00a89e044d80b8eb59f8.tar.gz
rust-c424b7f847bbec50d01b00a89e044d80b8eb59f8.zip
core: Don't fail during port dtor
-rw-r--r--src/libcore/comm.rs57
1 files changed, 40 insertions, 17 deletions
diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs
index 8ee09a2a646..f91dfa06ff3 100644
--- a/src/libcore/comm.rs
+++ b/src/libcore/comm.rs
@@ -93,25 +93,27 @@ fn listen<T: send, U>(f: fn(chan<T>) -> U) -> U {
     f(po.chan())
 }
 
-resource port_ptr<T: send>(po: *rust_port) {
-    // Once the port is detached it's guaranteed not to receive further
-    // messages
-    let yield = 0u;
-    let yieldp = ptr::addr_of(yield);
-    rustrt::rust_port_begin_detach(po, yieldp);
-    if yield != 0u {
-        // Need to wait for the port to be detached
-        // FIXME: If this fails then we're going to leave our port
-        // in a bogus state. (Issue #1988)
-        task::yield();
-    }
-    rustrt::rust_port_end_detach(po);
+resource port_ptr<T: send>(po: *rust_port) unsafe {
+    task::unkillable {||
+        // Once the port is detached it's guaranteed not to receive further
+        // messages
+        let yield = 0u;
+        let yieldp = ptr::addr_of(yield);
+        rustrt::rust_port_begin_detach(po, yieldp);
+        if yield != 0u {
+            // Need to wait for the port to be detached
+            // FIXME: If this fails then we're going to leave our port
+            // in a bogus state. (Issue #1988)
+            task::yield();
+        }
+        rustrt::rust_port_end_detach(po);
 
-    // Drain the port so that all the still-enqueued items get dropped
-    while rustrt::rust_port_size(po) > 0u {
-       recv_::<T>(po);
+        // Drain the port so that all the still-enqueued items get dropped
+        while rustrt::rust_port_size(po) > 0u {
+            recv_::<T>(po);
+        }
+        rustrt::del_port(po);
     }
-    rustrt::del_port(po);
 }
 
 #[doc = "
@@ -458,4 +460,25 @@ fn test_listen() {
         }
         assert parent.recv() == "oatmeal-salad";
     }
+}
+
+#[test]
+#[ignore(cfg(target_os="win32"))]
+fn test_port_detach_fail() {
+    iter::repeat(100u) {||
+        let builder = task::builder();
+        task::unsupervise(builder);
+        task::run(builder) {||
+            let po = port();
+            let ch = po.chan();
+
+            task::spawn {||
+                fail;
+            }
+
+            task::spawn {||
+                ch.send(());
+            }
+        }
+    }
 }
\ No newline at end of file