Skip to content

Commit e38a89d

Browse files
committed
Fix usage of libuv for windows
1 parent c5fdd69 commit e38a89d

File tree

11 files changed

+89
-42
lines changed

11 files changed

+89
-42
lines changed

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
branch = master
55
[submodule "src/libuv"]
66
path = src/libuv
7-
url = https://github.com/joyent/libuv.git
7+
url = https://github.com/alexcrichton/libuv.git
88
branch = master
99
[submodule "src/gyp"]
1010
path = src/gyp

src/librustuv/net.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,7 @@ mod test {
883883
}
884884
885885
#[test]
886+
#[ignore(cfg(windows))] // FIXME(#10102) server never sees second packet
886887
fn test_udp_twice() {
887888
let server_addr = next_test_ip4();
888889
let client_addr = next_test_ip4();

src/librustuv/pipe.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ mod tests {
251251
use super::super::local_loop;
252252

253253
#[test]
254+
#[ignore(cfg(windows))] // FIXME(#10386): how windows pipes work
254255
fn connect_err() {
255256
match PipeWatcher::connect(local_loop(), &"path/to/nowhere".to_c_str()) {
256257
Ok(*) => fail!(),
@@ -259,6 +260,7 @@ mod tests {
259260
}
260261

261262
#[test]
263+
#[ignore(cfg(windows))] // FIXME(#10386): how windows pipes work
262264
fn bind_err() {
263265
match PipeListener::bind(local_loop(), &"path/to/nowhere".to_c_str()) {
264266
Ok(*) => fail!(),
@@ -267,6 +269,7 @@ mod tests {
267269
}
268270

269271
#[test]
272+
#[ignore(cfg(windows))] // FIXME(#10386): how windows pipes work
270273
fn bind() {
271274
let p = next_test_unix().to_c_str();
272275
match PipeListener::bind(local_loop(), &p) {
@@ -276,13 +279,15 @@ mod tests {
276279
}
277280

278281
#[test] #[should_fail]
282+
#[ignore(cfg(windows))] // FIXME(#10386): how windows pipes work
279283
fn bind_fail() {
280284
let p = next_test_unix().to_c_str();
281285
let _w = PipeListener::bind(local_loop(), &p).unwrap();
282286
fail!();
283287
}
284288

285289
#[test]
290+
#[ignore(cfg(windows))] // FIXME(#10386): how windows pipes work
286291
fn connect() {
287292
let path = next_test_unix();
288293
let path2 = path.clone();
@@ -308,6 +313,7 @@ mod tests {
308313
}
309314

310315
#[test] #[should_fail]
316+
#[ignore(cfg(windows))] // FIXME(#10386): how windows pipes work
311317
fn connect_fail() {
312318
let path = next_test_unix();
313319
let path2 = path.clone();

src/librustuv/process.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,6 @@ impl Drop for Process {
232232
fn drop(&mut self) {
233233
let _m = self.fire_homing_missile();
234234
assert!(self.to_wake.is_none());
235-
self.close_async_();
235+
self.close();
236236
}
237237
}

src/librustuv/signal.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,21 @@ pub struct SignalWatcher {
3030
impl SignalWatcher {
3131
pub fn new(loop_: &mut Loop, signum: Signum,
3232
channel: SharedChan<Signum>) -> Result<~SignalWatcher, UvError> {
33-
let handle = UvHandle::alloc(None::<SignalWatcher>, uvll::UV_SIGNAL);
33+
let s = ~SignalWatcher {
34+
handle: UvHandle::alloc(None::<SignalWatcher>, uvll::UV_SIGNAL),
35+
home: get_handle_to_current_scheduler!(),
36+
channel: channel,
37+
signal: signum,
38+
};
3439
assert_eq!(unsafe {
35-
uvll::uv_signal_init(loop_.handle, handle)
36-
40+
uvll::uv_signal_init(loop_.handle, s.handle)
3741
}, 0);
3842

39-
match unsafe { uvll::uv_signal_start(handle, signal_cb, signum as c_int) } {
40-
0 => {
41-
let s = ~SignalWatcher {
42-
handle: handle,
43-
home: get_handle_to_current_scheduler!(),
44-
channel: channel,
45-
signal: signum,
46-
};
47-
Ok(s.install())
48-
}
49-
n => {
50-
unsafe { uvll::free_handle(handle) }
51-
Err(UvError(n))
52-
}
43+
match unsafe {
44+
uvll::uv_signal_start(s.handle, signal_cb, signum as c_int)
45+
} {
46+
0 => Ok(s.install()),
47+
n => Err(UvError(n)),
5348
}
5449

5550
}

src/librustuv/timer.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,27 @@ impl UvHandle<uvll::uv_timer_t> for TimerWatcher {
6767

6868
impl RtioTimer for TimerWatcher {
6969
fn sleep(&mut self, msecs: u64) {
70-
let (_m, sched) = self.fire_homing_missile_sched();
70+
// As with all of the below functions, we must be extra careful when
71+
// destroying the previous action. If the previous action was a channel,
72+
// destroying it could invoke a context switch. For these situtations,
73+
// we must temporarily un-home ourselves, then destroy the action, and
74+
// then re-home again.
75+
let missile = self.fire_homing_missile();
76+
self.stop();
77+
let _missile = match util::replace(&mut self.action, None) {
78+
None => missile, // no need to do a homing dance
79+
Some(action) => {
80+
util::ignore(missile); // un-home ourself
81+
util::ignore(action); // destroy the previous action
82+
self.fire_homing_missile() // re-home ourself
83+
}
84+
};
7185

7286
// If the descheduling operation unwinds after the timer has been
7387
// started, then we need to call stop on the timer.
7488
let _f = ForbidUnwind::new("timer");
7589

90+
let sched: ~Scheduler = Local::take();
7691
do sched.deschedule_running_task_and_then |_sched, task| {
7792
self.action = Some(WakeTask(task));
7893
self.start(msecs, 0);
@@ -87,6 +102,7 @@ impl RtioTimer for TimerWatcher {
87102
// of the homing missile
88103
let _prev_action = {
89104
let _m = self.fire_homing_missile();
105+
self.stop();
90106
self.start(msecs, 0);
91107
util::replace(&mut self.action, Some(SendOnce(chan)))
92108
};
@@ -97,12 +113,11 @@ impl RtioTimer for TimerWatcher {
97113
fn period(&mut self, msecs: u64) -> Port<()> {
98114
let (port, chan) = stream();
99115

100-
let _m = self.fire_homing_missile();
101-
102116
// similarly to the destructor, we must drop the previous action outside
103117
// of the homing missile
104118
let _prev_action = {
105119
let _m = self.fire_homing_missile();
120+
self.stop();
106121
self.start(msecs, msecs);
107122
util::replace(&mut self.action, Some(SendMany(chan)))
108123
};
@@ -236,6 +251,18 @@ mod test {
236251

237252
timer.oneshot(1);
238253
}
254+
#[test]
255+
fn reset_doesnt_switch_tasks2() {
256+
// similar test to the one above.
257+
let mut timer = TimerWatcher::new(local_loop());
258+
let timer_port = Cell::new(timer.period(1000));
259+
260+
do spawn {
261+
timer_port.take().try_recv();
262+
}
263+
264+
timer.sleep(1);
265+
}
239266

240267
#[test]
241268
fn sender_goes_away_oneshot() {

src/librustuv/tty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,6 @@ impl HomingIO for TtyWatcher {
113113
impl Drop for TtyWatcher {
114114
fn drop(&mut self) {
115115
let _m = self.fire_homing_missile();
116-
self.close();
116+
self.close_async_();
117117
}
118118
}

src/librustuv/uvll.rs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,14 @@ pub static UNKNOWN: c_int = -4094;
4747
pub mod errors {
4848
use std::libc::c_int;
4949

50-
pub static EACCES: c_int = -4093;
51-
pub static ECONNREFUSED: c_int = -4079;
52-
pub static ECONNRESET: c_int = -4078;
53-
pub static ENOTCONN: c_int = -4054;
54-
pub static EPIPE: c_int = -4048;
55-
pub static ECONNABORTED: c_int = -4080;
56-
pub static ECANCELED: c_int = -4082;
57-
pub static EBADF: c_int = -4084;
50+
pub static EACCES: c_int = -4092;
51+
pub static ECONNREFUSED: c_int = -4078;
52+
pub static ECONNRESET: c_int = -4077;
53+
pub static ENOTCONN: c_int = -4053;
54+
pub static EPIPE: c_int = -4047;
55+
pub static ECONNABORTED: c_int = -4079;
56+
pub static ECANCELED: c_int = -4081;
57+
pub static EBADF: c_int = -4083;
5858
}
5959
#[cfg(not(windows))]
6060
pub mod errors {
@@ -87,19 +87,19 @@ pub static STDIO_WRITABLE_PIPE: c_int = 0x20;
8787
#[cfg(unix)]
8888
pub type uv_buf_len_t = libc::size_t;
8989
#[cfg(windows)]
90-
pub type uv_buf_len_t = u32;
90+
pub type uv_buf_len_t = libc::c_ulong;
9191

9292
// see libuv/include/uv-unix.h
9393
#[cfg(unix)]
9494
pub struct uv_buf_t {
9595
base: *u8,
96-
len: libc::size_t,
96+
len: uv_buf_len_t,
9797
}
9898

9999
// see libuv/include/uv-win.h
100100
#[cfg(windows)]
101101
pub struct uv_buf_t {
102-
len: u32,
102+
len: uv_buf_len_t,
103103
base: *u8,
104104
}
105105

@@ -544,7 +544,19 @@ pub unsafe fn guess_handle(handle: c_int) -> c_int {
544544

545545

546546
// uv_support is the result of compiling rust_uv.cpp
547+
//
548+
// Note that this is in a cfg'd block so it doesn't get linked during testing.
549+
// There's a bit of a conundrum when testing in that we're actually assuming
550+
// that the tests are running in a uv loop, but they were created from the
551+
// statically linked uv to the original rustuv crate. When we create the test
552+
// executable, on some platforms if we re-link against uv, it actually creates
553+
// second copies of everything. We obviously don't want this, so instead of
554+
// dying horribly during testing, we allow all of the test rustuv's references
555+
// to get resolved to the original rustuv crate.
547556
#[link_args = "-luv_support -luv"]
557+
#[cfg(not(test))]
558+
extern {}
559+
548560
extern {
549561
fn rust_uv_loop_new() -> *c_void;
550562

src/libstd/rt/io/stdio.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ use result::{Ok, Err};
3333
use rt::io::buffered::LineBufferedWriter;
3434
use rt::rtio::{IoFactory, RtioTTY, RtioFileStream, with_local_io,
3535
CloseAsynchronously};
36-
use super::{Reader, Writer, io_error, IoError, OtherIoError};
36+
use super::{Reader, Writer, io_error, IoError, OtherIoError,
37+
standard_error, EndOfFile};
3738

3839
// And so begins the tale of acquiring a uv handle to a stdio stream on all
3940
// platforms in all situations. Our story begins by splitting the world into two
@@ -203,6 +204,15 @@ impl Reader for StdReader {
203204
File(ref mut file) => file.read(buf).map(|i| i as uint),
204205
};
205206
match ret {
207+
// When reading a piped stdin, libuv will return 0-length reads when
208+
// stdin reaches EOF. For pretty much all other streams it will
209+
// return an actual EOF error, but apparently for stdin it's a
210+
// little different. Hence, here we convert a 0 length read to an
211+
// end-of-file indicator so the caller knows to stop reading.
212+
Ok(0) => {
213+
io_error::cond.raise(standard_error(EndOfFile));
214+
None
215+
}
206216
Ok(amt) => Some(amt as uint),
207217
Err(e) => {
208218
io_error::cond.raise(e);

src/libstd/rt/io/timer.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,10 @@ mod test {
142142
fn oneshot_twice() {
143143
do run_in_mt_newsched_task {
144144
let mut timer = Timer::new().unwrap();
145-
let port1 = timer.oneshot(100000000000);
145+
let port1 = timer.oneshot(10000);
146146
let port = timer.oneshot(1);
147147
port.recv();
148-
let port1 = Cell::new(port1);
149-
let ret = do task::try {
150-
port1.take().recv();
151-
};
152-
assert!(ret.is_err());
148+
assert_eq!(port1.try_recv(), None);
153149
}
154150
}
155151

src/libuv

0 commit comments

Comments
 (0)