mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
correcting for libuv behavior that differs between linux & windows
net complexity increase :/
This commit is contained in:
parent
d461637cc5
commit
0b3a06ab2c
@ -8,7 +8,8 @@ enum uv_operation {
|
||||
op_close(uv_handle, *ctypes::void),
|
||||
op_timer_init([u8]),
|
||||
op_timer_start([u8], *ctypes::void, u32, u32),
|
||||
op_timer_stop([u8], *ctypes::void, fn~(uv_handle))
|
||||
op_timer_stop([u8], *ctypes::void, fn~(uv_handle)),
|
||||
op_teardown(*ctypes::void)
|
||||
}
|
||||
|
||||
enum uv_handle {
|
||||
@ -34,7 +35,8 @@ enum uv_msg {
|
||||
uv_timer_init([u8], *ctypes::void),
|
||||
uv_timer_call([u8]),
|
||||
uv_timer_stop([u8], fn~(uv_handle)),
|
||||
uv_end()
|
||||
uv_end(),
|
||||
uv_teardown_check()
|
||||
}
|
||||
|
||||
type uv_loop_data = {
|
||||
@ -148,11 +150,13 @@ fn loop_new() -> uv_loop unsafe {
|
||||
// loop process any pending operations
|
||||
// once its up and running
|
||||
task::spawn_sched(task::manual_threads(1u)) {||
|
||||
// make sure we didn't start the loop
|
||||
// without the user registering handles
|
||||
comm::send(rust_loop_chan, uv_teardown_check);
|
||||
// this call blocks
|
||||
rustrt::rust_uv_run(loop_handle);
|
||||
// when we're done, msg the
|
||||
// end chan
|
||||
rustrt::rust_uv_stop_op_cb(op_handle);
|
||||
comm::send(end_chan, true);
|
||||
comm::send(rust_loop_chan, uv_end);
|
||||
};
|
||||
@ -160,6 +164,8 @@ fn loop_new() -> uv_loop unsafe {
|
||||
|
||||
msg_run_in_bg {
|
||||
task::spawn_sched(task::manual_threads(1u)) {||
|
||||
// see note above
|
||||
comm::send(rust_loop_chan, uv_teardown_check);
|
||||
// this call blocks
|
||||
rustrt::rust_uv_run(loop_handle);
|
||||
};
|
||||
@ -194,6 +200,9 @@ fn loop_new() -> uv_loop unsafe {
|
||||
task::spawn {||
|
||||
cb();
|
||||
};
|
||||
// ask the rust loop to check and see if there
|
||||
// are no more user-registered handles
|
||||
comm::send(rust_loop_chan, uv_teardown_check);
|
||||
}
|
||||
|
||||
msg_async_init(callback, after_cb) {
|
||||
@ -202,6 +211,7 @@ fn loop_new() -> uv_loop unsafe {
|
||||
// data and save the callback for
|
||||
// invocation on msg_async_send
|
||||
let id = gen_handle_id();
|
||||
handles.insert(id, ptr::null());
|
||||
async_cbs.insert(id, callback);
|
||||
after_cbs.insert(id, after_cb);
|
||||
let op = op_async_init(id);
|
||||
@ -235,6 +245,7 @@ fn loop_new() -> uv_loop unsafe {
|
||||
|
||||
msg_timer_init(after_cb) {
|
||||
let id = gen_handle_id();
|
||||
handles.insert(id, ptr::null());
|
||||
after_cbs.insert(id, after_cb);
|
||||
let op = op_timer_init(id);
|
||||
pass_to_libuv(op_handle, operation_chan, op);
|
||||
@ -276,6 +287,18 @@ fn loop_new() -> uv_loop unsafe {
|
||||
after_cb(the_timer);
|
||||
}
|
||||
|
||||
uv_teardown_check() {
|
||||
// here we're checking if there are no user-registered
|
||||
// handles (and the loop is running), if this is the
|
||||
// case, then we need to unregister the op_handle via
|
||||
// a uv_close() call, thus allowing libuv to return
|
||||
// on its own.
|
||||
if (handles.size() == 0u) {
|
||||
let op = op_teardown(op_handle);
|
||||
pass_to_libuv(op_handle, operation_chan, op);
|
||||
}
|
||||
}
|
||||
|
||||
uv_end() {
|
||||
keep_going = false;
|
||||
}
|
||||
@ -442,6 +465,12 @@ crust fn process_operation(
|
||||
rustrt::rust_uv_timer_stop(handle);
|
||||
comm::send(loop_chan, uv_timer_stop(id, after_cb));
|
||||
}
|
||||
op_teardown(op_handle) {
|
||||
// this is the last msg that'll be processed by
|
||||
// this fn, in the current lifetime of the handle's
|
||||
// uv_loop_t
|
||||
rustrt::rust_uv_stop_op_cb(op_handle);
|
||||
}
|
||||
_ { fail "unknown form of uv_operation received"; }
|
||||
}
|
||||
op_pending = comm::peek(op_port);
|
||||
@ -536,7 +565,8 @@ fn test_uv_simple_async() {
|
||||
async_send(new_async);
|
||||
});
|
||||
run(test_loop);
|
||||
assert comm::recv(exit_port);
|
||||
let result = comm::recv(exit_port);
|
||||
assert result;
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -68,10 +68,8 @@ native_close_cb(uv_handle_t* handle) {
|
||||
|
||||
static void
|
||||
native_close_op_cb(uv_handle_t* op_handle) {
|
||||
uv_loop_t* loop = op_handle->loop;
|
||||
current_kernel_free(op_handle);
|
||||
loop->data = 0; // a ptr to some stack-allocated rust mem
|
||||
uv_loop_delete(loop);
|
||||
// uv_run() should return after this..
|
||||
}
|
||||
|
||||
// native fns bound in rust
|
||||
@ -94,25 +92,13 @@ rust_uv_bind_op_cb(uv_loop_t* loop, crust_async_op_cb cb) {
|
||||
async->data = (void*)cb;
|
||||
// decrement the ref count, so that our async bind
|
||||
// doesn't count towards keeping the loop alive
|
||||
uv_unref(loop);
|
||||
//uv_unref(loop);
|
||||
return async;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
rust_uv_stop_op_cb(uv_handle_t* op_handle) {
|
||||
/* // this is a hack to get libuv to cleanup a
|
||||
// handle that was made to not prevent the loop
|
||||
// from exiting via uv_unref().
|
||||
uv_ref(op_handle->loop);
|
||||
uv_close(op_handle, native_close_op_cb);
|
||||
uv_run(op_handle->loop); // this should process the handle's
|
||||
// close event and then return
|
||||
*/
|
||||
// the above code is supposed to work to cleanly close
|
||||
// a handler that was uv_unref()'d. but it causes much spew
|
||||
// instead. this is the ugly/quick way to deal w/ it for now.
|
||||
uv_close(op_handle, native_close_op_cb);
|
||||
native_close_op_cb(op_handle);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
|
Loading…
Reference in New Issue
Block a user