diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs index 5fab90330638..0e21d1d5da6c 100644 --- a/src/libstd/uv.rs +++ b/src/libstd/uv.rs @@ -274,6 +274,30 @@ fn gen_stub_uv_write_t() -> uv_write_t { a12: 0 as *u8 }; } +// unix size: 120 +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] +type uv_async_t = { + fields: uv_handle_fields, + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, a07: *u8, + a08: *u8, a09: *u8, a10: *u8 +}; +#[cfg(target_os = "linux")] +#[cfg(target_os = "macos")] +#[cfg(target_os = "freebsd")] +#[cfg(target_os = "win32")] +fn gen_stub_uv_async_t() -> uv_async_t { + ret { fields: { loop_handle: ptr::null(), type_: 0u32, + close_cb: ptr::null(), + mut data: ptr::null() }, + a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8, a03: 0 as *u8, + a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8, a07: 0 as *u8, + a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8 + }; +} // unix size: 16 #[cfg(target_os = "linux")] @@ -312,8 +336,11 @@ fn rust_uv_bind_op_cb(lp: *libc::c_void, cb: *u8) fn rust_uv_hilvl_close(handle: *libc::c_void, cb: *u8); fn rust_uv_hilvl_close_async(handle: *libc::c_void); fn rust_uv_hilvl_close_timer(handle: *libc::c_void); - fn rust_uv_async_send(handle: *libc::c_void); - fn rust_uv_async_init( + fn rust_uv_async_send(handle: *uv_async_t); + fn rust_uv_async_init(loop_handle: *libc::c_void, + async_handle: *uv_async_t, + cb: *u8) -> libc::c_int; + fn rust_uv_hilvl_async_init( loop_handle: *libc::c_void, cb: *u8, id: *u8) -> *libc::c_void; @@ -366,6 +393,7 @@ fn rust_uv_read_start(stream: *libc::c_void, on_alloc: *u8, fn rust_uv_helper_uv_write_t_size() -> libc::c_uint; fn rust_uv_helper_uv_err_t_size() -> libc::c_uint; fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint; + fn rust_uv_helper_uv_async_t_size() -> libc::c_uint; // data accessors for rust-mapped uv structs fn rust_uv_get_stream_handle_from_connect_req( @@ -460,6 +488,18 @@ unsafe fn uv_last_error(loop_handle: *libc::c_void) -> uv_err_t { ret rustrt::rust_uv_last_error(loop_handle); } + unsafe fn async_init(loop_handle: *libc::c_void, + async_handle: *uv_async_t, + cb: *u8) -> libc::c_int { + ret rustrt::rust_uv_async_init(loop_handle, + async_handle, + cb); + } + + unsafe fn async_send(async_handle: *uv_async_t) { + ret rustrt::rust_uv_async_send(async_handle); + } + // libuv struct initializers unsafe fn tcp_t() -> uv_tcp_t { ret gen_stub_uv_tcp_t(); @@ -470,6 +510,9 @@ unsafe fn connect_t() -> uv_connect_t { unsafe fn write_t() -> uv_write_t { ret gen_stub_uv_write_t(); } + unsafe fn async_t() -> uv_async_t { + ret gen_stub_uv_async_t(); + } unsafe fn get_loop_for_uv_handle(handle: *libc::c_void) -> *libc::c_void { ret rustrt::rust_uv_get_loop_for_uv_handle(handle); @@ -855,7 +898,7 @@ fn pass_to_libuv( do_send(op_handle); } fn do_send(h: *libc::c_void) { - rustrt::rust_uv_async_send(h); + rustrt::rust_uv_async_send(h as *uv_async_t); } fn gen_handle_id() -> [u8] { ret rand::rng().gen_bytes(16u); @@ -920,7 +963,7 @@ fn get_id_from_handle(handle: uv_handle) -> [u8] { alt comm::recv(op_port) { op_async_init(id) { let id_ptr = vec::unsafe::to_ptr(id); - let async_handle = rustrt::rust_uv_async_init( + let async_handle = rustrt::rust_uv_hilvl_async_init( lp, process_async_send, id_ptr); @@ -1367,12 +1410,29 @@ fn impl_uv_tcp_request(ip: str, port: int, req_str: str, server_write_req: *uv_write_t }; +type async_handle_data = { + continue_chan: *comm::chan +}; + +crust fn continue_async_cb(async_handle: *uv_async_t, + status: libc::c_int) unsafe { + // once we're in the body of this callback, + // the tcp server's loop is set up, so we + // can continue on to let the tcp client + // do its thang + let data = direct::get_data_for_uv_handle( + async_handle as *libc::c_void) as *async_handle_data; + let continue_chan = *((*data).continue_chan); + comm::send(continue_chan, true); + direct::close(async_handle as *libc::c_void, 0 as *u8); +} + fn impl_uv_tcp_server(server_ip: str, server_port: int, kill_server_msg: str, server_resp_msg: str, server_chan: *comm::chan, - continue_chan: comm::chan) unsafe { + continue_chan: *comm::chan) unsafe { let test_loop = direct::loop_new(); let tcp_server = direct::tcp_t(); let tcp_server_ptr = ptr::addr_of(tcp_server); @@ -1389,6 +1449,13 @@ fn impl_uv_tcp_server(server_ip: str, direct::buf_init(resp_msg_ptr, vec::len(resp_str_bytes)) ]; + let continue_async_handle = direct::async_t(); + let continue_async_handle_ptr = + ptr::addr_of(continue_async_handle); + let async_data = + { continue_chan: continue_chan }; + let async_data_ptr = ptr::addr_of(async_data); + let server_data: tcp_server_data = { client: tcp_client_ptr, server: tcp_server_ptr, @@ -1423,10 +1490,22 @@ fn impl_uv_tcp_server(server_ip: str, if (listen_result == 0i32) { // let the test know it can set up the tcp server, // now.. this may still present a race, not sure.. - comm::send(continue_chan, true); - - // uv_run() - direct::run(test_loop); + let async_result = direct::async_init(test_loop, + continue_async_handle_ptr, + continue_async_cb); + if (async_result == 0i32) { + direct::set_data_for_uv_handle( + continue_async_handle_ptr as *libc::c_void, + async_data_ptr as *libc::c_void); + direct::async_send(continue_async_handle_ptr); + // uv_run() + direct::run(test_loop); + } + else { + io::println(#fmt("uv_async_init failure: %d", + async_result as int)); + assert false; + } } else { io::println(#fmt("non-zero result on uv_listen: %d", @@ -1462,13 +1541,14 @@ fn test_uv_tcp_server_and_request() unsafe { let continue_port = comm::port::(); let continue_chan = comm::chan::(continue_port); + let continue_chan_ptr = ptr::addr_of(continue_chan); task::spawn_sched(task::manual_threads(1u)) {|| impl_uv_tcp_server(ip, port, kill_server_msg, server_resp_msg, ptr::addr_of(server_chan), - continue_chan); + continue_chan_ptr); }; // block until the server up is.. possibly a race? @@ -1546,6 +1626,18 @@ fn test_uv_struct_size_sockaddr_in() { assert native_handle_size as uint == rust_handle_size; } +#[test] +#[ignore(cfg(target_os = "freebsd"))] +fn test_uv_struct_size_uv_async_t() { + let native_handle_size = + rustrt::rust_uv_helper_uv_async_t_size(); + let rust_handle_size = sys::size_of::(); + let output = #fmt("uv_async_t -- native: %u rust: %u", + native_handle_size as uint, rust_handle_size); + io::println(output); + assert native_handle_size as uint == rust_handle_size; +} + fn impl_uv_byval_test() unsafe { let addr = direct::ip4_addr("173.194.33.111", 80); io::println(#fmt("after build addr in rust. port: %u", diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 7a6a79ce17bf..6303bd700a6b 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -167,15 +167,22 @@ rust_uv_async_send(uv_async_t* handle) { uv_async_send(handle); } +extern "C" int +rust_uv_async_init(uv_loop_t* loop_handle, + uv_async_t* async_handle, + uv_async_cb cb) { + return uv_async_init(loop_handle, async_handle, cb); +} + extern "C" void* -rust_uv_async_init(uv_loop_t* loop, crust_simple_cb cb, - uint8_t* buf) { - uv_async_t* async = (uv_async_t*)current_kernel_malloc( - sizeof(uv_async_t), - "uv_async_t"); - uv_async_init(loop, async, native_async_cb); - handle_data* data = new_handle_data_from(buf, cb); - async->data = data; +rust_uv_hilvl_async_init(uv_loop_t* loop, crust_simple_cb cb, + uint8_t* buf) { + uv_async_t* async = (uv_async_t*)current_kernel_malloc( + sizeof(uv_async_t), + "uv_async_t"); + uv_async_init(loop, async, native_async_cb); + handle_data* data = new_handle_data_from(buf, cb); + async->data = data; return async; } @@ -270,6 +277,10 @@ extern "C" size_t rust_uv_helper_sockaddr_in_size() { return sizeof(sockaddr_in); } +extern "C" size_t +rust_uv_helper_uv_async_t_size() { + return sizeof(uv_async_t); +} extern "C" uv_stream_t* rust_uv_get_stream_handle_from_connect_req(uv_connect_t* connect) { diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 3369f6a3048e..38d97f0c3ed2 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -92,6 +92,7 @@ rust_uv_hilvl_close_async rust_uv_hilvl_close_timer rust_uv_async_send rust_uv_async_init +rust_uv_hilvl_async_init rust_uv_timer_init rust_uv_timer_start rust_uv_timer_stop @@ -116,6 +117,7 @@ rust_uv_helper_uv_buf_t_size rust_uv_helper_uv_write_t_size rust_uv_helper_uv_err_t_size rust_uv_helper_sockaddr_in_size +rust_uv_helper_uv_async_t_size rust_uv_get_stream_handle_from_connect_req rust_uv_get_stream_handle_from_write_req rust_uv_get_loop_for_uv_handle