about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-11-25 05:46:37 -0800
committerbors <bors@rust-lang.org>2013-11-25 05:46:37 -0800
commitfffacb34fec23da45c4d18ce8504c7947527aa78 (patch)
treea59470563bc3b39b3d32f16ea5fb235c0a1d48e6
parent1746c0269d356a93aaef367541872d363651cb23 (diff)
parent6acf227cc8db09ca25d274918f860849c41df19a (diff)
auto merge of #10646 : alexcrichton/rust/issue-10645, r=luqmana
This is a behavioral difference in libuv between different platforms in
different situations. It turns out that libuv on windows will immediately
allocate a buffer instead of waiting for data to be ready. What this implies is
that we must have our custom data set on the handle before we call
uv_read_start.

I wish I knew of a way to test this, but this relies to being on the windows
platform *and* reading from a true TTY handle which only happens when this is
actually attached to a terminal. I have manually verified this works.

Closes #10645
-rw-r--r--src/librustuv/stream.rs25
1 files changed, 15 insertions, 10 deletions
diff --git a/src/librustuv/stream.rs b/src/librustuv/stream.rs
index 08b307700c7..47ef26ee9d4 100644
--- a/src/librustuv/stream.rs
+++ b/src/librustuv/stream.rs
@@ -69,22 +69,27 @@ impl StreamWatcher {
         // uv_read_stop function
         let _f = ForbidUnwind::new("stream read");
 
+        let mut rcx = ReadContext {
+            buf: Some(slice_to_uv_buf(buf)),
+            result: 0,
+            task: None,
+        };
+        // When reading a TTY stream on windows, libuv will invoke alloc_cb
+        // immediately as part of the call to alloc_cb. What this means is that
+        // we must be ready for this to happen (by setting the data in the uv
+        // handle). In theory this otherwise doesn't need to happen until after
+        // the read is succesfully started.
+        unsafe {
+            uvll::set_data_for_uv_handle(self.handle, &rcx)
+        }
+
         // Send off the read request, but don't block until we're sure that the
         // read request is queued.
         match unsafe {
             uvll::uv_read_start(self.handle, alloc_cb, read_cb)
         } {
             0 => {
-                let mut rcx = ReadContext {
-                    buf: Some(slice_to_uv_buf(buf)),
-                    result: 0,
-                    task: None,
-                };
-                do wait_until_woken_after(&mut rcx.task) {
-                    unsafe {
-                        uvll::set_data_for_uv_handle(self.handle, &rcx)
-                    }
-                }
+                wait_until_woken_after(&mut rcx.task, || {});
                 match rcx.result {
                     n if n < 0 => Err(UvError(n as c_int)),
                     n => Ok(n as uint),