diff --git a/src/unix/core.c b/src/unix/core.c index 78bf4908..cf323adc 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -317,8 +317,8 @@ int64_t uv_now(uv_loop_t* loop) { } -void uv__req_init(uv_req_t* req) { - /* loop->counters.req_init++; */ +void uv__req_init(uv_loop_t* loop, uv_req_t* req) { + loop->counters.req_init++; req->type = UV_UNKNOWN_REQ; } @@ -658,7 +658,7 @@ int uv_getaddrinfo(uv_loop_t* loop, return -1; } - uv__req_init((uv_req_t*)handle); + uv__req_init(loop, (uv_req_t*)handle); handle->type = UV_GETADDRINFO; handle->loop = loop; handle->cb = cb; diff --git a/src/unix/cygwin.c b/src/unix/cygwin.c index 25ff02c9..a3d17365 100644 --- a/src/unix/cygwin.c +++ b/src/unix/cygwin.c @@ -72,6 +72,7 @@ int uv_fs_event_init(uv_loop_t* loop, const char* filename, uv_fs_event_cb cb, int flags) { + loop->counters.fs_event_init++; uv__set_sys_error(loop, ENOSYS); return -1; } diff --git a/src/unix/fs.c b/src/unix/fs.c index 2ce38f14..436e54c6 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -66,7 +66,7 @@ static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req, uv_fs_type fs_type, /* Make sure the thread pool is initialized. */ uv_eio_init(loop); - uv__req_init((uv_req_t*) req); + uv__req_init(loop, (uv_req_t*)req); req->type = UV_FS; req->loop = loop; req->fs_type = fs_type; @@ -685,7 +685,7 @@ int uv_queue_work(uv_loop_t* loop, uv_work_t* req, uv_work_cb work_cb, uv_eio_init(loop); - uv__req_init((uv_req_t*) req); + uv__req_init(loop, (uv_req_t*)req); uv_ref(loop); req->loop = loop; req->data = data; diff --git a/src/unix/internal.h b/src/unix/internal.h index bb97c531..17381f33 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -143,7 +143,6 @@ enum { }; int uv__close(int fd); -void uv__req_init(uv_req_t*); void uv__handle_init(uv_loop_t* loop, uv_handle_t* handle, uv_handle_type type); @@ -155,6 +154,9 @@ int uv__socket(int domain, int type, int protocol); uv_err_code uv_translate_sys_error(int sys_errno); void uv_fatal_error(const int errorno, const char* syscall); +/* requests */ +void uv__req_init(uv_loop_t* loop, uv_req_t*); + /* stream */ void uv__stream_init(uv_loop_t* loop, uv_stream_t* stream, uv_handle_type type); diff --git a/src/unix/kqueue.c b/src/unix/kqueue.c index ad80a26f..551bce0a 100644 --- a/src/unix/kqueue.c +++ b/src/unix/kqueue.c @@ -90,6 +90,8 @@ int uv_fs_event_init(uv_loop_t* loop, int flags) { int fd; + loop->counters.fs_event_init++; + /* We don't support any flags yet. */ assert(!flags); @@ -129,6 +131,7 @@ int uv_fs_event_init(uv_loop_t* loop, const char* filename, uv_fs_event_cb cb, int flags) { + loop->counters.fs_event_init++; uv__set_sys_error(loop, ENOSYS); return -1; } diff --git a/src/unix/linux.c b/src/unix/linux.c index f91839f7..4b796903 100644 --- a/src/unix/linux.c +++ b/src/unix/linux.c @@ -161,6 +161,8 @@ int uv_fs_event_init(uv_loop_t* loop, int events; int fd; + loop->counters.fs_event_init++; + /* We don't support any flags yet. */ assert(!flags); diff --git a/src/unix/stream.c b/src/unix/stream.c index 035e6383..e0689fbc 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -662,7 +662,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { } /* Initialize request */ - uv__req_init((uv_req_t*)req); + uv__req_init(stream->loop, (uv_req_t*)req); req->handle = stream; req->cb = cb; @@ -772,7 +772,7 @@ int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr, } } - uv__req_init((uv_req_t*)req); + uv__req_init(stream->loop, (uv_req_t*)req); req->cb = cb; req->handle = stream; req->type = UV_CONNECT; @@ -847,7 +847,7 @@ int uv_write2(uv_write_t* req, uv_stream_t* stream, uv_buf_t bufs[], int bufcnt, empty_queue = (stream->write_queue_size == 0); /* Initialize the req */ - uv__req_init((uv_req_t*) req); + uv__req_init(stream->loop, (uv_req_t*)req); req->cb = cb; req->handle = stream; req->error = 0; diff --git a/src/unix/sunos.c b/src/unix/sunos.c index 725e5603..cf9f162a 100644 --- a/src/unix/sunos.c +++ b/src/unix/sunos.c @@ -145,6 +145,8 @@ int uv_fs_event_init(uv_loop_t* loop, int flags) { int portfd; + loop->counters.fs_event_init++; + /* We don't support any flags yet. */ assert(!flags); @@ -185,6 +187,7 @@ int uv_fs_event_init(uv_loop_t* loop, const char* filename, uv_fs_event_cb cb, int flags) { + loop->counters.fs_event_init++; uv__set_sys_error(loop, ENOSYS); return -1; } diff --git a/src/unix/udp.c b/src/unix/udp.c index 15cd609b..cbb37669 100644 --- a/src/unix/udp.c +++ b/src/unix/udp.c @@ -401,8 +401,7 @@ static int uv__udp_send(uv_udp_send_t* req, if (uv__udp_maybe_deferred_bind(handle, addr->sa_family)) return -1; - /* Don't use uv__req_init(), it zeroes the data field. */ - handle->loop->counters.req_init++; + uv__req_init(handle->loop, (uv_req_t*)req); memcpy(&req->addr, addr, addrlen); req->addrlen = addrlen; diff --git a/src/win/tty.c b/src/win/tty.c index 6d8f6bca..88c68954 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -90,6 +90,8 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { HANDLE win_handle; CONSOLE_SCREEN_BUFFER_INFO info; + loop->counters.tty_init++; + win_handle = (HANDLE) _get_osfhandle(fd); if (win_handle == INVALID_HANDLE_VALUE) { uv__set_sys_error(loop, ERROR_INVALID_HANDLE); diff --git a/test/test-counters-init.c b/test/test-counters-init.c new file mode 100644 index 00000000..423d349c --- /dev/null +++ b/test/test-counters-init.c @@ -0,0 +1,216 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#define UNIX (defined(__unix__) || defined(__POSIX__) || defined(__APPLE__)) +#include "task.h" +#include "uv.h" +#include + +#if UNIX +#include /* unlink, rmdir, etc. */ +#else +# include +# include +# define unlink _unlink +# define rmdir _rmdir +# define stat _stati64 +# define open _open +# define write _write +# define lseek _lseek +# define close _close +#endif + +static char exepath[1024]; +static size_t exepath_size = 1024; +static char* args[3]; +static uv_fs_t open_req; +static uv_tcp_t tcp; +static uv_udp_t udp; +static uv_pipe_t uvpipe; +static uv_tty_t tty; +static uv_prepare_t prepare; +static uv_check_t check; +static uv_idle_t idle; +static uv_async_t async; +static uv_timer_t timer; +static uv_fs_event_t fs_event; +static uv_process_t process; +static uv_process_options_t options; +static uv_fs_t fs_req; + +static void exit_cb(uv_process_t* process, int exit_status, int term_signal) { + ASSERT(exit_status == 1); + ASSERT(term_signal == 0); + uv_close((uv_handle_t*)process, NULL); +} + +static void init_process_options(char* test, uv_exit_cb exit_cb) { + int r = uv_exepath(exepath, &exepath_size); + ASSERT(r == 0); + exepath[exepath_size] = '\0'; + args[0] = exepath; + args[1] = test; + args[2] = NULL; + options.file = exepath; + options.args = args; + options.exit_cb = exit_cb; +} + +static void create_dir(uv_loop_t* loop, const char* name) { + int r; + uv_fs_t req; + r = uv_fs_rmdir(loop, &req, name, NULL); + r = uv_fs_mkdir(loop, &req, name, 0755, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&req); +} + +static void create_cb(uv_fs_t* req) { + ASSERT(req == &open_req); + ASSERT(req->fs_type == UV_FS_OPEN); + ASSERT(req->result != -1); + uv_fs_req_cleanup(req); + unlink("test_file"); +} + +TEST_IMPL(counters_init) { + int r; + int eio_init_prev; + int req_init_prev; + int handle_init_prev; + int stream_init_prev; + int tcp_init_prev; + int udp_init_prev; + int pipe_init_prev; + int tty_init_prev; + int prepare_init_prev; + int check_init_prev; + int idle_init_prev; + int async_init_prev; + int timer_init_prev; + int process_init_prev; + int fs_event_init_prev; + + /* req_init and eio_init test by uv_fs_open() */ + unlink("test_file"); + req_init_prev = uv_default_loop()->counters.req_init; + eio_init_prev = uv_default_loop()->counters.eio_init; + r = uv_fs_open(uv_default_loop(), &open_req, "test_file", O_WRONLY | O_CREAT, + S_IREAD | S_IWRITE, create_cb); + ASSERT(r == 0); + ASSERT(open_req.result == 0); + ASSERT(uv_default_loop()->counters.req_init == ++req_init_prev); +#ifndef _WIN32 + ASSERT(uv_default_loop()->counters.eio_init == ++eio_init_prev); +#endif + + /* tcp_init, stream_init and handle_init test by uv_tcp_init() */ + tcp_init_prev = uv_default_loop()->counters.tcp_init; + stream_init_prev = uv_default_loop()->counters.stream_init; + handle_init_prev = uv_default_loop()->counters.handle_init; + r = uv_tcp_init(uv_default_loop(), &tcp); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.tcp_init == ++tcp_init_prev); + ASSERT(uv_default_loop()->counters.stream_init == ++stream_init_prev); + ASSERT(uv_default_loop()->counters.handle_init == ++handle_init_prev); + uv_close((uv_handle_t*)&tcp, NULL); + + /* udp_init test by uv_udp_init() */ + udp_init_prev = uv_default_loop()->counters.udp_init; + r = uv_udp_init(uv_default_loop(), &udp); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.udp_init == ++udp_init_prev); + uv_close((uv_handle_t*)&udp, NULL); + + /* pipe_init uv_pipe_init() */ + pipe_init_prev = uv_default_loop()->counters.pipe_init; + uv_pipe_init(uv_default_loop(), &uvpipe, 0); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.pipe_init == ++pipe_init_prev); + uv_close((uv_handle_t*)&uvpipe, NULL); + + /* tty_init test by uv_tty_init()*/ + tty_init_prev = uv_default_loop()->counters.tty_init; + r = uv_tty_init(uv_default_loop(), &tty, 1, 0); + /* uv_tty_init() always returns -1 in run_test in Windows + so that we avoid to check return value. + */ +#ifndef _WIN32 + ASSERT(r == 0); + uv_close((uv_handle_t*)&tty, NULL); +#endif + ASSERT(uv_default_loop()->counters.tty_init == ++tty_init_prev); + + /* prepare_init test by uv_prepare_init() */ + prepare_init_prev = uv_default_loop()->counters.prepare_init; + r = uv_prepare_init(uv_default_loop(), &prepare); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.prepare_init == ++prepare_init_prev); + uv_close((uv_handle_t*)&prepare, NULL); + + /* check_init test by uv_check_init() */ + check_init_prev = uv_default_loop()->counters.check_init; + r = uv_check_init(uv_default_loop(), &check); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.check_init == ++check_init_prev); + uv_close((uv_handle_t*)&check, NULL); + + /* idle_init test by uv_idle_init() */ + idle_init_prev = uv_default_loop()->counters.idle_init; + r = uv_idle_init(uv_default_loop(), &idle); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.idle_init == ++idle_init_prev); + uv_close((uv_handle_t*)&idle, NULL); + + /* async_init test by uv_async_init() */ + async_init_prev = uv_default_loop()->counters.async_init; + r = uv_async_init(uv_default_loop(), &async, NULL); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.async_init == ++async_init_prev); + uv_close((uv_handle_t*)&async, NULL); + + /* timer_init test by uv_timer_init() */ + timer_init_prev = uv_default_loop()->counters.timer_init; + r = uv_timer_init(uv_default_loop(), &timer); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.timer_init == ++timer_init_prev); + uv_close((uv_handle_t*)&timer, NULL); + + /* process_init test by uv_spawn() */ + process_init_prev = uv_default_loop()->counters.process_init; + init_process_options("spawn_helper1", exit_cb); + r = uv_spawn(uv_default_loop(), &process, options); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.process_init == ++process_init_prev); + r = uv_run(uv_default_loop()); + ASSERT(r == 0); + + /* fs_event_init test by uv_fs_event_init() */ + create_dir(uv_default_loop(), "watch_dir"); + fs_event_init_prev = uv_default_loop()->counters.fs_event_init; + r = uv_fs_event_init(uv_default_loop(), &fs_event, "watch_dir", NULL, 0); + ASSERT(r == 0); + ASSERT(uv_default_loop()->counters.fs_event_init == ++fs_event_init_prev); + r = uv_fs_rmdir(uv_default_loop(), &fs_req, "watch_dir", NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&fs_req); + + return 0; +} diff --git a/test/test-list.h b/test/test-list.h index 23b24818..96e9d84c 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -122,7 +122,7 @@ TEST_DECLARE (thread_rwlock) TEST_DECLARE (thread_create) TEST_DECLARE (strlcpy) TEST_DECLARE (strlcat) - +TEST_DECLARE (counters_init) #ifdef _WIN32 TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) TEST_DECLARE (argument_escaping) @@ -283,7 +283,7 @@ TASK_LIST_START TEST_ENTRY (thread_create) TEST_ENTRY (strlcpy) TEST_ENTRY (strlcat) - + TEST_ENTRY (counters_init) #if 0 /* These are for testing the test runner. */ TEST_ENTRY (fail_always) diff --git a/uv.gyp b/uv.gyp index d8a18a0c..b2eef605 100644 --- a/uv.gyp +++ b/uv.gyp @@ -323,6 +323,7 @@ 'test/test-udp-ipv6.c', 'test/test-udp-send-and-recv.c', 'test/test-udp-multicast-join.c', + 'test/test-counters-init.c', ], 'conditions': [ [ 'OS=="win"', {