]> git.lizzy.rs Git - rust.git/commitdiff
rustuv: Don't zero-out data on clones
authorAlex Crichton <alex@alexcrichton.com>
Sun, 29 Jun 2014 16:38:07 +0000 (09:38 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Sun, 29 Jun 2014 16:38:07 +0000 (09:38 -0700)
When cloning a stream, the data is already guaranteed to be in a consistent
state, so there's no need to perform a zeroing. This prevents segfaults as seen
in #15231

Closes #15231

src/librustuv/net.rs
src/librustuv/pipe.rs
src/librustuv/stream.rs
src/librustuv/tty.rs
src/libstd/io/net/tcp.rs
src/libstd/task.rs

index f1c37762129a3b442d8013e56e41bb47a804982e..cfed05bf5bebf80cd1285514c77ad570b3b3e948 100644 (file)
@@ -191,7 +191,7 @@ fn new_home(loop_: &Loop, home: HomeHandle) -> 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 @@ fn letdie(&mut self) -> Result<(), IoError> {
     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(),
index cff7e9d7738516f3a07964b2098d322ce3157247..1c53814ac2441731be8ecdf52b04c7ef1c665fc6 100644 (file)
@@ -67,7 +67,7 @@ pub fn new_home(loop_: &Loop, home: HomeHandle, ipc: bool) -> PipeWatcher {
             handle
         };
         PipeWatcher {
-            stream: StreamWatcher::new(handle),
+            stream: StreamWatcher::new(handle, true),
             home: home,
             defused: false,
             refcount: Refcount::new(),
@@ -131,7 +131,7 @@ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
 
     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(),
index f615e8287b3c7efb3b77daf3b07f3cd4f954c720..f6b9226588ca34572a7ac8e87172f7c77569d989 100644 (file)
@@ -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,
index 85ec0c75d53c8cd270a0fd9ef63005bbf08894c1..70b17db8dcfdd147a8a4616866bbf41b94f028a4 100644 (file)
@@ -56,7 +56,7 @@ pub fn new(io: &mut UvIoFactory, fd: libc::c_int, readable: bool)
         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,
         };
index b79e831ff61356e491d2d0174dc8eb5521581c88..baf53251fbe082e5e485ac2df70e64d7dc36c72d 100644 (file)
@@ -1360,4 +1360,44 @@ pub fn peer_name(addr: SocketAddr) {
 
         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();
+    })
 }
index 21d19deb0c7b6dcc7198dc7fbd931ea92f1bd98e..6492717d3ecafd95d8321818cd902c3b53af9ec4 100644 (file)
@@ -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);