about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustuv/net.rs4
-rw-r--r--src/librustuv/pipe.rs4
-rw-r--r--src/librustuv/stream.rs7
-rw-r--r--src/librustuv/tty.rs2
-rw-r--r--src/libstd/io/net/tcp.rs40
-rw-r--r--src/libstd/task.rs2
6 files changed, 51 insertions, 8 deletions
diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs
index f1c37762129..cfed05bf5be 100644
--- a/src/librustuv/net.rs
+++ b/src/librustuv/net.rs
@@ -191,7 +191,7 @@ impl TcpWatcher {
         TcpWatcher {
             home: home,
             handle: handle,
-            stream: StreamWatcher::new(handle),
+            stream: StreamWatcher::new(handle, true),
             refcount: Refcount::new(),
             read_access: AccessTimeout::new(),
             write_access: AccessTimeout::new(),
@@ -278,7 +278,7 @@ impl rtio::RtioTcpStream for TcpWatcher {
     fn clone(&self) -> Box<rtio::RtioTcpStream + Send> {
         box TcpWatcher {
             handle: self.handle,
-            stream: StreamWatcher::new(self.handle),
+            stream: StreamWatcher::new(self.handle, false),
             home: self.home.clone(),
             refcount: self.refcount.clone(),
             read_access: self.read_access.clone(),
diff --git a/src/librustuv/pipe.rs b/src/librustuv/pipe.rs
index cff7e9d7738..1c53814ac24 100644
--- a/src/librustuv/pipe.rs
+++ b/src/librustuv/pipe.rs
@@ -67,7 +67,7 @@ impl PipeWatcher {
             handle
         };
         PipeWatcher {
-            stream: StreamWatcher::new(handle),
+            stream: StreamWatcher::new(handle, true),
             home: home,
             defused: false,
             refcount: Refcount::new(),
@@ -131,7 +131,7 @@ impl rtio::RtioPipe for PipeWatcher {
 
     fn clone(&self) -> Box<rtio::RtioPipe + Send> {
         box PipeWatcher {
-            stream: StreamWatcher::new(self.stream.handle),
+            stream: StreamWatcher::new(self.stream.handle, false),
             defused: false,
             home: self.home.clone(),
             refcount: self.refcount.clone(),
diff --git a/src/librustuv/stream.rs b/src/librustuv/stream.rs
index f615e8287b3..f6b9226588c 100644
--- a/src/librustuv/stream.rs
+++ b/src/librustuv/stream.rs
@@ -59,8 +59,11 @@ impl StreamWatcher {
     // will be manipulated on each of the methods called on this watcher.
     // Wrappers should ensure to always reset the field to an appropriate value
     // if they rely on the field to perform an action.
-    pub fn new(stream: *mut uvll::uv_stream_t) -> StreamWatcher {
-        unsafe { uvll::set_data_for_uv_handle(stream, 0 as *mut int) }
+    pub fn new(stream: *mut uvll::uv_stream_t,
+               init: bool) -> StreamWatcher {
+        if init {
+            unsafe { uvll::set_data_for_uv_handle(stream, 0 as *mut int) }
+        }
         StreamWatcher {
             handle: stream,
             last_write_req: None,
diff --git a/src/librustuv/tty.rs b/src/librustuv/tty.rs
index 85ec0c75d53..70b17db8dcf 100644
--- a/src/librustuv/tty.rs
+++ b/src/librustuv/tty.rs
@@ -56,7 +56,7 @@ impl TtyWatcher {
         let handle = UvHandle::alloc(None::<TtyWatcher>, uvll::UV_TTY);
         let mut watcher = TtyWatcher {
             tty: handle,
-            stream: StreamWatcher::new(handle),
+            stream: StreamWatcher::new(handle, true),
             home: io.make_handle(),
             fd: fd,
         };
diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs
index b79e831ff61..baf53251fbe 100644
--- a/src/libstd/io/net/tcp.rs
+++ b/src/libstd/io/net/tcp.rs
@@ -1360,4 +1360,44 @@ mod test {
 
         rx2.recv();
     })
+
+    iotest!(fn clone_while_reading() {
+        let addr = next_test_ip6();
+        let listen = TcpListener::bind(addr.ip.to_str().as_slice(), addr.port);
+        let mut accept = listen.listen().unwrap();
+
+        // Enqueue a task to write to a socket
+        let (tx, rx) = channel();
+        let (txdone, rxdone) = channel();
+        let txdone2 = txdone.clone();
+        spawn(proc() {
+            let mut tcp = TcpStream::connect(addr.ip.to_str().as_slice(),
+                                             addr.port).unwrap();
+            rx.recv();
+            tcp.write_u8(0).unwrap();
+            txdone2.send(());
+        });
+
+        // Spawn off a reading clone
+        let tcp = accept.accept().unwrap();
+        let tcp2 = tcp.clone();
+        let txdone3 = txdone.clone();
+        spawn(proc() {
+            let mut tcp2 = tcp2;
+            tcp2.read_u8().unwrap();
+            txdone3.send(());
+        });
+
+        // Try to ensure that the reading clone is indeed reading
+        for _ in range(0i, 50) {
+            ::task::deschedule();
+        }
+
+        // clone the handle again while it's reading, then let it finish the
+        // read.
+        let _ = tcp.clone();
+        tx.send(());
+        rxdone.recv();
+        rxdone.recv();
+    })
 }
diff --git a/src/libstd/task.rs b/src/libstd/task.rs
index 21d19deb0c7..6492717d3ec 100644
--- a/src/libstd/task.rs
+++ b/src/libstd/task.rs
@@ -649,7 +649,7 @@ fn task_abort_no_kill_runtime() {
     use std::io::timer;
     use mem;
 
-    let mut tb = TaskBuilder::new();
+    let tb = TaskBuilder::new();
     let rx = tb.try_future(proc() {});
     mem::drop(rx);
     timer::sleep(1000);