mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-30 18:53:39 +00:00
auto merge of #13619 : alexcrichton/rust/update-libuv, r=brson
This update brings a few months of changes, but primarily a fix for the following situation. When creating a handle to stdin, libuv used to set the stdin handle to nonblocking mode. This would end up affect this stdin handle across all processes that shared it, which mean that stdin become nonblocking for everyone using the same stdin. On linux, this also affected *stdout* because stdin/stdout roughly point at the same thing. This problem became apparent when running the test suite manually on a local computer. The stdtest suite (running with libgreen) would set stdout to nonblocking mode (as described above), and then the next test suite would always fail for a printing failure (because stdout was returning EAGAIN). This has been fixed upstream, joyent/libuv@342e8c, and this update pulls in this fix. This also brings us in line with a recently upstreamed libuv patch. Closes #12827 Closes #13336 Closes #13355
This commit is contained in:
commit
22e4e6adaf
@ -9,7 +9,6 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use libc::c_int;
|
|
||||||
use std::rt::rtio::{Callback, RemoteCallback};
|
use std::rt::rtio::{Callback, RemoteCallback};
|
||||||
use std::unstable::sync::Exclusive;
|
use std::unstable::sync::Exclusive;
|
||||||
|
|
||||||
@ -54,8 +53,7 @@ impl UvHandle<uvll::uv_async_t> for AsyncWatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn async_cb(handle: *uvll::uv_async_t, status: c_int) {
|
extern fn async_cb(handle: *uvll::uv_async_t) {
|
||||||
assert!(status == 0);
|
|
||||||
let payload: &mut Payload = unsafe {
|
let payload: &mut Payload = unsafe {
|
||||||
cast::transmute(uvll::get_data_for_uv_handle(handle))
|
cast::transmute(uvll::get_data_for_uv_handle(handle))
|
||||||
};
|
};
|
||||||
|
@ -12,7 +12,7 @@ use std::c_str::CString;
|
|||||||
use std::c_str;
|
use std::c_str;
|
||||||
use std::cast::transmute;
|
use std::cast::transmute;
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use libc::{c_int, c_char, c_void, size_t, ssize_t};
|
use libc::{c_int, c_char, c_void, ssize_t};
|
||||||
use libc;
|
use libc;
|
||||||
use std::rt::task::BlockedTask;
|
use std::rt::task::BlockedTask;
|
||||||
use std::io::{FileStat, IoError};
|
use std::io::{FileStat, IoError};
|
||||||
@ -86,14 +86,12 @@ impl FsRequest {
|
|||||||
} else {
|
} else {
|
||||||
offset + written as i64
|
offset + written as i64
|
||||||
};
|
};
|
||||||
|
let uvbuf = uvll::uv_buf_t {
|
||||||
|
base: buf.slice_from(written as uint).as_ptr(),
|
||||||
|
len: (buf.len() - written) as uvll::uv_buf_len_t,
|
||||||
|
};
|
||||||
match execute(|req, cb| unsafe {
|
match execute(|req, cb| unsafe {
|
||||||
uvll::uv_fs_write(loop_.handle,
|
uvll::uv_fs_write(loop_.handle, req, fd, &uvbuf, 1, offset, cb)
|
||||||
req,
|
|
||||||
fd,
|
|
||||||
buf.as_ptr().offset(written as int) as *c_void,
|
|
||||||
(buf.len() - written) as size_t,
|
|
||||||
offset,
|
|
||||||
cb)
|
|
||||||
}).map(|req| req.get_result()) {
|
}).map(|req| req.get_result()) {
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
Ok(n) => { written += n as uint; }
|
Ok(n) => { written += n as uint; }
|
||||||
@ -106,9 +104,11 @@ impl FsRequest {
|
|||||||
-> Result<int, UvError>
|
-> Result<int, UvError>
|
||||||
{
|
{
|
||||||
execute(|req, cb| unsafe {
|
execute(|req, cb| unsafe {
|
||||||
uvll::uv_fs_read(loop_.handle, req,
|
let uvbuf = uvll::uv_buf_t {
|
||||||
fd, buf.as_ptr() as *c_void,
|
base: buf.as_ptr(),
|
||||||
buf.len() as size_t, offset, cb)
|
len: buf.len() as uvll::uv_buf_len_t,
|
||||||
|
};
|
||||||
|
uvll::uv_fs_read(loop_.handle, req, fd, &uvbuf, 1, offset, cb)
|
||||||
}).map(|req| {
|
}).map(|req| {
|
||||||
req.get_result() as int
|
req.get_result() as int
|
||||||
})
|
})
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use libc::{c_int, c_void};
|
use libc::c_void;
|
||||||
|
|
||||||
use uvll;
|
use uvll;
|
||||||
use super::{Loop, UvHandle};
|
use super::{Loop, UvHandle};
|
||||||
@ -46,8 +46,7 @@ impl IdleWatcher {
|
|||||||
assert_eq!(uvll::uv_idle_start(handle, onetime_cb), 0)
|
assert_eq!(uvll::uv_idle_start(handle, onetime_cb), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn onetime_cb(handle: *uvll::uv_idle_t, status: c_int) {
|
extern fn onetime_cb(handle: *uvll::uv_idle_t) {
|
||||||
assert_eq!(status, 0);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = uvll::get_data_for_uv_handle(handle);
|
let data = uvll::get_data_for_uv_handle(handle);
|
||||||
let f: ~proc() = cast::transmute(data);
|
let f: ~proc() = cast::transmute(data);
|
||||||
@ -82,8 +81,7 @@ impl UvHandle<uvll::uv_idle_t> for IdleWatcher {
|
|||||||
fn uv_handle(&self) -> *uvll::uv_idle_t { self.handle }
|
fn uv_handle(&self) -> *uvll::uv_idle_t { self.handle }
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) {
|
extern fn idle_cb(handle: *uvll::uv_idle_t) {
|
||||||
assert_eq!(status, 0);
|
|
||||||
let idle: &mut IdleWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
|
let idle: &mut IdleWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
|
||||||
idle.callback.call();
|
idle.callback.call();
|
||||||
}
|
}
|
||||||
|
@ -255,10 +255,9 @@ impl TcpWatcher {
|
|||||||
n => Err(UvError(n))
|
n => Err(UvError(n))
|
||||||
};
|
};
|
||||||
|
|
||||||
extern fn timer_cb(handle: *uvll::uv_timer_t, status: c_int) {
|
extern fn timer_cb(handle: *uvll::uv_timer_t) {
|
||||||
// Don't close the corresponding tcp request, just wake up the task
|
// Don't close the corresponding tcp request, just wake up the task
|
||||||
// and let RAII take care of the pending watcher.
|
// and let RAII take care of the pending watcher.
|
||||||
assert_eq!(status, 0);
|
|
||||||
let cx: &mut Ctx = unsafe {
|
let cx: &mut Ctx = unsafe {
|
||||||
&mut *(uvll::get_data_for_uv_handle(handle) as *mut Ctx)
|
&mut *(uvll::get_data_for_uv_handle(handle) as *mut Ctx)
|
||||||
};
|
};
|
||||||
@ -599,8 +598,7 @@ impl rtio::RtioTcpAcceptor for TcpAcceptor {
|
|||||||
self.timeout_tx = Some(tx);
|
self.timeout_tx = Some(tx);
|
||||||
self.timeout_rx = Some(rx);
|
self.timeout_rx = Some(rx);
|
||||||
|
|
||||||
extern fn timer_cb(timer: *uvll::uv_timer_t, status: c_int) {
|
extern fn timer_cb(timer: *uvll::uv_timer_t) {
|
||||||
assert_eq!(status, 0);
|
|
||||||
let acceptor: &mut TcpAcceptor = unsafe {
|
let acceptor: &mut TcpAcceptor = unsafe {
|
||||||
&mut *(uvll::get_data_for_uv_handle(timer) as *mut TcpAcceptor)
|
&mut *(uvll::get_data_for_uv_handle(timer) as *mut TcpAcceptor)
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use libc::{c_void, c_int};
|
use libc::c_void;
|
||||||
use std::rt::task::BlockedTask;
|
use std::rt::task::BlockedTask;
|
||||||
use std::unstable::mutex::NativeMutex;
|
use std::unstable::mutex::NativeMutex;
|
||||||
use std::sync::arc::UnsafeArc;
|
use std::sync::arc::UnsafeArc;
|
||||||
@ -55,8 +55,7 @@ pub struct Queue {
|
|||||||
queue: UnsafeArc<State>,
|
queue: UnsafeArc<State>,
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn async_cb(handle: *uvll::uv_async_t, status: c_int) {
|
extern fn async_cb(handle: *uvll::uv_async_t) {
|
||||||
assert_eq!(status, 0);
|
|
||||||
let pool: &mut QueuePool = unsafe {
|
let pool: &mut QueuePool = unsafe {
|
||||||
cast::transmute(uvll::get_data_for_uv_handle(handle))
|
cast::transmute(uvll::get_data_for_uv_handle(handle))
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use libc::c_int;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rt::rtio::RtioTimer;
|
use std::rt::rtio::RtioTimer;
|
||||||
use std::rt::task::BlockedTask;
|
use std::rt::task::BlockedTask;
|
||||||
@ -137,9 +136,8 @@ impl RtioTimer for TimerWatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn timer_cb(handle: *uvll::uv_timer_t, status: c_int) {
|
extern fn timer_cb(handle: *uvll::uv_timer_t) {
|
||||||
let _f = ForbidSwitch::new("timer callback can't switch");
|
let _f = ForbidSwitch::new("timer callback can't switch");
|
||||||
assert_eq!(status, 0);
|
|
||||||
let timer: &mut TimerWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
|
let timer: &mut TimerWatcher = unsafe { UvHandle::from_uv_handle(&handle) };
|
||||||
|
|
||||||
match timer.action.take_unwrap() {
|
match timer.action.take_unwrap() {
|
||||||
|
@ -40,7 +40,7 @@ impl TtyWatcher {
|
|||||||
// - https://github.com/joyent/libuv/issues/982
|
// - https://github.com/joyent/libuv/issues/982
|
||||||
// - https://github.com/joyent/libuv/issues/988
|
// - https://github.com/joyent/libuv/issues/988
|
||||||
let guess = unsafe { uvll::guess_handle(fd) };
|
let guess = unsafe { uvll::guess_handle(fd) };
|
||||||
if readable && guess != uvll::UV_TTY as libc::c_int {
|
if guess != uvll::UV_TTY as libc::c_int {
|
||||||
return Err(UvError(uvll::EBADF));
|
return Err(UvError(uvll::EBADF));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ use libc::{O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY, S_IRUSR,
|
|||||||
use libc;
|
use libc;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rt::rtio;
|
use std::rt::rtio;
|
||||||
use std::rt::rtio::IoFactory;
|
use std::rt::rtio::{IoFactory, EventLoop};
|
||||||
use ai = std::io::net::addrinfo;
|
use ai = std::io::net::addrinfo;
|
||||||
|
|
||||||
#[cfg(test)] use std::unstable::run_in_bare_thread;
|
#[cfg(test)] use std::unstable::run_in_bare_thread;
|
||||||
@ -69,14 +69,20 @@ impl Drop for UvEventLoop {
|
|||||||
// the loop is free'd (use-after-free). We also must free the uv handle
|
// the loop is free'd (use-after-free). We also must free the uv handle
|
||||||
// after the loop has been closed because during the closing of the loop
|
// after the loop has been closed because during the closing of the loop
|
||||||
// the handle is required to be used apparently.
|
// the handle is required to be used apparently.
|
||||||
|
//
|
||||||
|
// Lastly, after we've closed the pool of handles we pump the event loop
|
||||||
|
// one last time to run any closing callbacks to make sure the loop
|
||||||
|
// shuts down cleanly.
|
||||||
let handle = self.uvio.handle_pool.get_ref().handle();
|
let handle = self.uvio.handle_pool.get_ref().handle();
|
||||||
drop(self.uvio.handle_pool.take());
|
drop(self.uvio.handle_pool.take());
|
||||||
|
self.run();
|
||||||
|
|
||||||
self.uvio.loop_.close();
|
self.uvio.loop_.close();
|
||||||
unsafe { uvll::free_handle(handle) }
|
unsafe { uvll::free_handle(handle) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl rtio::EventLoop for UvEventLoop {
|
impl EventLoop for UvEventLoop {
|
||||||
fn run(&mut self) {
|
fn run(&mut self) {
|
||||||
self.uvio.loop_.run();
|
self.uvio.loop_.run();
|
||||||
}
|
}
|
||||||
@ -110,7 +116,6 @@ impl rtio::EventLoop for UvEventLoop {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_callback_run_once() {
|
fn test_callback_run_once() {
|
||||||
use std::rt::rtio::EventLoop;
|
|
||||||
run_in_bare_thread(proc() {
|
run_in_bare_thread(proc() {
|
||||||
let mut event_loop = UvEventLoop::new();
|
let mut event_loop = UvEventLoop::new();
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
@ -212,8 +212,7 @@ impl uv_stat_t {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type uv_idle_cb = extern "C" fn(handle: *uv_idle_t,
|
pub type uv_idle_cb = extern "C" fn(handle: *uv_idle_t);
|
||||||
status: c_int);
|
|
||||||
pub type uv_alloc_cb = extern "C" fn(stream: *uv_stream_t,
|
pub type uv_alloc_cb = extern "C" fn(stream: *uv_stream_t,
|
||||||
suggested_size: size_t,
|
suggested_size: size_t,
|
||||||
buf: *mut uv_buf_t);
|
buf: *mut uv_buf_t);
|
||||||
@ -230,14 +229,12 @@ pub type uv_udp_recv_cb = extern "C" fn(handle: *uv_udp_t,
|
|||||||
pub type uv_close_cb = extern "C" fn(handle: *uv_handle_t);
|
pub type uv_close_cb = extern "C" fn(handle: *uv_handle_t);
|
||||||
pub type uv_walk_cb = extern "C" fn(handle: *uv_handle_t,
|
pub type uv_walk_cb = extern "C" fn(handle: *uv_handle_t,
|
||||||
arg: *c_void);
|
arg: *c_void);
|
||||||
pub type uv_async_cb = extern "C" fn(handle: *uv_async_t,
|
pub type uv_async_cb = extern "C" fn(handle: *uv_async_t);
|
||||||
status: c_int);
|
|
||||||
pub type uv_connect_cb = extern "C" fn(handle: *uv_connect_t,
|
pub type uv_connect_cb = extern "C" fn(handle: *uv_connect_t,
|
||||||
status: c_int);
|
status: c_int);
|
||||||
pub type uv_connection_cb = extern "C" fn(handle: *uv_connection_t,
|
pub type uv_connection_cb = extern "C" fn(handle: *uv_connection_t,
|
||||||
status: c_int);
|
status: c_int);
|
||||||
pub type uv_timer_cb = extern "C" fn(handle: *uv_timer_t,
|
pub type uv_timer_cb = extern "C" fn(handle: *uv_timer_t);
|
||||||
status: c_int);
|
|
||||||
pub type uv_write_cb = extern "C" fn(handle: *uv_write_t,
|
pub type uv_write_cb = extern "C" fn(handle: *uv_write_t,
|
||||||
status: c_int);
|
status: c_int);
|
||||||
pub type uv_getaddrinfo_cb = extern "C" fn(req: *uv_getaddrinfo_t,
|
pub type uv_getaddrinfo_cb = extern "C" fn(req: *uv_getaddrinfo_t,
|
||||||
@ -597,10 +594,12 @@ extern {
|
|||||||
flags: c_int, mode: c_int, cb: uv_fs_cb) -> c_int;
|
flags: c_int, mode: c_int, cb: uv_fs_cb) -> c_int;
|
||||||
pub fn uv_fs_unlink(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char,
|
pub fn uv_fs_unlink(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char,
|
||||||
cb: uv_fs_cb) -> c_int;
|
cb: uv_fs_cb) -> c_int;
|
||||||
pub fn uv_fs_write(l: *uv_loop_t, req: *uv_fs_t, fd: c_int, buf: *c_void,
|
pub fn uv_fs_write(l: *uv_loop_t, req: *uv_fs_t, fd: c_int,
|
||||||
len: size_t, offset: i64, cb: uv_fs_cb) -> c_int;
|
bufs: *uv_buf_t, nbufs: c_uint,
|
||||||
pub fn uv_fs_read(l: *uv_loop_t, req: *uv_fs_t, fd: c_int, buf: *c_void,
|
offset: i64, cb: uv_fs_cb) -> c_int;
|
||||||
len: size_t, offset: i64, cb: uv_fs_cb) -> c_int;
|
pub fn uv_fs_read(l: *uv_loop_t, req: *uv_fs_t, fd: c_int,
|
||||||
|
bufs: *uv_buf_t, nbufs: c_uint,
|
||||||
|
offset: i64, cb: uv_fs_cb) -> c_int;
|
||||||
pub fn uv_fs_close(l: *uv_loop_t, req: *uv_fs_t, fd: c_int,
|
pub fn uv_fs_close(l: *uv_loop_t, req: *uv_fs_t, fd: c_int,
|
||||||
cb: uv_fs_cb) -> c_int;
|
cb: uv_fs_cb) -> c_int;
|
||||||
pub fn uv_fs_stat(l: *uv_loop_t, req: *uv_fs_t, path: *c_char,
|
pub fn uv_fs_stat(l: *uv_loop_t, req: *uv_fs_t, path: *c_char,
|
||||||
|
@ -364,7 +364,7 @@ mod tests {
|
|||||||
use option::{Some, None};
|
use option::{Some, None};
|
||||||
use str::{Str,StrSlice};
|
use str::{Str,StrSlice};
|
||||||
use strbuf::StrBuf;
|
use strbuf::StrBuf;
|
||||||
use slice::{Vector, ImmutableVector, OwnedVector};
|
use slice::{Vector, ImmutableVector};
|
||||||
use self::test::Bencher;
|
use self::test::Bencher;
|
||||||
|
|
||||||
use super::super::Hash;
|
use super::super::Hash;
|
||||||
|
@ -67,9 +67,9 @@ mod imp {
|
|||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use option::{Option, Some, None};
|
use option::{Option, Some, None};
|
||||||
use iter::Iterator;
|
use iter::Iterator;
|
||||||
use str::StrSlice;
|
|
||||||
use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
|
||||||
use mem;
|
use mem;
|
||||||
|
#[cfg(not(test))] use str::StrSlice;
|
||||||
#[cfg(not(test))] use ptr::RawPtr;
|
#[cfg(not(test))] use ptr::RawPtr;
|
||||||
|
|
||||||
static mut global_args_ptr: uint = 0;
|
static mut global_args_ptr: uint = 0;
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 800b56fe6af21ffd8e56aee8cf12dd758f5bbdf1
|
Subproject commit 43495892ded622de51eba7362c5ffae1ed50c9cc
|
@ -1,2 +1,2 @@
|
|||||||
# Change the contents of this file to force a full rebuild of libuv
|
# Change the contents of this file to force a full rebuild of libuv
|
||||||
2014-02-16
|
2014-04-18
|
||||||
|
Loading…
Reference in New Issue
Block a user