From ce112c27c636ba17129d6061f8db636a80faeb48 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Tue, 21 Oct 2014 00:45:30 +0200 Subject: [PATCH] deps: update uv to v1.0.0-rc2 PR-URL: https://github.com/joyent/node/pull/8566 Reviewed-by: Fedor Indutny Reviewed-by: Trevor Norris --- deps/uv/AUTHORS | 9 + deps/uv/CONTRIBUTING.md | 6 +- deps/uv/ChangeLog | 42 +++++ deps/uv/Makefile.am | 9 + deps/uv/README.md | 4 +- deps/uv/configure.ac | 21 ++- deps/uv/docs/src/fs.rst | 30 ++- deps/uv/docs/src/fs_poll.rst | 4 + deps/uv/docs/src/handle.rst | 9 + deps/uv/docs/src/index.rst | 11 ++ deps/uv/docs/src/loop.rst | 4 +- deps/uv/docs/src/migration_010_100.rst | 244 +++++++++++++++++++++++++ deps/uv/docs/src/process.rst | 10 + deps/uv/docs/src/stream.rst | 28 +++ deps/uv/docs/src/threading.rst | 1 + deps/uv/include/uv-version.h | 2 +- deps/uv/include/uv-win.h | 12 ++ deps/uv/include/uv.h | 15 +- deps/uv/src/unix/core.c | 2 +- deps/uv/src/unix/fs.c | 32 +++- deps/uv/src/unix/thread.c | 5 + deps/uv/src/uv-common.c | 10 +- deps/uv/src/uv-common.h | 2 +- deps/uv/src/win/fs.c | 68 ++++++- deps/uv/src/win/poll.c | 2 +- deps/uv/src/win/thread.c | 5 + deps/uv/src/win/util.c | 185 +++++++++++++++---- deps/uv/test/test-fs.c | 237 ++++++++++++++++++------ deps/uv/test/test-list.h | 14 +- deps/uv/test/test-thread-equal.c | 45 +++++ deps/uv/test/test-threadpool-cancel.c | 2 +- deps/uv/uv.gyp | 1 + 32 files changed, 921 insertions(+), 150 deletions(-) create mode 100644 deps/uv/docs/src/migration_010_100.rst create mode 100644 deps/uv/test/test-thread-equal.c diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 210fa5610..6dae58e02 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -157,3 +157,12 @@ John Firebaugh lilohuang Paul Goldsmith Julien Gilli +Michael Hudson-Doyle +Recep ASLANTAS +Rob Adams +Zachary Newman +Robin Hahling +Jeff Widman +cjihrig +Tomasz Kołodziejski +Unknown W. Brackets diff --git a/deps/uv/CONTRIBUTING.md b/deps/uv/CONTRIBUTING.md index 28a32baae..ea4be395e 100644 --- a/deps/uv/CONTRIBUTING.md +++ b/deps/uv/CONTRIBUTING.md @@ -37,10 +37,10 @@ Okay, so you have decided on the proper branch. Create a feature branch and start hacking: ``` -$ git checkout -b my-feature-branch -t origin/v0.10 +$ git checkout -b my-feature-branch -t origin/v1.x ``` -(Where v0.10 is the latest stable branch as of this writing.) +(Where v1.x is the latest stable branch as of this writing.) ### CODE @@ -131,7 +131,7 @@ Use `git rebase` (not `git merge`) to sync your work from time to time. ``` $ git fetch upstream -$ git rebase upstream/v0.10 # or upstream/master +$ git rebase upstream/v1.x # or upstream/master ``` diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 9d303e4ff..c06c78209 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,5 +1,47 @@ +2014.10.21, Version 1.0.0-rc2 (Pre-release) + +Changes since version 1.0.0-rc1: + +* build: add missing fixtures to distribution tarball (Rob Adams) + +* doc: update references to current stable branch (Zachary Newman) + +* fs: fix readdir on empty directory (Fedor Indutny) + +* fs: rename uv_fs_readdir to uv_fs_scandir (Saúl Ibarra Corretgé) + +* doc: document uv_alloc_cb (Saúl Ibarra Corretgé) + +* doc: add migration guide from version 0.10 (Saúl Ibarra Corretgé) + +* build: add DragonFly BSD support in autotools (Robin Hahling) + +* doc: document missing stream related structures (Saúl Ibarra Corretgé) + +* doc: clarify uv_loop_t.data field lifetime (Saúl Ibarra Corretgé) + +* doc: add documentation for missing functions and structures (Saúl Ibarra + Corretgé) + +* doc: fix punctuation and grammar in README (Jeff Widman) + +* windows: return libuv error codes in uv_poll_init() (cjihrig) + +* unix, windows: add uv_fs_access() (cjihrig) + +* windows: fix netmask detection (Alexis Campailla) + +* unix, windows: don't include null byte in uv_cwd size (Saúl Ibarra Corretgé) + +* unix, windows: add uv_thread_equal (Tomasz Kołodziejski) + +* windows: fix fs_write with nbufs > 1 and offset (Unknown W. Brackets) + + 2014.09.18, Version 1.0.0-rc1 (Unstable), 0c28bbf7b42882853d1799ab96ff68b07f7f8d49 +Changes since version 0.11.29: + * windows: improve timer precision (Alexis Campailla) * build, gyp: set xcode flags (Recep ASLANTAS) diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 06a5532ef..07d628d3e 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -106,6 +106,9 @@ libuv_la_SOURCES += src/unix/async.c \ endif # WINNT +EXTRA_DIST = test/fixtures/empty_file \ + test/fixtures/load_error.node + TESTS = test/run-tests check_PROGRAMS = test/run-tests test_run_tests_CFLAGS = @@ -203,6 +206,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-tcp-writealot.c \ test/test-tcp-try-write.c \ test/test-tcp-write-queue-order.c \ + test/test-thread-equal.c \ test/test-thread.c \ test/test-threadpool-cancel.c \ test/test-threadpool.c \ @@ -268,6 +272,11 @@ libuv_la_SOURCES += src/unix/darwin.c \ src/unix/proctitle.c endif +if DRAGONFLY +include_HEADERS += include/uv-bsd.h +libuv_la_SOURCES += src/unix/kqueue.c src/unix/freebsd.c +endif + if FREEBSD include_HEADERS += include/uv-bsd.h libuv_la_SOURCES += src/unix/freebsd.c src/unix/kqueue.c diff --git a/deps/uv/README.md b/deps/uv/README.md index e0edf5038..53c1b46af 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -85,7 +85,7 @@ Documentation can be browsed online [here](http://docs.libuv.org). ## Build Instructions -For GCC there are two methods building: via autotools or via [GYP][]. +For GCC there are two build methods: via autotools or via [GYP][]. GYP is a meta-build system which can generate MSVS, Makefile, and XCode backends. It is best used for integration into other projects. @@ -100,7 +100,7 @@ To build with autotools: ### Windows First, [Python][] 2.6 or 2.7 must be installed as it is required by [GYP][]. -If python is not in your path set the environment variable `PYTHON` to its +If python is not in your path, set the environment variable `PYTHON` to its location. For example: `set PYTHON=C:\Python27\python.exe` To build with Visual Studio, launch a git shell (e.g. Cmd or PowerShell) diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index e85439c05..c6a30e16b 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.0.0], [https://github.com/joyent/libuv/issues]) +AC_INIT([libuv], [1.0.0-rc2], [https://github.com/joyent/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/as_case.m4]) @@ -40,15 +40,16 @@ AC_CHECK_LIB([rt], [clock_gettime]) AC_CHECK_LIB([sendfile], [sendfile]) AC_CHECK_LIB([socket], [socket]) AC_SYS_LARGEFILE -AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])]) -AM_CONDITIONAL([ANDROID],[AS_CASE([$host_os],[linux-android*],[true], [false])]) -AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])]) -AM_CONDITIONAL([FREEBSD],[AS_CASE([$host_os],[freebsd*], [true], [false])]) -AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])]) -AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])]) -AM_CONDITIONAL([OPENBSD],[AS_CASE([$host_os],[openbsd*], [true], [false])]) -AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])]) -AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])]) +AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])]) +AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])]) +AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])]) +AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])]) +AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[freebsd*], [true], [false])]) +AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])]) +AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])]) +AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])]) +AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])]) +AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])]) PANDORA_ENABLE_DTRACE AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes) AM_CONDITIONAL([HAVE_PKG_CONFIG], [test "x$PKG_CONFIG" != "x"]) diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index d2db40813..cc8f5525b 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -20,9 +20,20 @@ Data types Filesystem request type. +.. c:type:: uv_timespec_t + + Portable equivalent of ``struct timespec``. + + :: + + typedef struct { + long tv_sec; + long tv_nsec; + } uv_timespec_t; + .. c:type:: uv_stat_t - Portable equivalent of `struct stat`. + Portable equivalent of ``struct stat``. :: @@ -65,6 +76,7 @@ Data types UV_FS_FTRUNCATE, UV_FS_UTIME, UV_FS_FUTIME, + UV_FS_ACCESS, UV_FS_CHMOD, UV_FS_FCHMOD, UV_FS_FSYNC, @@ -74,7 +86,7 @@ Data types UV_FS_MKDIR, UV_FS_MKDTEMP, UV_FS_RENAME, - UV_FS_READDIR, + UV_FS_SCANDIR, UV_FS_LINK, UV_FS_SYMLINK, UV_FS_READLINK, @@ -85,7 +97,7 @@ Data types .. c:type:: uv_dirent_t Cross platform (reduced) equivalent of ``struct dirent``. - Used in :c:func:`uv_fs_readdir_next`. + Used in :c:func:`uv_fs_scandir_next`. :: @@ -183,11 +195,11 @@ API Equivalent to ``rmdir(2)``. -.. c:function:: int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) -.. c:function:: int uv_fs_readdir_next(uv_fs_t* req, uv_dirent_t* ent) +.. c:function:: int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) +.. c:function:: int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) - Equivalent to ``readdir(2)``, with a slightly different API. Once the callback - for the request is called, the user can use :c:func:`uv_fs_readdir_next` to + Equivalent to ``scandir(3)``, with a slightly different API. Once the callback + for the request is called, the user can use :c:func:`uv_fs_scandir_next` to get `ent` populated with the next directory entry data. When there are no more entries ``UV_EOF`` will be returned. @@ -217,6 +229,10 @@ API Limited equivalent to ``sendfile(2)``. +.. c:function:: int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) + + Equivalent to ``access(2)`` on Unix. Windows uses ``GetFileAttributesW()``. + .. c:function:: int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) .. c:function:: int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb) diff --git a/deps/uv/docs/src/fs_poll.rst b/deps/uv/docs/src/fs_poll.rst index 2e64bfb70..7459aac07 100644 --- a/deps/uv/docs/src/fs_poll.rst +++ b/deps/uv/docs/src/fs_poll.rst @@ -42,6 +42,10 @@ N/A API --- +.. c:function:: int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) + + Initialize the handle. + .. c:function:: int uv_fs_poll_start(uv_fs_poll_t* handle, uv_fs_poll_cb poll_cb, const char* path, unsigned int interval) Check the file at `path` for changes every `interval` milliseconds. diff --git a/deps/uv/docs/src/handle.rst b/deps/uv/docs/src/handle.rst index ae8efb70d..4dcfc3dd9 100644 --- a/deps/uv/docs/src/handle.rst +++ b/deps/uv/docs/src/handle.rst @@ -21,6 +21,15 @@ Data types Union of all handle types. +.. c:type:: void (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) + + Type definition for callback passed to :c:func:`uv_read_start` and + :c:func:`uv_udp_recv_start`. The user must fill the supplied :c:type:`uv_buf_t` + structure with whatever size, as long as it's > 0. A suggested size (65536 at the moment) + is provided, but it doesn't need to be honored. Setting the buffer's length to 0 + will trigger a ``UV_ENOBUFS`` error in the :c:type:`uv_udp_recv_cb` or + :c:type:`uv_read_cb` callback. + .. c:type:: void (*uv_close_cb)(uv_handle_t* handle) Type definition for callback passed to :c:func:`uv_close`. diff --git a/deps/uv/docs/src/index.rst b/deps/uv/docs/src/index.rst index 112a0d04c..ce30cf965 100644 --- a/deps/uv/docs/src/index.rst +++ b/deps/uv/docs/src/index.rst @@ -50,6 +50,17 @@ Installation Installation instructions can be found on `the README `_. +Upgrading +--------- + +Migration guides for different libuv versions, starting with 1.0. + +.. toctree:: + :maxdepth: 1 + + migration_010_100 + + Documentation ------------- diff --git a/deps/uv/docs/src/loop.rst b/deps/uv/docs/src/loop.rst index bc2afe2ff..c63ef7eb6 100644 --- a/deps/uv/docs/src/loop.rst +++ b/deps/uv/docs/src/loop.rst @@ -38,7 +38,9 @@ Public members .. c:member:: void* uv_loop_t.data - Space for user-defined arbitrary data. libuv does not use this field. + Space for user-defined arbitrary data. libuv does not use this field. libuv does, however, + initialize it to NULL in :c:func:`uv_loop_init`, and it poisons the value (on debug builds) + on :c:func:`uv_loop_close`. API diff --git a/deps/uv/docs/src/migration_010_100.rst b/deps/uv/docs/src/migration_010_100.rst new file mode 100644 index 000000000..83b386556 --- /dev/null +++ b/deps/uv/docs/src/migration_010_100.rst @@ -0,0 +1,244 @@ + +.. _migration_010_100: + +libuv 0.10 -> 1.0.0 migration guide +=================================== + +Some APIs changed quite a bit throughout the 1.0.0 development process. Here +is a migration guide for the most significant changes that happened after 0.10 +was released. + + +Loop initialization and closing +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In libuv 0.10 (and previous versions), loops were created with `uv_loop_new`, which +allocated memory for a new loop and initialized it; and destroyed with `uv_loop_delete`, +which destroyed the loop and freed the memory. Starting with 1.0, those are deprecated +and the user is responsible for allocating the memory and then initializing the loop. + +libuv 0.10 + +:: + + uv_loop_t* loop = uv_loop_new(); + ... + uv_loop_delete(loop); + +libuv 1.0 + +:: + + uv_loop_t* loop = malloc(sizeof *loop); + uv_loop_init(loop); + ... + uv_loop_close(loop); + free(loop); + +.. note:: + Error handling was omitted for brevity. Check the documentation for :c:func:`uv_loop_init` + and :c:func:`uv_loop_close`. + + +Error handling +~~~~~~~~~~~~~~ + +Error handling had a major overhaul in libuv 1.0. In general, functions and status parameters +would get 0 for success and -1 for failure on libuv 0.10, and the user had to use `uv_last_error` +to fetch the error code, which was a positive number. + +In 1.0, functions and status parameters contain the actual error code, which is 0 for success, or +a negative number in case of error. + +libuv 0.10 + +:: + + ... assume 'server' is a TCP server which is already listening + r = uv_listen((uv_stream_t*) server, 511, NULL); + if (r == -1) { + uv_err_t err = uv_last_error(uv_default_loop()); + /* err.code contains UV_EADDRINUSE */ + } + +libuv 1.0 + +:: + + ... assume 'server' is a TCP server which is already listening + r = uv_listen((uv_stream_t*) server, 511, NULL); + if (r < 0) { + /* r contains UV_EADDRINUSE */ + } + + +Threadpool changes +~~~~~~~~~~~~~~~~~~ + +In libuv 0.10 Unix used a threadpool which defaulted to 4 threads, while Windows used the +`QueueUserWorkItem` API, which uses a Windows internal threadpool, which defaults to 512 +threads per process. + +In 1.0, we unified both implementations, so Windows now uses the same implementation Unix +does. The threadppol size can be set by exporting the ``UV_THREADPOOL_SIZE`` environment +variable. See :c:ref:`threadpool`. + + +Allocation callback API change +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In libuv 0.10 the callback had to return a filled :c:type:`uv_buf_t` by value: + +:: + + uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) { + return uv_buf_init(malloc(size), size); + } + +In libuv 1.0 a pointer to a buffer is passed to the callbck, which the user +needs to fill: + +:: + + void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { + buf->base = malloc(size); + buf->len = size; + } + + +Unification of IPv4 / IPv6 APIs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +libuv 1.0 unified the IPv4 and IPv6 APIS. There is no longer a `uv_tcp_bind` and `uv_tcp_bind6` +duality, there is only :c:func:`uv_tcp_bind` now. + +IPv4 functions took ``struct sockaddr_in`` structures by value, and IPv6 functions took +``struct sockaddr_in6``. Now functions take a ``struct sockaddr*`` (note it's a pointer). +It can be stack allocated. + +libuv 0.10 + +:: + + struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", 1234); + ... + uv_tcp_bind(&server, addr) + +libuv 1.0 + +:: + + struct sockaddr_in addr; + uv_ip4_addr("0.0.0.0", 1234, &addr) + ... + uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); + +The IPv4 and IPv6 struct creating functions (:c:func:`uv_ip4_addr` and :c:func:`uv_ip6_addr`) +have also changed, make sure you check the documentation. + +..note:: + This change applies to all functions that made a distinction between IPv4 and IPv6 + addresses. + + +Streams / UDP data receive callback API change +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The streams and UDP data receive callbacks now get a pointer to a :c:type:`uv_buf_t` buffer, +not a structure by value. + +libuv 0.10 + +:: + + void on_read(uv_stream_t* handle, + ssize_t nread, + uv_buf_t buf) { + ... + } + + void recv_cb(uv_udp_t* handle, + ssize_t nread, + uv_buf_t buf, + struct sockaddr* addr, + unsigned flags) { + ... + } + +libuv 1.0 + +:: + + void on_read(uv_stream_t* handle, + ssize_t nread, + const uv_buf_t* buf) { + ... + } + + void recv_cb(uv_udp_t* handle, + ssize_t nread, + const uv_buf_t* buf, + const struct sockaddr* addr, + unsigned flags) { + ... + } + + +Receiving handles over pipes API change +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In libuv 0.10 (and earlier versions) the `uv_read2_start` function was used to start reading +data on a pipe, which could also result in the reception of handles over it. The callback +for such function looked like this: + +:: + + void on_read(uv_pipe_t* pipe, + ssize_t nread, + uv_buf_t buf, + uv_handle_type pending) { + ... + } + +In libuv 1.0, `uv_read2_start` was removed, and the user needs to check if there are penging +handles using :c:func:`uv_pipe_pending_count` and :c:func:`uv_pipe_pending_type` while in +the read callback: + +:: + + void on_read(uv_stream_t* handle, + ssize_t nread, + const uv_buf_t* buf) { + ... + while (uv_pipe_pending_count((uv_pipe_t*) handle) != 0) { + pending = uv_pipe_pending_type((uv_pipe_t*) handle); + ... + } + ... + } + + +Extracting the file descriptor out of a handle +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +While it wasn't supported by the API, users often accessed the libuv internals in +order to get access to the file descript of a TCP handle, for example. + +:: + + fd = handle->io_watcher.fd; + +This is now properly exposed through the :c:func:`uv_fileno` function. + + +uv_fs_readdir rename and API change +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`uv_fs_readdir` returned a list of strings in the `req->ptr` field upon completion in +libuv 0.10. In 1.0, this function got renamed to :c:func:`uv_fs_scandir`, since it's +actually implemented using ``scandir(3)``. + +In addition, instead of allocating a full list strings, the user is able to get one +result at a time by using the :c:func:`uv_fs_scandir_next` function. This function +does not need to make a roundtrip to the threadpool, because libuv will keep the +list of *dents* returned by ``scandir(3)`` around. diff --git a/deps/uv/docs/src/process.rst b/deps/uv/docs/src/process.rst index fccfc00ca..b0380ddfb 100644 --- a/deps/uv/docs/src/process.rst +++ b/deps/uv/docs/src/process.rst @@ -212,4 +212,14 @@ API setgid specified, or not having enough memory to allocate for the new process. +.. c:function:: int uv_process_kill(uv_process_t* handle, int signum) + + Sends the specified signal to the given process handle. Check the documentation + on :c:ref:`signal` for signal support, specially on Windows. + +.. c:function:: int uv_kill(int pid, int signum) + + Sends the specified signal to the given PID. Check the documentation + on :c:ref:`signal` for signal support, specially on Windows. + .. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/deps/uv/docs/src/stream.rst b/deps/uv/docs/src/stream.rst index 686efa1b3..44dccbe94 100644 --- a/deps/uv/docs/src/stream.rst +++ b/deps/uv/docs/src/stream.rst @@ -16,6 +16,18 @@ Data types Stream handle type. +.. c:type:: uv_connect_t + + Connect request type. + +.. c:type:: uv_shutdown_t + + Shutdown request type. + +.. c:type:: uv_write_t + + Write request type. + .. c:type:: void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) Callback called when data was read on a stream. @@ -60,6 +72,22 @@ Public members Contains the amount of queued bytes waiting to be sent. Readonly. +.. c:member:: uv_stream_t* uv_connect_t.handle + + Pointer to the stream where this connection request is running. + +.. c:member:: uv_stream_t* uv_shutdown_t.handle + + Pointer to the stream where this shutdown request is running. + +.. c:member:: uv_stream_t* uv_write_t.handle + + Pointer to the stream where this write request is running. + +.. c:member:: uv_stream_t* uv_write_t.send_handle + + Pointer to the stream being sent using this write request.. + .. seealso:: The :c:type:`uv_handle_t` members also apply. diff --git a/deps/uv/docs/src/threading.rst b/deps/uv/docs/src/threading.rst index 38daf4e5a..0d6c0df13 100644 --- a/deps/uv/docs/src/threading.rst +++ b/deps/uv/docs/src/threading.rst @@ -58,6 +58,7 @@ Threads .. c:function:: int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg) .. c:function:: unsigned long uv_thread_self(void) .. c:function:: int uv_thread_join(uv_thread_t *tid) +.. c:function:: int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) Thread-local storage ^^^^^^^^^^^^^^^^^^^^ diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h index a95f48b49..2ae3ca70f 100644 --- a/deps/uv/include/uv-version.h +++ b/deps/uv/include/uv-version.h @@ -34,6 +34,6 @@ #define UV_VERSION_MINOR 0 #define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 -#define UV_VERSION_SUFFIX "rc1" +#define UV_VERSION_SUFFIX "rc2" #endif /* UV_VERSION_H */ diff --git a/deps/uv/include/uv-win.h b/deps/uv/include/uv-win.h index 293b41d08..4abb294c0 100644 --- a/deps/uv/include/uv-win.h +++ b/deps/uv/include/uv-win.h @@ -639,3 +639,15 @@ int uv_utf16_to_utf8(const WCHAR* utf16Buffer, size_t utf16Size, int uv_utf8_to_utf16(const char* utf8Buffer, WCHAR* utf16Buffer, size_t utf16Size); +#ifndef F_OK +#define F_OK 0 +#endif +#ifndef R_OK +#define R_OK 4 +#endif +#ifndef W_OK +#define W_OK 2 +#endif +#ifndef X_OK +#define X_OK 1 +#endif diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 9ee9e9c42..9afdc0b59 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -1022,6 +1022,7 @@ typedef enum { UV_FS_FTRUNCATE, UV_FS_UTIME, UV_FS_FUTIME, + UV_FS_ACCESS, UV_FS_CHMOD, UV_FS_FCHMOD, UV_FS_FSYNC, @@ -1031,7 +1032,7 @@ typedef enum { UV_FS_MKDIR, UV_FS_MKDTEMP, UV_FS_RENAME, - UV_FS_READDIR, + UV_FS_SCANDIR, UV_FS_LINK, UV_FS_SYMLINK, UV_FS_READLINK, @@ -1094,12 +1095,12 @@ UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); -UV_EXTERN int uv_fs_readdir(uv_loop_t* loop, +UV_EXTERN int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb); -UV_EXTERN int uv_fs_readdir_next(uv_fs_t* req, +UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent); UV_EXTERN int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, @@ -1134,6 +1135,11 @@ UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop, int64_t in_offset, size_t length, uv_fs_cb cb); +UV_EXTERN int uv_fs_access(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + int flags, + uv_fs_cb cb); UV_EXTERN int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, @@ -1363,8 +1369,9 @@ UV_EXTERN void uv_key_set(uv_key_t* key, void* value); typedef void (*uv_thread_cb)(void* arg); UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg); -UV_EXTERN unsigned long uv_thread_self(void); +UV_EXTERN uv_thread_t uv_thread_self(void); UV_EXTERN int uv_thread_join(uv_thread_t *tid); +UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2); /* The presence of these unions force similar struct layout. */ #define XX(_, name) uv_ ## name ## _t name; diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 9dcc3935d..7add085fe 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -637,7 +637,7 @@ int uv_cwd(char* buffer, size_t* size) { if (getcwd(buffer, *size) == NULL) return -errno; - *size = strlen(buffer) + 1; + *size = strlen(buffer); return 0; } diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 9bb7baf77..65fd01230 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -295,22 +295,21 @@ done: #if defined(__OpenBSD__) || (defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)) -static int uv__fs_readdir_filter(uv__dirent_t* dent) { +static int uv__fs_scandir_filter(uv__dirent_t* dent) { #else -static int uv__fs_readdir_filter(const uv__dirent_t* dent) { +static int uv__fs_scandir_filter(const uv__dirent_t* dent) { #endif return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0; } -/* This should have been called uv__fs_scandir(). */ -static ssize_t uv__fs_readdir(uv_fs_t* req) { +static ssize_t uv__fs_scandir(uv_fs_t* req) { uv__dirent_t **dents; int saved_errno; int n; dents = NULL; - n = scandir(req->path, &dents, uv__fs_readdir_filter, alphasort); + n = scandir(req->path, &dents, uv__fs_scandir_filter, alphasort); /* NOTE: We will use nbufs as an index field */ req->nbufs = 0; @@ -764,6 +763,7 @@ static void uv__fs_work(struct uv__work* w) { break; switch (req->fs_type) { + X(ACCESS, access(req->path, req->flags)); X(CHMOD, chmod(req->path, req->mode)); X(CHOWN, chown(req->path, req->uid, req->gid)); X(CLOSE, close(req->file)); @@ -779,7 +779,7 @@ static void uv__fs_work(struct uv__work* w) { X(MKDIR, mkdir(req->path, req->mode)); X(MKDTEMP, uv__fs_mkdtemp(req)); X(READ, uv__fs_read(req)); - X(READDIR, uv__fs_readdir(req)); + X(SCANDIR, uv__fs_scandir(req)); X(READLINK, uv__fs_readlink(req)); X(RENAME, rename(req->path, req->new_path)); X(RMDIR, rmdir(req->path)); @@ -854,6 +854,18 @@ static void uv__fs_done(struct uv__work* w, int status) { } +int uv_fs_access(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + int flags, + uv_fs_cb cb) { + INIT(ACCESS); + PATH; + req->flags = flags; + POST; +} + + int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, @@ -1040,12 +1052,12 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, } -int uv_fs_readdir(uv_loop_t* loop, +int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) { - INIT(READDIR); + INIT(SCANDIR); PATH; req->flags = flags; POST; @@ -1167,8 +1179,8 @@ void uv_fs_req_cleanup(uv_fs_t* req) { req->path = NULL; req->new_path = NULL; - if (req->fs_type == UV_FS_READDIR && req->ptr != NULL) - uv__fs_readdir_cleanup(req); + if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL) + uv__fs_scandir_cleanup(req); if (req->ptr != &req->statbuf) free(req->ptr); diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index 522426f63..00579cb8f 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -36,6 +36,11 @@ int uv_thread_join(uv_thread_t *tid) { } +int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) { + return pthread_equal(*t1, *t2); +} + + int uv_mutex_init(uv_mutex_t* mutex) { #if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK) return -pthread_mutex_init(mutex, NULL); diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 13e732dd3..69fc53ae2 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -306,11 +306,11 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { } -unsigned long uv_thread_self(void) { +uv_thread_t uv_thread_self(void) { #ifdef _WIN32 - return (unsigned long) GetCurrentThreadId(); + return GetCurrentThreadId(); #else - return (unsigned long) pthread_self(); + return pthread_self(); #endif } @@ -437,7 +437,7 @@ int uv_fs_event_getpath(uv_fs_event_t* handle, char* buf, size_t* len) { } -void uv__fs_readdir_cleanup(uv_fs_t* req) { +void uv__fs_scandir_cleanup(uv_fs_t* req) { uv__dirent_t** dents; dents = req->ptr; @@ -448,7 +448,7 @@ void uv__fs_readdir_cleanup(uv_fs_t* req) { } -int uv_fs_readdir_next(uv_fs_t* req, uv_dirent_t* ent) { +int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { uv__dirent_t** dents; uv__dirent_t* dent; diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index c9bad2f16..e06606c19 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -109,7 +109,7 @@ size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs); int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value); -void uv__fs_readdir_cleanup(uv_fs_t* req); +void uv__fs_scandir_cleanup(uv_fs_t* req); #define uv__has_active_reqs(loop) \ (QUEUE_EMPTY(&(loop)->active_reqs) == 0) diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index d3801460e..11d20f2db 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -613,11 +613,6 @@ void fs__write(uv_fs_t* req) { if (offset != -1) { memset(&overlapped, 0, sizeof overlapped); - - offset_.QuadPart = offset; - overlapped.Offset = offset_.LowPart; - overlapped.OffsetHigh = offset_.HighPart; - overlapped_ptr = &overlapped; } else { overlapped_ptr = NULL; @@ -627,6 +622,14 @@ void fs__write(uv_fs_t* req) { bytes = 0; do { DWORD incremental_bytes; + + /* WriteFile() does not advance overlapped as ReadFile() does. */ + if (offset != -1) { + offset_.QuadPart = offset + bytes; + overlapped.Offset = offset_.LowPart; + overlapped.OffsetHigh = offset_.HighPart; + } + result = WriteFile(handle, req->bufs[index].base, req->bufs[index].len, @@ -783,7 +786,7 @@ void fs__mkdtemp(uv_fs_t* req) { } -void fs__readdir(uv_fs_t* req) { +void fs__scandir(uv_fs_t* req) { WCHAR* pathw = req->pathw; size_t len = wcslen(pathw); int result; @@ -1220,6 +1223,25 @@ static void fs__sendfile(uv_fs_t* req) { } +static void fs__access(uv_fs_t* req) { + DWORD attr = GetFileAttributesW(req->pathw); + + if (attr == INVALID_FILE_ATTRIBUTES) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + return; + } + + if ((req->flags & W_OK) && + ((attr & FILE_ATTRIBUTE_READONLY) || + (attr & FILE_ATTRIBUTE_DIRECTORY))) { + SET_REQ_WIN32_ERROR(req, UV_EPERM); + return; + } + + SET_REQ_RESULT(req, 0); +} + + static void fs__chmod(uv_fs_t* req) { int result = _wchmod(req->pathw, req->mode); SET_REQ_RESULT(req, result); @@ -1595,6 +1617,7 @@ static void uv__fs_work(struct uv__work* w) { XX(FTRUNCATE, ftruncate) XX(UTIME, utime) XX(FUTIME, futime) + XX(ACCESS, access) XX(CHMOD, chmod) XX(FCHMOD, fchmod) XX(FSYNC, fsync) @@ -1604,7 +1627,7 @@ static void uv__fs_work(struct uv__work* w) { XX(MKDIR, mkdir) XX(MKDTEMP, mkdtemp) XX(RENAME, rename) - XX(READDIR, readdir) + XX(SCANDIR, scandir) XX(LINK, link) XX(SYMLINK, symlink) XX(READLINK, readlink) @@ -1839,11 +1862,11 @@ int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { } -int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, +int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) { int err; - uv_fs_req_init(loop, req, UV_FS_READDIR, cb); + uv_fs_req_init(loop, req, UV_FS_SCANDIR, cb); err = fs__capture_path(loop, req, path, NULL, cb != NULL); if (err) { @@ -1856,7 +1879,7 @@ int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, QUEUE_FS_TP_JOB(loop, req); return 0; } else { - fs__readdir(req); + fs__scandir(req); return req->result; } } @@ -2102,6 +2125,31 @@ int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out, } +int uv_fs_access(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + int flags, + uv_fs_cb cb) { + int err; + + uv_fs_req_init(loop, req, UV_FS_ACCESS, cb); + + err = fs__capture_path(loop, req, path, NULL, cb != NULL); + if (err) + return uv_translate_sys_error(err); + + req->flags = flags; + + if (cb) { + QUEUE_FS_TP_JOB(loop, req); + return 0; + } + + fs__access(req); + return req->result; +} + + int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) { int err; diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c index bf3739985..85c314828 100644 --- a/deps/uv/src/win/poll.c +++ b/deps/uv/src/win/poll.c @@ -530,7 +530,7 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, SO_PROTOCOL_INFOW, (char*) &protocol_info, &len) != 0) { - return WSAGetLastError(); + return uv_translate_sys_error(WSAGetLastError()); } /* Get the peer socket that is needed to enable fast poll. If the returned */ diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c index ccc5579fa..5d8d568c0 100644 --- a/deps/uv/src/win/thread.c +++ b/deps/uv/src/win/thread.c @@ -129,6 +129,11 @@ int uv_thread_join(uv_thread_t *tid) { } +int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) { + return *t1 == *t2; +} + + int uv_mutex_init(uv_mutex_t* mutex) { InitializeCriticalSection(mutex); return 0; diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 8d1aefc53..b7dba7bbd 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -206,7 +206,7 @@ int uv_cwd(char* buffer, size_t* size) { if (r == 0) { return uv_translate_sys_error(GetLastError()); } else if (r > (int) *size) { - *size = r; + *size = r -1; return UV_ENOBUFS; } @@ -223,7 +223,7 @@ int uv_cwd(char* buffer, size_t* size) { return uv_translate_sys_error(GetLastError()); } - *size = r; + *size = r - 1; return 0; } @@ -778,11 +778,76 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { } +static int is_windows_version_or_greater(DWORD os_major, + DWORD os_minor, + WORD service_pack_major, + WORD service_pack_minor) { + OSVERSIONINFOEX osvi; + DWORDLONG condition_mask = 0; + int op = VER_GREATER_EQUAL; + + /* Initialize the OSVERSIONINFOEX structure. */ + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + osvi.dwMajorVersion = os_major; + osvi.dwMinorVersion = os_minor; + osvi.wServicePackMajor = service_pack_major; + osvi.wServicePackMinor = service_pack_minor; + + /* Initialize the condition mask. */ + VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, op); + VER_SET_CONDITION(condition_mask, VER_MINORVERSION, op); + VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, op); + VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, op); + + /* Perform the test. */ + return (int) VerifyVersionInfo( + &osvi, + VER_MAJORVERSION | VER_MINORVERSION | + VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, + condition_mask); +} + + +static int address_prefix_match(int family, + struct sockaddr* address, + struct sockaddr* prefix_address, + int prefix_len) { + uint8_t* address_data; + uint8_t* prefix_address_data; + int i; + + assert(address->sa_family == family); + assert(prefix_address->sa_family == family); + + if (family == AF_INET6) { + address_data = (uint8_t*) &(((struct sockaddr_in6 *) address)->sin6_addr); + prefix_address_data = + (uint8_t*) &(((struct sockaddr_in6 *) prefix_address)->sin6_addr); + } else { + address_data = (uint8_t*) &(((struct sockaddr_in *) address)->sin_addr); + prefix_address_data = + (uint8_t*) &(((struct sockaddr_in *) prefix_address)->sin_addr); + } + + for (i = 0; i < prefix_len >> 3; i++) { + if (address_data[i] != prefix_address_data[i]) + return 0; + } + + if (prefix_len % 8) + return prefix_address_data[i] == + (address_data[i] & (0xff << (8 - prefix_len % 8))); + + return 1; +} + + int uv_interface_addresses(uv_interface_address_t** addresses_ptr, int* count_ptr) { IP_ADAPTER_ADDRESSES* win_address_buf; ULONG win_address_buf_size; - IP_ADAPTER_ADDRESSES* win_address; + IP_ADAPTER_ADDRESSES* adapter; uv_interface_address_t* uv_address_buf; char* name_buf; @@ -791,6 +856,23 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, int count; + int is_vista_or_greater; + ULONG flags; + + is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0); + if (is_vista_or_greater) { + flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER; + } else { + /* We need at least XP SP1. */ + if (!is_windows_version_or_greater(5, 1, 1, 0)) + return UV_ENOTSUP; + + flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX; + } + + /* Fetch the size of the adapters reported by windows, and then get the */ /* list itself. */ win_address_buf_size = 0; @@ -803,7 +885,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, /* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */ /* win_address_buf_size. */ r = GetAdaptersAddresses(AF_UNSPEC, - GAA_FLAG_INCLUDE_PREFIX, + flags, NULL, win_address_buf, &win_address_buf_size); @@ -862,25 +944,23 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, count = 0; uv_address_buf_size = 0; - for (win_address = win_address_buf; - win_address != NULL; - win_address = win_address->Next) { - /* Use IP_ADAPTER_UNICAST_ADDRESS_XP to retain backwards compatibility */ - /* with Windows XP */ - IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address; + for (adapter = win_address_buf; + adapter != NULL; + adapter = adapter->Next) { + IP_ADAPTER_UNICAST_ADDRESS* unicast_address; int name_size; /* Interfaces that are not 'up' should not be reported. Also skip */ /* interfaces that have no associated unicast address, as to avoid */ /* allocating space for the name for this interface. */ - if (win_address->OperStatus != IfOperStatusUp || - win_address->FirstUnicastAddress == NULL) + if (adapter->OperStatus != IfOperStatusUp || + adapter->FirstUnicastAddress == NULL) continue; /* Compute the size of the interface name. */ name_size = WideCharToMultiByte(CP_UTF8, 0, - win_address->FriendlyName, + adapter->FriendlyName, -1, NULL, 0, @@ -894,8 +974,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, /* Count the number of addresses associated with this interface, and */ /* compute the size. */ - for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*) - win_address->FirstUnicastAddress; + for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*) + adapter->FirstUnicastAddress; unicast_address != NULL; unicast_address = unicast_address->Next) { count++; @@ -916,16 +996,15 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, name_buf = (char*) (uv_address_buf + count); /* Fill out the output buffer. */ - for (win_address = win_address_buf; - win_address != NULL; - win_address = win_address->Next) { - IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address; - IP_ADAPTER_PREFIX* prefix; + for (adapter = win_address_buf; + adapter != NULL; + adapter = adapter->Next) { + IP_ADAPTER_UNICAST_ADDRESS* unicast_address; int name_size; size_t max_name_size; - if (win_address->OperStatus != IfOperStatusUp || - win_address->FirstUnicastAddress == NULL) + if (adapter->OperStatus != IfOperStatusUp || + adapter->FirstUnicastAddress == NULL) continue; /* Convert the interface name to UTF8. */ @@ -934,7 +1013,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, max_name_size = INT_MAX; name_size = WideCharToMultiByte(CP_UTF8, 0, - win_address->FriendlyName, + adapter->FriendlyName, -1, name_buf, (int) max_name_size, @@ -946,47 +1025,77 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, return uv_translate_sys_error(GetLastError()); } - prefix = win_address->FirstPrefix; - /* Add an uv_interface_address_t element for every unicast address. */ - /* Walk the prefix list in tandem with the address list. */ - for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*) - win_address->FirstUnicastAddress; - unicast_address != NULL && prefix != NULL; - unicast_address = unicast_address->Next, prefix = prefix->Next) { + for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*) + adapter->FirstUnicastAddress; + unicast_address != NULL; + unicast_address = unicast_address->Next) { struct sockaddr* sa; ULONG prefix_len; sa = unicast_address->Address.lpSockaddr; - prefix_len = prefix->PrefixLength; + + /* XP has no OnLinkPrefixLength field. */ + if (is_vista_or_greater) { + prefix_len = unicast_address->OnLinkPrefixLength; + } else { + /* Prior to Windows Vista the FirstPrefix pointed to the list with + * single prefix for each IP address assigned to the adapter. + * Order of FirstPrefix does not match order of FirstUnicastAddress, + * so we need to find corresponding prefix. + */ + IP_ADAPTER_PREFIX* prefix; + prefix_len = 0; + + for (prefix = adapter->FirstPrefix; prefix; prefix = prefix->Next) { + /* We want the longest matching prefix. */ + if (prefix->Address.lpSockaddr->sa_family != sa->sa_family || + prefix->PrefixLength <= prefix_len) + continue; + + if (address_prefix_match(sa->sa_family, sa, + prefix->Address.lpSockaddr, prefix->PrefixLength)) { + prefix_len = prefix->PrefixLength; + } + } + + /* If there is no matching prefix information, return a single-host + * subnet mask (e.g. 255.255.255.255 for IPv4). + */ + if (!prefix_len) + prefix_len = (sa->sa_family == AF_INET6) ? 128 : 32; + } memset(uv_address, 0, sizeof *uv_address); uv_address->name = name_buf; - if (win_address->PhysicalAddressLength == sizeof(uv_address->phys_addr)) { + if (adapter->PhysicalAddressLength == sizeof(uv_address->phys_addr)) { memcpy(uv_address->phys_addr, - win_address->PhysicalAddress, + adapter->PhysicalAddress, sizeof(uv_address->phys_addr)); } uv_address->is_internal = - (win_address->IfType == IF_TYPE_SOFTWARE_LOOPBACK); + (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK); if (sa->sa_family == AF_INET6) { uv_address->address.address6 = *((struct sockaddr_in6 *) sa); uv_address->netmask.netmask6.sin6_family = AF_INET6; memset(uv_address->netmask.netmask6.sin6_addr.s6_addr, 0xff, prefix_len >> 3); - uv_address->netmask.netmask6.sin6_addr.s6_addr[prefix_len >> 3] = - 0xff << (8 - prefix_len % 8); + /* This check ensures that we don't write past the size of the data. */ + if (prefix_len % 8) { + uv_address->netmask.netmask6.sin6_addr.s6_addr[prefix_len >> 3] = + 0xff << (8 - prefix_len % 8); + } } else { uv_address->address.address4 = *((struct sockaddr_in *) sa); uv_address->netmask.netmask4.sin_family = AF_INET; - uv_address->netmask.netmask4.sin_addr.s_addr = - htonl(0xffffffff << (32 - prefix_len)); + uv_address->netmask.netmask4.sin_addr.s_addr = (prefix_len > 0) ? + htonl(0xffffffff << (32 - prefix_len)) : 0; } uv_address++; diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index a514801b9..3e9dcb81f 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -67,7 +67,7 @@ static int unlink_cb_count; static int mkdir_cb_count; static int mkdtemp_cb_count; static int rmdir_cb_count; -static int readdir_cb_count; +static int scandir_cb_count; static int stat_cb_count; static int rename_cb_count; static int fsync_cb_count; @@ -75,6 +75,7 @@ static int fdatasync_cb_count; static int ftruncate_cb_count; static int sendfile_cb_count; static int fstat_cb_count; +static int access_cb_count; static int chmod_cb_count; static int fchmod_cb_count; static int chown_cb_count; @@ -97,7 +98,7 @@ static uv_fs_t mkdir_req; static uv_fs_t mkdtemp_req1; static uv_fs_t mkdtemp_req2; static uv_fs_t rmdir_req; -static uv_fs_t readdir_req; +static uv_fs_t scandir_req; static uv_fs_t stat_req; static uv_fs_t rename_req; static uv_fs_t fsync_req; @@ -109,6 +110,7 @@ static uv_fs_t futime_req; static char buf[32]; static char test_buf[] = "test-buffer\n"; +static char test_buf2[] = "second-buffer\n"; static uv_buf_t iov; static void check_permission(const char* filename, unsigned int mode) { @@ -164,6 +166,14 @@ static void readlink_cb(uv_fs_t* req) { uv_fs_req_cleanup(req); } + +static void access_cb(uv_fs_t* req) { + ASSERT(req->fs_type == UV_FS_ACCESS); + access_cb_count++; + uv_fs_req_cleanup(req); +} + + static void fchmod_cb(uv_fs_t* req) { ASSERT(req->fs_type == UV_FS_FCHMOD); ASSERT(req->result == 0); @@ -416,18 +426,18 @@ static void rmdir_cb(uv_fs_t* req) { } -static void readdir_cb(uv_fs_t* req) { +static void scandir_cb(uv_fs_t* req) { uv_dirent_t dent; - ASSERT(req == &readdir_req); - ASSERT(req->fs_type == UV_FS_READDIR); + ASSERT(req == &scandir_req); + ASSERT(req->fs_type == UV_FS_SCANDIR); ASSERT(req->result == 2); ASSERT(req->ptr); - while (UV_EOF != uv_fs_readdir_next(req, &dent)) { + while (UV_EOF != uv_fs_scandir_next(req, &dent)) { ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); } - readdir_cb_count++; + scandir_cb_count++; ASSERT(req->path); ASSERT(memcmp(req->path, "test_dir\0", 9) == 0); uv_fs_req_cleanup(req); @@ -435,26 +445,26 @@ static void readdir_cb(uv_fs_t* req) { } -static void empty_readdir_cb(uv_fs_t* req) { +static void empty_scandir_cb(uv_fs_t* req) { uv_dirent_t dent; - ASSERT(req == &readdir_req); - ASSERT(req->fs_type == UV_FS_READDIR); + ASSERT(req == &scandir_req); + ASSERT(req->fs_type == UV_FS_SCANDIR); ASSERT(req->result == 0); ASSERT(req->ptr == NULL); - ASSERT(UV_EOF == uv_fs_readdir_next(req, &dent)); + ASSERT(UV_EOF == uv_fs_scandir_next(req, &dent)); uv_fs_req_cleanup(req); - readdir_cb_count++; + scandir_cb_count++; } -static void file_readdir_cb(uv_fs_t* req) { - ASSERT(req == &readdir_req); - ASSERT(req->fs_type == UV_FS_READDIR); +static void file_scandir_cb(uv_fs_t* req) { + ASSERT(req == &scandir_req); + ASSERT(req->fs_type == UV_FS_SCANDIR); ASSERT(req->result == UV_ENOTDIR); ASSERT(req->ptr == NULL); uv_fs_req_cleanup(req); - readdir_cb_count++; + scandir_cb_count++; } @@ -841,23 +851,23 @@ TEST_IMPL(fs_async_dir) { ASSERT(r == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_readdir(loop, &readdir_req, "test_dir", 0, readdir_cb); + r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, scandir_cb); ASSERT(r == 0); uv_run(loop, UV_RUN_DEFAULT); - ASSERT(readdir_cb_count == 1); + ASSERT(scandir_cb_count == 1); - /* sync uv_fs_readdir */ - r = uv_fs_readdir(loop, &readdir_req, "test_dir", 0, NULL); + /* sync uv_fs_scandir */ + r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, NULL); ASSERT(r == 2); - ASSERT(readdir_req.result == 2); - ASSERT(readdir_req.ptr); - while (UV_EOF != uv_fs_readdir_next(&readdir_req, &dent)) { + ASSERT(scandir_req.result == 2); + ASSERT(scandir_req.ptr); + while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); } - uv_fs_req_cleanup(&readdir_req); - ASSERT(!readdir_req.ptr); + uv_fs_req_cleanup(&scandir_req); + ASSERT(!scandir_req.ptr); r = uv_fs_stat(loop, &stat_req, "test_dir", stat_cb); ASSERT(r == 0); @@ -1119,6 +1129,70 @@ TEST_IMPL(fs_fstat) { } +TEST_IMPL(fs_access) { + int r; + uv_fs_t req; + uv_file file; + + /* Setup. */ + unlink("test_file"); + + loop = uv_default_loop(); + + /* File should not exist */ + r = uv_fs_access(loop, &req, "test_file", F_OK, NULL); + ASSERT(r < 0); + ASSERT(req.result < 0); + uv_fs_req_cleanup(&req); + + /* File should not exist */ + r = uv_fs_access(loop, &req, "test_file", F_OK, access_cb); + ASSERT(r == 0); + uv_run(loop, UV_RUN_DEFAULT); + ASSERT(access_cb_count == 1); + access_cb_count = 0; /* reset for the next test */ + + /* Create file */ + r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, + S_IWUSR | S_IRUSR, NULL); + ASSERT(r >= 0); + ASSERT(req.result >= 0); + file = req.result; + uv_fs_req_cleanup(&req); + + /* File should exist */ + r = uv_fs_access(loop, &req, "test_file", F_OK, NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + uv_fs_req_cleanup(&req); + + /* File should exist */ + r = uv_fs_access(loop, &req, "test_file", F_OK, access_cb); + ASSERT(r == 0); + uv_run(loop, UV_RUN_DEFAULT); + ASSERT(access_cb_count == 1); + access_cb_count = 0; /* reset for the next test */ + + /* Close file */ + r = uv_fs_close(loop, &req, file, NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + uv_fs_req_cleanup(&req); + + /* + * Run the loop just to check we don't have make any extraneous uv_ref() + * calls. This should drop out immediately. + */ + uv_run(loop, UV_RUN_DEFAULT); + + /* Cleanup. */ + unlink("test_file"); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(fs_chmod) { int r; uv_fs_t req; @@ -1604,36 +1678,36 @@ TEST_IMPL(fs_symlink_dir) { ASSERT(r == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_readdir(loop, &readdir_req, "test_dir_symlink", 0, NULL); + r = uv_fs_scandir(loop, &scandir_req, "test_dir_symlink", 0, NULL); ASSERT(r == 2); - ASSERT(readdir_req.result == 2); - ASSERT(readdir_req.ptr); - while (UV_EOF != uv_fs_readdir_next(&readdir_req, &dent)) { + ASSERT(scandir_req.result == 2); + ASSERT(scandir_req.ptr); + while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); } - uv_fs_req_cleanup(&readdir_req); - ASSERT(!readdir_req.ptr); + uv_fs_req_cleanup(&scandir_req); + ASSERT(!scandir_req.ptr); /* unlink will remove the directory symlink */ r = uv_fs_unlink(loop, &req, "test_dir_symlink", NULL); ASSERT(r == 0); uv_fs_req_cleanup(&req); - r = uv_fs_readdir(loop, &readdir_req, "test_dir_symlink", 0, NULL); + r = uv_fs_scandir(loop, &scandir_req, "test_dir_symlink", 0, NULL); ASSERT(r == UV_ENOENT); - uv_fs_req_cleanup(&readdir_req); + uv_fs_req_cleanup(&scandir_req); - r = uv_fs_readdir(loop, &readdir_req, "test_dir", 0, NULL); + r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, NULL); ASSERT(r == 2); - ASSERT(readdir_req.result == 2); - ASSERT(readdir_req.ptr); - while (UV_EOF != uv_fs_readdir_next(&readdir_req, &dent)) { + ASSERT(scandir_req.result == 2); + ASSERT(scandir_req.ptr); + while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); } - uv_fs_req_cleanup(&readdir_req); - ASSERT(!readdir_req.ptr); + uv_fs_req_cleanup(&scandir_req); + ASSERT(!scandir_req.ptr); /* clean-up */ unlink("test_dir/file1"); @@ -1805,7 +1879,7 @@ TEST_IMPL(fs_stat_missing_path) { } -TEST_IMPL(fs_readdir_empty_dir) { +TEST_IMPL(fs_scandir_empty_dir) { const char* path; uv_fs_t req; uv_dirent_t dent; @@ -1820,19 +1894,19 @@ TEST_IMPL(fs_readdir_empty_dir) { /* Fill the req to ensure that required fields are cleaned up */ memset(&req, 0xdb, sizeof(req)); - r = uv_fs_readdir(loop, &req, path, 0, NULL); + r = uv_fs_scandir(loop, &req, path, 0, NULL); ASSERT(r == 0); ASSERT(req.result == 0); ASSERT(req.ptr == NULL); - ASSERT(UV_EOF == uv_fs_readdir_next(&req, &dent)); + ASSERT(UV_EOF == uv_fs_scandir_next(&req, &dent)); uv_fs_req_cleanup(&req); - r = uv_fs_readdir(loop, &readdir_req, path, 0, empty_readdir_cb); + r = uv_fs_scandir(loop, &scandir_req, path, 0, empty_scandir_cb); ASSERT(r == 0); - ASSERT(readdir_cb_count == 0); + ASSERT(scandir_cb_count == 0); uv_run(loop, UV_RUN_DEFAULT); - ASSERT(readdir_cb_count == 1); + ASSERT(scandir_cb_count == 1); uv_fs_rmdir(loop, &req, path, NULL); uv_fs_req_cleanup(&req); @@ -1842,23 +1916,23 @@ TEST_IMPL(fs_readdir_empty_dir) { } -TEST_IMPL(fs_readdir_file) { +TEST_IMPL(fs_scandir_file) { const char* path; int r; path = "test/fixtures/empty_file"; loop = uv_default_loop(); - r = uv_fs_readdir(loop, &readdir_req, path, 0, NULL); + r = uv_fs_scandir(loop, &scandir_req, path, 0, NULL); ASSERT(r == UV_ENOTDIR); - uv_fs_req_cleanup(&readdir_req); + uv_fs_req_cleanup(&scandir_req); - r = uv_fs_readdir(loop, &readdir_req, path, 0, file_readdir_cb); + r = uv_fs_scandir(loop, &scandir_req, path, 0, file_scandir_cb); ASSERT(r == 0); - ASSERT(readdir_cb_count == 0); + ASSERT(scandir_cb_count == 0); uv_run(loop, UV_RUN_DEFAULT); - ASSERT(readdir_cb_count == 1); + ASSERT(scandir_cb_count == 1); MAKE_VALGRIND_HAPPY(); return 0; @@ -2091,3 +2165,64 @@ TEST_IMPL(fs_read_file_eof) { MAKE_VALGRIND_HAPPY(); return 0; } + + +TEST_IMPL(fs_write_multiple_bufs) { + uv_buf_t iovs[2]; + int r; + + /* Setup. */ + unlink("test_file"); + + loop = uv_default_loop(); + + r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, + S_IWUSR | S_IRUSR, NULL); + ASSERT(r >= 0); + ASSERT(open_req1.result >= 0); + uv_fs_req_cleanup(&open_req1); + + iovs[0] = uv_buf_init(test_buf, sizeof(test_buf)); + iovs[1] = uv_buf_init(test_buf2, sizeof(test_buf2)); + r = uv_fs_write(loop, &write_req, open_req1.result, iovs, 2, 0, NULL); + ASSERT(r >= 0); + ASSERT(write_req.result >= 0); + uv_fs_req_cleanup(&write_req); + + r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, 0, NULL); + ASSERT(r >= 0); + ASSERT(open_req1.result >= 0); + uv_fs_req_cleanup(&open_req1); + + memset(buf, 0, sizeof(buf)); + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, NULL); + ASSERT(r >= 0); + ASSERT(read_req.result >= 0); + ASSERT(memcmp(buf, test_buf, sizeof(test_buf)) == 0); + ASSERT(strcmp(buf + sizeof(test_buf), test_buf2) == 0); + uv_fs_req_cleanup(&read_req); + + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, + read_req.result, NULL); + ASSERT(r == 0); + ASSERT(read_req.result == 0); + uv_fs_req_cleanup(&read_req); + + r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + /* Cleanup */ + unlink("test_file"); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 9cb65c393..85ddac82a 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -218,6 +218,7 @@ TEST_DECLARE (fs_async_dir) TEST_DECLARE (fs_async_sendfile) TEST_DECLARE (fs_mkdtemp) TEST_DECLARE (fs_fstat) +TEST_DECLARE (fs_access) TEST_DECLARE (fs_chmod) TEST_DECLARE (fs_chown) TEST_DECLARE (fs_link) @@ -241,10 +242,11 @@ TEST_DECLARE (fs_event_close_in_callback) TEST_DECLARE (fs_event_start_and_close) TEST_DECLARE (fs_event_error_reporting) TEST_DECLARE (fs_event_getpath) -TEST_DECLARE (fs_readdir_empty_dir) -TEST_DECLARE (fs_readdir_file) +TEST_DECLARE (fs_scandir_empty_dir) +TEST_DECLARE (fs_scandir_file) TEST_DECLARE (fs_open_dir) TEST_DECLARE (fs_rename_to_existing_file) +TEST_DECLARE (fs_write_multiple_bufs) TEST_DECLARE (threadpool_queue_work_simple) TEST_DECLARE (threadpool_queue_work_einval) TEST_DECLARE (threadpool_multiple_event_loops) @@ -257,6 +259,7 @@ TEST_DECLARE (thread_local_storage) TEST_DECLARE (thread_mutex) TEST_DECLARE (thread_rwlock) TEST_DECLARE (thread_create) +TEST_DECLARE (thread_equal) TEST_DECLARE (dlerror) TEST_DECLARE (poll_duplex) TEST_DECLARE (poll_unidirectional) @@ -590,6 +593,7 @@ TASK_LIST_START TEST_ENTRY (fs_async_sendfile) TEST_ENTRY (fs_mkdtemp) TEST_ENTRY (fs_fstat) + TEST_ENTRY (fs_access) TEST_ENTRY (fs_chmod) TEST_ENTRY (fs_chown) TEST_ENTRY (fs_utime) @@ -612,10 +616,11 @@ TASK_LIST_START TEST_ENTRY (fs_event_start_and_close) TEST_ENTRY (fs_event_error_reporting) TEST_ENTRY (fs_event_getpath) - TEST_ENTRY (fs_readdir_empty_dir) - TEST_ENTRY (fs_readdir_file) + TEST_ENTRY (fs_scandir_empty_dir) + TEST_ENTRY (fs_scandir_file) TEST_ENTRY (fs_open_dir) TEST_ENTRY (fs_rename_to_existing_file) + TEST_ENTRY (fs_write_multiple_bufs) TEST_ENTRY (threadpool_queue_work_simple) TEST_ENTRY (threadpool_queue_work_einval) TEST_ENTRY (threadpool_multiple_event_loops) @@ -628,6 +633,7 @@ TASK_LIST_START TEST_ENTRY (thread_mutex) TEST_ENTRY (thread_rwlock) TEST_ENTRY (thread_create) + TEST_ENTRY (thread_equal) TEST_ENTRY (dlerror) TEST_ENTRY (ip4_addr) TEST_ENTRY (ip6_addr_link_local) diff --git a/deps/uv/test/test-thread-equal.c b/deps/uv/test/test-thread-equal.c new file mode 100644 index 000000000..27c07ee2c --- /dev/null +++ b/deps/uv/test/test-thread-equal.c @@ -0,0 +1,45 @@ +/* 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. + */ + +#include "uv.h" +#include "task.h" + +uv_thread_t main_thread_id; +uv_thread_t subthreads[2]; + +static void check_thread(void* arg) { + uv_thread_t *thread_id = arg; + uv_thread_t self_id = uv_thread_self(); + ASSERT(uv_thread_equal(&main_thread_id, &self_id) == 0); + *thread_id = uv_thread_self(); +} + +TEST_IMPL(thread_equal) { + uv_thread_t threads[2]; + main_thread_id = uv_thread_self(); + ASSERT(0 != uv_thread_equal(&main_thread_id, &main_thread_id)); + ASSERT(0 == uv_thread_create(threads + 0, check_thread, subthreads + 0)); + ASSERT(0 == uv_thread_create(threads + 1, check_thread, subthreads + 1)); + ASSERT(0 == uv_thread_join(threads + 0)); + ASSERT(0 == uv_thread_join(threads + 1)); + ASSERT(0 == uv_thread_equal(subthreads + 0, subthreads + 1)); + return 0; +} diff --git a/deps/uv/test/test-threadpool-cancel.c b/deps/uv/test/test-threadpool-cancel.c index d852e488b..f999cba81 100644 --- a/deps/uv/test/test-threadpool-cancel.c +++ b/deps/uv/test/test-threadpool-cancel.c @@ -301,7 +301,7 @@ TEST_IMPL(threadpool_cancel_fs) { ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb)); ASSERT(0 == uv_fs_open(loop, reqs + n++, "/", 0, 0, fs_cb)); ASSERT(0 == uv_fs_read(loop, reqs + n++, 0, NULL, 0, 0, fs_cb)); - ASSERT(0 == uv_fs_readdir(loop, reqs + n++, "/", 0, fs_cb)); + ASSERT(0 == uv_fs_scandir(loop, reqs + n++, "/", 0, fs_cb)); ASSERT(0 == uv_fs_readlink(loop, reqs + n++, "/", fs_cb)); ASSERT(0 == uv_fs_rename(loop, reqs + n++, "/", "/", fs_cb)); ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb)); diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 444182b62..27885d23f 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -410,6 +410,7 @@ 'test/test-tcp-write-queue-order.c', 'test/test-threadpool.c', 'test/test-threadpool-cancel.c', + 'test/test-thread-equal.c', 'test/test-mutexes.c', 'test/test-thread.c', 'test/test-barrier.c', -- 2.34.1