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:
bors 2014-06-29 21:41:45 +00:00
commit a490871a6c
6 changed files with 51 additions and 8 deletions

View file

@ -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(),

View file

@ -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(),

View 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,

View file

@ -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,
};

View file

@ -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();
})
}

View 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);