auto merge of #15252 : alexcrichton/rust/issue-15231, r=pcwalton
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
This commit is contained in:
commit
a490871a6c
6 changed files with 51 additions and 8 deletions
|
@ -191,7 +191,7 @@ impl TcpWatcher {
|
||||||
TcpWatcher {
|
TcpWatcher {
|
||||||
home: home,
|
home: home,
|
||||||
handle: handle,
|
handle: handle,
|
||||||
stream: StreamWatcher::new(handle),
|
stream: StreamWatcher::new(handle, true),
|
||||||
refcount: Refcount::new(),
|
refcount: Refcount::new(),
|
||||||
read_access: AccessTimeout::new(),
|
read_access: AccessTimeout::new(),
|
||||||
write_access: AccessTimeout::new(),
|
write_access: AccessTimeout::new(),
|
||||||
|
@ -278,7 +278,7 @@ impl rtio::RtioTcpStream for TcpWatcher {
|
||||||
fn clone(&self) -> Box<rtio::RtioTcpStream + Send> {
|
fn clone(&self) -> Box<rtio::RtioTcpStream + Send> {
|
||||||
box TcpWatcher {
|
box TcpWatcher {
|
||||||
handle: self.handle,
|
handle: self.handle,
|
||||||
stream: StreamWatcher::new(self.handle),
|
stream: StreamWatcher::new(self.handle, false),
|
||||||
home: self.home.clone(),
|
home: self.home.clone(),
|
||||||
refcount: self.refcount.clone(),
|
refcount: self.refcount.clone(),
|
||||||
read_access: self.read_access.clone(),
|
read_access: self.read_access.clone(),
|
||||||
|
|
|
@ -67,7 +67,7 @@ impl PipeWatcher {
|
||||||
handle
|
handle
|
||||||
};
|
};
|
||||||
PipeWatcher {
|
PipeWatcher {
|
||||||
stream: StreamWatcher::new(handle),
|
stream: StreamWatcher::new(handle, true),
|
||||||
home: home,
|
home: home,
|
||||||
defused: false,
|
defused: false,
|
||||||
refcount: Refcount::new(),
|
refcount: Refcount::new(),
|
||||||
|
@ -131,7 +131,7 @@ impl rtio::RtioPipe for PipeWatcher {
|
||||||
|
|
||||||
fn clone(&self) -> Box<rtio::RtioPipe + Send> {
|
fn clone(&self) -> Box<rtio::RtioPipe + Send> {
|
||||||
box PipeWatcher {
|
box PipeWatcher {
|
||||||
stream: StreamWatcher::new(self.stream.handle),
|
stream: StreamWatcher::new(self.stream.handle, false),
|
||||||
defused: false,
|
defused: false,
|
||||||
home: self.home.clone(),
|
home: self.home.clone(),
|
||||||
refcount: self.refcount.clone(),
|
refcount: self.refcount.clone(),
|
||||||
|
|
|
@ -59,8 +59,11 @@ impl StreamWatcher {
|
||||||
// will be manipulated on each of the methods called on this watcher.
|
// will be manipulated on each of the methods called on this watcher.
|
||||||
// Wrappers should ensure to always reset the field to an appropriate value
|
// Wrappers should ensure to always reset the field to an appropriate value
|
||||||
// if they rely on the field to perform an action.
|
// if they rely on the field to perform an action.
|
||||||
pub fn new(stream: *mut uvll::uv_stream_t) -> StreamWatcher {
|
pub fn new(stream: *mut uvll::uv_stream_t,
|
||||||
unsafe { uvll::set_data_for_uv_handle(stream, 0 as *mut int) }
|
init: bool) -> StreamWatcher {
|
||||||
|
if init {
|
||||||
|
unsafe { uvll::set_data_for_uv_handle(stream, 0 as *mut int) }
|
||||||
|
}
|
||||||
StreamWatcher {
|
StreamWatcher {
|
||||||
handle: stream,
|
handle: stream,
|
||||||
last_write_req: None,
|
last_write_req: None,
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl TtyWatcher {
|
||||||
let handle = UvHandle::alloc(None::<TtyWatcher>, uvll::UV_TTY);
|
let handle = UvHandle::alloc(None::<TtyWatcher>, uvll::UV_TTY);
|
||||||
let mut watcher = TtyWatcher {
|
let mut watcher = TtyWatcher {
|
||||||
tty: handle,
|
tty: handle,
|
||||||
stream: StreamWatcher::new(handle),
|
stream: StreamWatcher::new(handle, true),
|
||||||
home: io.make_handle(),
|
home: io.make_handle(),
|
||||||
fd: fd,
|
fd: fd,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1360,4 +1360,44 @@ mod test {
|
||||||
|
|
||||||
rx2.recv();
|
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();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -649,7 +649,7 @@ fn task_abort_no_kill_runtime() {
|
||||||
use std::io::timer;
|
use std::io::timer;
|
||||||
use mem;
|
use mem;
|
||||||
|
|
||||||
let mut tb = TaskBuilder::new();
|
let tb = TaskBuilder::new();
|
||||||
let rx = tb.try_future(proc() {});
|
let rx = tb.try_future(proc() {});
|
||||||
mem::drop(rx);
|
mem::drop(rx);
|
||||||
timer::sleep(1000);
|
timer::sleep(1000);
|
||||||
|
|
Loading…
Reference in a new issue