Skip to content

Commit ee0ce64

Browse files
committed
core::rt: Wait for handles to close
1 parent 204e3d8 commit ee0ce64

File tree

3 files changed

+60
-24
lines changed

3 files changed

+60
-24
lines changed

src/libcore/rt/uv/idle.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use libc::c_int;
1212
use option::Some;
1313
use rt::uv::uvll;
14-
use rt::uv::{Watcher, Loop, NativeHandle, IdleCallback};
14+
use rt::uv::{Watcher, Loop, NativeHandle, IdleCallback, NullCallback};
1515
use rt::uv::status_to_maybe_uv_error;
1616

1717
pub struct IdleWatcher(*uvll::uv_idle_t);
@@ -57,12 +57,23 @@ pub impl IdleWatcher {
5757
}
5858
}
5959

60-
fn close(self) {
60+
fn close(self, cb: NullCallback) {
61+
{
62+
let mut this = self;
63+
let data = this.get_watcher_data();
64+
assert!(data.close_cb.is_none());
65+
data.close_cb = Some(cb);
66+
}
67+
6168
unsafe { uvll::close(self.native_handle(), close_cb) };
6269

6370
extern fn close_cb(handle: *uvll::uv_idle_t) {
6471
unsafe {
6572
let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
73+
{
74+
let mut data = idle_watcher.get_watcher_data();
75+
data.close_cb.swap_unwrap()();
76+
}
6677
idle_watcher.drop_watcher_data();
6778
uvll::idle_delete(handle);
6879
}

src/libcore/rt/uv/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ fn idle_new_then_close() {
356356
do run_in_bare_thread {
357357
let mut loop_ = Loop::new();
358358
let idle_watcher = { IdleWatcher::new(&mut loop_) };
359-
idle_watcher.close();
359+
idle_watcher.close(||());
360360
}
361361
}
362362

@@ -372,7 +372,7 @@ fn idle_smoke_test() {
372372
assert!(status.is_none());
373373
if unsafe { *count_ptr == 10 } {
374374
idle_watcher.stop();
375-
idle_watcher.close();
375+
idle_watcher.close(||());
376376
} else {
377377
unsafe { *count_ptr = *count_ptr + 1; }
378378
}
@@ -396,7 +396,7 @@ fn idle_start_stop_start() {
396396
assert!(status.is_none());
397397
let mut idle_watcher = idle_watcher;
398398
idle_watcher.stop();
399-
idle_watcher.close();
399+
idle_watcher.close(||());
400400
}
401401
}
402402
loop_.run();

src/libcore/rt/uv/uvio.rs

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ impl EventLoop for UvEventLoop {
6666
assert!(status.is_none());
6767
let mut idle_watcher = idle_watcher;
6868
idle_watcher.stop();
69-
idle_watcher.close();
69+
idle_watcher.close(||());
7070
f();
7171
}
7272
}
@@ -124,22 +124,26 @@ impl IoFactory for UvIoFactory {
124124
// Wait for a connection
125125
do tcp_watcher.connect(addr) |stream_watcher, status| {
126126
rtdebug!("connect: in connect callback");
127-
let maybe_stream = if status.is_none() {
127+
if status.is_none() {
128128
rtdebug!("status is none");
129-
Ok(~UvTcpStream { watcher: stream_watcher })
129+
let res = Ok(~UvTcpStream { watcher: stream_watcher });
130+
131+
// Store the stream in the task's stack
132+
unsafe { (*result_cell_ptr).put_back(res); }
133+
134+
// Context switch
135+
let scheduler = local_sched::take();
136+
scheduler.resume_task_immediately(task_cell.take());
130137
} else {
131138
rtdebug!("status is some");
132-
// XXX: Wait for close
133-
stream_watcher.close(||());
134-
Err(uv_error_to_io_error(status.get()))
139+
let task_cell = Cell(task_cell.take());
140+
do stream_watcher.close {
141+
let res = Err(uv_error_to_io_error(status.get()));
142+
unsafe { (*result_cell_ptr).put_back(res); }
143+
let scheduler = local_sched::take();
144+
scheduler.resume_task_immediately(task_cell.take());
145+
}
135146
};
136-
137-
// Store the stream in the task's stack
138-
unsafe { (*result_cell_ptr).put_back(maybe_stream); }
139-
140-
// Context switch
141-
let scheduler = local_sched::take();
142-
scheduler.resume_task_immediately(task_cell.take());
143147
}
144148
}
145149

@@ -152,8 +156,14 @@ impl IoFactory for UvIoFactory {
152156
match watcher.bind(addr) {
153157
Ok(_) => Ok(~UvTcpListener::new(watcher)),
154158
Err(uverr) => {
155-
// XXX: Should we wait until close completes?
156-
watcher.as_stream().close(||());
159+
let scheduler = local_sched::take();
160+
do scheduler.deschedule_running_task_and_then |task| {
161+
let task_cell = Cell(task);
162+
do watcher.as_stream().close {
163+
let scheduler = local_sched::take();
164+
scheduler.resume_task_immediately(task_cell.take());
165+
}
166+
}
157167
Err(uv_error_to_io_error(uverr))
158168
}
159169
}
@@ -181,8 +191,15 @@ impl UvTcpListener {
181191

182192
impl Drop for UvTcpListener {
183193
fn finalize(&self) {
184-
// XXX: Need to wait until close finishes before returning
185-
self.watcher().as_stream().close(||());
194+
let watcher = self.watcher();
195+
let scheduler = local_sched::take();
196+
do scheduler.deschedule_running_task_and_then |task| {
197+
let task_cell = Cell(task);
198+
do watcher.as_stream().close {
199+
let scheduler = local_sched::take();
200+
scheduler.resume_task_immediately(task_cell.take());
201+
}
202+
}
186203
}
187204
}
188205

@@ -235,8 +252,16 @@ impl UvTcpStream {
235252

236253
impl Drop for UvTcpStream {
237254
fn finalize(&self) {
238-
rtdebug!("closing stream");
239-
self.watcher().close(||());
255+
rtdebug!("closing tcp stream");
256+
let watcher = self.watcher();
257+
let scheduler = local_sched::take();
258+
do scheduler.deschedule_running_task_and_then |task| {
259+
let task_cell = Cell(task);
260+
do watcher.close {
261+
let scheduler = local_sched::take();
262+
scheduler.resume_task_immediately(task_cell.take());
263+
}
264+
}
240265
}
241266
}
242267

0 commit comments

Comments
 (0)