diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 6929fff222cd91..a0e3dd46f092f4 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -181,3 +181,19 @@ Johan Bergström Alex Mo Luis Martinez de Bartolome Michael Penick +Michael +Massimiliano Torromeo +TomCrypto +Brett Vickers +Ole André Vadla Ravnås +Kazuho Oku +Ryan Phillips +Brian Green +Devchandra Meetei Leishangthem +Corey Farrell +Per Nilsson +Alan Rogers +Daryl Haresign +Rui Abreu Ferreira +João Reis +farblue68 diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 7bbe5027a7aa28..e5c79808d2e1cc 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,4 +1,108 @@ -2015.02.27, Version 1.4.2 (Stable) +2015.05.07, Version 1.5.0 (Stable), 4e77f74c7b95b639b3397095db1bc5bcc016c203 + +Changes since version 1.4.2: + +* doc: clarify that the thread pool primites are not thread safe (Andrius + Bentkus) + +* aix: always deregister closing fds from epoll (Michael) + +* unix: fix glibc-2.20+ macro incompatibility (Massimiliano Torromeo) + +* doc: add Sphinx plugin for generating links to man pages (Saúl Ibarra + Corretgé) + +* doc: link system and library calls to man pages (Saúl Ibarra Corretgé) + +* doc: document uv_getnameinfo_t.{host|service} (Saúl Ibarra Corretgé) + +* build: update the location of gyp (Stephen von Takach) + +* win: name all anonymous structs and unions (TomCrypto) + +* linux: work around epoll bug in kernels 3.10-3.19 (Ben Noordhuis) + +* darwin: fix size calculation in select() fallback (Ole André Vadla Ravnås) + +* solaris: fix setsockopt for multicast options (Julien Gilli) + +* test: fix race condition in multithreaded test (Ben Noordhuis) + +* doc: fix long lines in tty.rst (Ben Noordhuis) + +* test: use UV_TTY_MODE_* values in tty test (Ben Noordhuis) + +* unix: don't clobber errno in uv_tty_reset_mode() (Ben Noordhuis) + +* unix: reject non-tty fds in uv_tty_init() (Ben Noordhuis) + +* win: fix pipe blocking writes (Alexis Campailla) + +* build: fix cross-compiling for iOS (Steven Kabbes) + +* win: remove unnecessary malloc.h + +* include: use `extern "c++"` for defining C++ code (Kazuho Oku) + +* unix: reap child on execvp() failure (Ryan Phillips) + +* windows: fix handle leak on EMFILE (Brian Green) + +* test: fix tty_file, close handle if initialized (Saúl Ibarra Corretgé) + +* doc: clarify what uv_*_open accepts (Saúl Ibarra Corretgé) + +* doc: clarify that we don't maintain external doc resources (Saúl Ibarra + Corretgé) + +* build: add documentation for ninja support (Devchandra Meetei Leishangthem) + +* doc: document uv_buf_t members (Corey Farrell) + +* linux: fix epoll_pwait() fallback on arm64 (Ben Noordhuis) + +* android: fix compilation warning (Saúl Ibarra Corretgé) + +* unix: don't close the fds we just setup (Sam Roberts) + +* test: spawn child replacing std{out,err} to stderr (Saúl Ibarra Corretgé) + +* unix: fix swapping fds order in uv_spawn (Saúl Ibarra Corretgé) + +* unix: fix potential bug if dup2 fails in uv_spawn (Saúl Ibarra Corretgé) + +* test: remove LOG and LOGF variadic macros (Saúl Ibarra Corretgé) + +* win: fix uv_fs_access on directories (Saúl Ibarra Corretgé) + +* win: fix of double free in uv_uptime (Per Nilsson) + +* unix: open "/dev/null" instead of "/" for emfile_fd (Alan Rogers) + +* docs: add some missing words (Daryl Haresign) + +* unix: clean up uv_fs_open() O_CLOEXEC logic (Ben Noordhuis) + +* build: set SONAME for shared library in uv.gyp (Rui Abreu Ferreira) + +* windows: define snprintf replacement as inline instead of static (Rui Abreu + Ferreira) + +* win: fix unlink of readonly files (João Reis) + +* doc: fix uv_run(UV_RUN_DEFAULT) description (Ben Noordhuis) + +* linux: intercept syscall when running under memory sanitizer (Keno Fischer) + +* aix: fix uv_interface_addresses return value (farblue68) + +* windows: defer reporting TCP write failure until next tick (Saúl Ibarra + Corretgé) + +* test: add test for deferred TCP write failure (Saúl Ibarra Corretgé) + + +2015.02.27, Version 1.4.2 (Stable), 1a7391348a11d5450c0f69c828d5302e2cb842eb Changes since version 1.4.1: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 9c511db47a6c8f..b9fb80c6738b52 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -226,6 +226,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-tcp-write-to-half-open-connection.c \ test/test-tcp-write-after-connect.c \ test/test-tcp-writealot.c \ + test/test-tcp-write-fail.c \ test/test-tcp-try-write.c \ test/test-tcp-write-queue-order.c \ test/test-thread-equal.c \ diff --git a/deps/uv/README.md b/deps/uv/README.md index a267f0d5b527e5..a7da8b898c581d 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -72,19 +72,23 @@ NOTE: Windows users need to use make.bat instead of plain 'make'. Documentation can be browsed online [here](http://docs.libuv.org). +The [tests and benchmarks](https://github.com/libuv/libuv/tree/master/test) +also serve as API specification and usage examples. + ### Other resources * [An Introduction to libuv](http://nikhilm.github.com/uvbook/) — An overview of libuv with tutorials. * [LXJS 2012 talk](http://www.youtube.com/watch?v=nGn60vDSxQ4) — High-level introductory talk about libuv. - * [Tests and benchmarks](https://github.com/libuv/libuv/tree/master/test) - — API specification and usage examples. * [libuv-dox](https://github.com/thlorenz/libuv-dox) — Documenting types and methods of libuv, mostly by reading uv.h. * [learnuv](https://github.com/thlorenz/learnuv) — Learn uv for fun and profit, a self guided workshop to libuv. +These resources are not handled by libuv maintainers and might be out of +date. Please verify it before opening new issues. + ## Build Instructions For GCC there are two build methods: via autotools or via [GYP][]. @@ -113,8 +117,6 @@ To have GYP generate build script for another system, checkout GYP into the project tree manually: $ git clone https://chromium.googlesource.com/external/gyp.git build/gyp - OR - $ svn co http://gyp.googlecode.com/svn/trunk build/gyp ### Unix @@ -153,6 +155,15 @@ Run: Note for UNIX users: compile your project with `-D_LARGEFILE_SOURCE` and `-D_FILE_OFFSET_BITS=64`. GYP builds take care of that automatically. +### Using Ninja + +To use ninja for build on ninja supported platforms, run: + + $ ./gyp_uv.py -f ninja + $ ninja -C out/Debug #for debug build OR + $ ninja -C out/Release + + ### Running tests Run: diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index 9473d5ffcb09d2..71cb4704138c57 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.4.2], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.5.0], [https://github.com/libuv/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/as_case.m4]) diff --git a/deps/uv/docs/src/conf.py b/deps/uv/docs/src/conf.py index f614fc5b434b24..b9eaa137432dea 100644 --- a/deps/uv/docs/src/conf.py +++ b/deps/uv/docs/src/conf.py @@ -38,7 +38,7 @@ def get_libuv_version(): # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +sys.path.insert(0, os.path.abspath('sphinx-plugins')) # -- General configuration ------------------------------------------------ @@ -48,7 +48,7 @@ def get_libuv_version(): # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = [] +extensions = ['manpage'] # Add any paths that contain templates here, relative to this directory. templates_path = ['templates'] diff --git a/deps/uv/docs/src/design.rst b/deps/uv/docs/src/design.rst index 63141bedf58438..34c3cff68e54ca 100644 --- a/deps/uv/docs/src/design.rst +++ b/deps/uv/docs/src/design.rst @@ -40,7 +40,7 @@ The I/O loop The I/O (or event) loop is the central part of libuv. It establishes the content for all I/O operations, and it's meant to be tied to a single thread. One can run multiple event loops as long as each runs in a different thread. The libuv event loop (or any other API involving -the loop or handles, for that matter) **is not thread-safe** except stated otherwise. +the loop or handles, for that matter) **is not thread-safe** except where stated otherwise. The event loop follows the rather usual single threaded asynchronous I/O approach: all (network) I/O is performed on non-blocking sockets which are polled using the best mechanism available @@ -113,7 +113,7 @@ stages of a loop iteration: .. note:: While the polling mechanism is different, libuv makes the execution model consistent - Unix systems and Windows. + across Unix systems and Windows. File I/O diff --git a/deps/uv/docs/src/dns.rst b/deps/uv/docs/src/dns.rst index 3b15377f91e419..1d881580966315 100644 --- a/deps/uv/docs/src/dns.rst +++ b/deps/uv/docs/src/dns.rst @@ -51,6 +51,18 @@ Public members Loop that started this getnameinfo request and where completion will be reported. Readonly. +.. c:member:: char[NI_MAXHOST] uv_getnameinfo_t.host + + Char array containing the resulting host. It's null terminated. + + .. versionchanged:: 1.3.0 the field is declared as public. + +.. c:member:: char[NI_MAXSERV] uv_getnameinfo_t.service + + Char array containing the resulting service. It's null terminated. + + .. versionchanged:: 1.3.0 the field is declared as public. + .. seealso:: The :c:type:`uv_req_t` members also apply. @@ -59,7 +71,7 @@ API .. c:function:: int uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* req, uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service, const struct addrinfo* hints) - Asynchronous ``getaddrinfo(3)``. + Asynchronous :man:`getaddrinfo(3)`. Either node or service may be NULL but not both. @@ -84,7 +96,7 @@ API .. c:function:: int uv_getnameinfo(uv_loop_t* loop, uv_getnameinfo_t* req, uv_getnameinfo_cb getnameinfo_cb, const struct sockaddr* addr, int flags) - Asynchronous ``getnameinfo(3)``. + Asynchronous :man:`getnameinfo(3)`. Returns 0 on success or an error code < 0 on failure. If successful, the callback will get called sometime in the future with the lookup result. diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index cd535f756fc1c9..c2a3fc252a1ffe 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -162,46 +162,46 @@ API .. c:function:: int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) - Equivalent to ``close(2)``. + Equivalent to :man:`close(2)`. .. c:function:: int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb) - Equivalent to ``open(2)``. + Equivalent to :man:`open(2)`. .. c:function:: int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb) - Equivalent to ``preadv(2)``. + Equivalent to :man:`preadv(2)`. .. c:function:: int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) - Equivalent to ``unlink(2)``. + Equivalent to :man:`unlink(2)`. .. c:function:: int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb) - Equivalent to ``pwritev(2)``. + Equivalent to :man:`pwritev(2)`. .. c:function:: int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) - Equivalent to ``mkdir(2)``. + Equivalent to :man:`mkdir(2)`. .. note:: `mode` is currently not implemented on Windows. .. c:function:: int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb) - Equivalent to ``mkdtemp(3)``. + Equivalent to :man:`mkdtemp(3)`. .. note:: The result can be found as a null terminated string at `req->path`. .. c:function:: int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) - Equivalent to ``rmdir(2)``. + Equivalent to :man:`rmdir(2)`. .. 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 ``scandir(3)``, with a slightly different API. Once the callback + Equivalent to :man:`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. @@ -210,49 +210,49 @@ API .. c:function:: int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) .. c:function:: int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) - Equivalent to ``(f/l)stat(2)``. + Equivalent to :man:`stat(2)`, :man:`fstat(2)` and :man:`fstat(2)` respectively. .. c:function:: int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) - Equivalent to ``rename(2)``. + Equivalent to :man:`rename(2)`. .. c:function:: int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) - Equivalent to ``fsync(2)``. + Equivalent to :man:`fsync(2)`. .. c:function:: int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) - Equivalent to ``fdatasync(2)``. + Equivalent to :man:`fdatasync(2)`. .. c:function:: int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int64_t offset, uv_fs_cb cb) - Equivalent to ``ftruncate(2)``. + Equivalent to :man:`ftruncate(2)`. .. c:function:: int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb) - Limited equivalent to ``sendfile(2)``. + Limited equivalent to :man:`sendfile(2)`. .. c:function:: int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) - Equivalent to ``access(2)`` on Unix. Windows uses ``GetFileAttributesW()``. + Equivalent to :man:`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) - Equivalent to ``(f)chmod(2)``. + Equivalent to :man:`chmod(2)` and :man:`fchmod(2)` respectively. .. c:function:: int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb) .. c:function:: int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb) - Equivalent to ``(f)utime(s)(2)``. + Equivalent to :man:`utime(2)` and :man:`futime(2)` respectively. .. c:function:: int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) - Equivalent to ``link(2)``. + Equivalent to :man:`link(2)`. .. c:function:: int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb) - Equivalent to ``symlink(2)``. + Equivalent to :man:`symlink(2)`. .. note:: On Windows the `flags` parameter can be specified to control how the symlink will @@ -265,12 +265,12 @@ API .. c:function:: int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) - Equivalent to ``readlink(2)``. + Equivalent to :man:`readlink(2)`. .. c:function:: int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) .. c:function:: int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) - Equivalent to ``(f)chown(2)``. + Equivalent to :man:`chown(2)` and :man:`fchown(2)` respectively. .. note:: These functions are not implemented on Windows. diff --git a/deps/uv/docs/src/loop.rst b/deps/uv/docs/src/loop.rst index 203672bd34f00a..2a01d796375e8e 100644 --- a/deps/uv/docs/src/loop.rst +++ b/deps/uv/docs/src/loop.rst @@ -92,7 +92,9 @@ API specified mode: - UV_RUN_DEFAULT: Runs the event loop until there are no more active and - referenced handles or requests. Always returns zero. + referenced handles or requests. Returns non-zero if :c:func:`uv_stop` + was called and there are still active handles or requests. Returns + zero in all other cases. - UV_RUN_ONCE: Poll for i/o once. Note that this function blocks if there are no pending callbacks. Returns zero when done (no active handles or requests left), or non-zero if more callbacks are expected (meaning diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index 10c349e9b736f3..bb97a260057fc8 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -15,6 +15,17 @@ Data types Buffer data type. + .. c:member:: char* uv_buf_t.base + + Pointer to the base of the buffer. Readonly. + + .. c:member:: size_t uv_buf_t.len + + Total bytes in the buffer. Readonly. + + .. note:: + On Windows this field is ULONG. + .. c:type:: uv_file Cross platform representation of a file handle. @@ -26,7 +37,7 @@ Data types .. c:type:: uv_os_fd_t Abstract representation of a file descriptor. On Unix systems this is a - `typedef` of `int` and on Windows fa `HANDLE`. + `typedef` of `int` and on Windows a `HANDLE`. .. c:type:: uv_rusage_t @@ -101,7 +112,8 @@ API descriptor. Usually this will be used during initialization to guess the type of the stdio streams. - For ``isatty()`` functionality use this function and test for ``UV_TTY``. + For :man:`isatty(3)` equivalent functionality use this function and test + for ``UV_TTY``. .. c:function:: unsigned int uv_version(void) @@ -195,8 +207,8 @@ API .. c:function:: int uv_inet_ntop(int af, const void* src, char* dst, size_t size) .. c:function:: int uv_inet_pton(int af, const char* src, void* dst) - Cross-platform IPv6-capable implementation of the 'standard' ``inet_ntop()`` - and ``inet_pton()`` functions. On success they return 0. In case of error + Cross-platform IPv6-capable implementation of :man:`inet_ntop(3)` + and :man:`inet_pton(3)`. On success they return 0. In case of error the target `dst` pointer is unmodified. .. c:function:: int uv_exepath(char* buffer, size_t* size) diff --git a/deps/uv/docs/src/pipe.rst b/deps/uv/docs/src/pipe.rst index 8f8402c29bbadd..df896a0583447f 100644 --- a/deps/uv/docs/src/pipe.rst +++ b/deps/uv/docs/src/pipe.rst @@ -40,6 +40,10 @@ API .. versionchanged:: 1.2.1 the file descriptor is set to non-blocking mode. + .. note:: + The passed file descriptor or HANDLE is not checked for its type, but + it's required that it represents a valid pipe. + .. c:function:: int uv_pipe_bind(uv_pipe_t* handle, const char* name) Bind the pipe to a file path (Unix) or a name (Windows). diff --git a/deps/uv/docs/src/poll.rst b/deps/uv/docs/src/poll.rst index 907cb1a613dfbb..6dc41839ac1e92 100644 --- a/deps/uv/docs/src/poll.rst +++ b/deps/uv/docs/src/poll.rst @@ -5,7 +5,7 @@ =================================== Poll handles are used to watch file descriptors for readability and -writability, similar to the purpose of poll(2). +writability, similar to the purpose of :man:`poll(2)`. The purpose of poll handles is to enable integrating external libraries that rely on the event loop to signal it about the socket status changes, like @@ -29,7 +29,7 @@ closed immediately after a call to :c:func:`uv_poll_stop` or :c:func:`uv_close`. .. note:: On windows only sockets can be polled with poll handles. On Unix any file - descriptor that would be accepted by poll(2) can be used. + descriptor that would be accepted by :man:`poll(2)` can be used. Data types diff --git a/deps/uv/docs/src/sphinx-plugins/manpage.py b/deps/uv/docs/src/sphinx-plugins/manpage.py new file mode 100644 index 00000000000000..1d1dc379f410ee --- /dev/null +++ b/deps/uv/docs/src/sphinx-plugins/manpage.py @@ -0,0 +1,46 @@ +# encoding: utf-8 + +# +# Copyright (c) 2013 Dariusz Dwornikowski. All rights reserved. +# +# Adapted from https://github.com/tdi/sphinxcontrib-manpage +# License: Apache 2 +# + + +import re + +from docutils import nodes, utils +from docutils.parsers.rst.roles import set_classes +from string import Template + + +def make_link_node(rawtext, app, name, manpage_num, options): + ref = app.config.man_url_regex + if not ref: + ref = "http://linux.die.net/man/%s/%s" % (manpage_num, name) + else: + s = Template(ref) + ref = s.substitute(num=manpage_num, topic=name) + set_classes(options) + node = nodes.reference(rawtext, "%s(%s)" % (name, manpage_num), refuri=ref, **options) + return node + + +def man_role(name, rawtext, text, lineno, inliner, options={}, content=[]): + app = inliner.document.settings.env.app + p = re.compile("([a-zA-Z0-9_\.-_]+)\((\d)\)") + m = p.match(text) + + manpage_num = m.group(2) + name = m.group(1) + node = make_link_node(rawtext, app, name, manpage_num, options) + return [node], [] + + +def setup(app): + app.info('Initializing manpage plugin') + app.add_role('man', man_role) + app.add_config_value('man_url_regex', None, 'env') + return + diff --git a/deps/uv/docs/src/stream.rst b/deps/uv/docs/src/stream.rst index 1f6682adc1cfc2..880f0e2ebc75d3 100644 --- a/deps/uv/docs/src/stream.rst +++ b/deps/uv/docs/src/stream.rst @@ -104,7 +104,7 @@ API .. c:function:: int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) Start listening for incoming connections. `backlog` indicates the number of - connections the kernel might queue, same as ``listen(2)``. When a new + connections the kernel might queue, same as :man:`listen(2)`. When a new incoming connection is received the :c:type:`uv_connection_cb` callback is called. diff --git a/deps/uv/docs/src/tcp.rst b/deps/uv/docs/src/tcp.rst index 8baedde86c5c15..2b5d268ddd86e6 100644 --- a/deps/uv/docs/src/tcp.rst +++ b/deps/uv/docs/src/tcp.rst @@ -38,6 +38,10 @@ API .. versionchanged:: 1.2.1 the file descriptor is set to non-blocking mode. + .. note:: + The passed file descriptor or SOCKET is not checked for its type, but + it's required that it represents a valid stream socket. + .. c:function:: int uv_tcp_nodelay(uv_tcp_t* handle, int enable) Enable / disable Nagle's algorithm. diff --git a/deps/uv/docs/src/threadpool.rst b/deps/uv/docs/src/threadpool.rst index 89f00844ef2c65..18949507e75004 100644 --- a/deps/uv/docs/src/threadpool.rst +++ b/deps/uv/docs/src/threadpool.rst @@ -18,6 +18,10 @@ libuv preallocates and initializes the maximum number of threads allowed by ``UV_THREADPOOL_SIZE``. This causes a relatively minor memory overhead (~1MB for 128 threads) but increases the performance of threading at runtime. +.. note:: + Note that even though a global thread pool which is shared across all events + loops is used, the functions are not thread safe. + Data types ---------- diff --git a/deps/uv/docs/src/tty.rst b/deps/uv/docs/src/tty.rst index 6c20c84bf75e58..18f34ef46d97b5 100644 --- a/deps/uv/docs/src/tty.rst +++ b/deps/uv/docs/src/tty.rst @@ -24,14 +24,14 @@ Data types :: - typedef enum { - /* Initial/normal terminal mode */ - UV_TTY_MODE_NORMAL, - /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */ - UV_TTY_MODE_RAW, - /* Binary-safe I/O mode for IPC (Unix-only) */ - UV_TTY_MODE_IO - } uv_tty_mode_t; + typedef enum { + /* Initial/normal terminal mode */ + UV_TTY_MODE_NORMAL, + /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */ + UV_TTY_MODE_RAW, + /* Binary-safe I/O mode for IPC (Unix-only) */ + UV_TTY_MODE_IO + } uv_tty_mode_t; @@ -58,18 +58,22 @@ API `readable`, specifies if you plan on calling :c:func:`uv_read_start` with this stream. stdin is readable, stdout is not. - On Unix this function will try to open ``/dev/tty`` and use it if the passed file - descriptor refers to a TTY. This lets libuv put the tty in non-blocking mode - without affecting other processes that share the tty. + On Unix this function will try to open ``/dev/tty`` and use it if the passed + file descriptor refers to a TTY. This lets libuv put the tty in non-blocking + mode without affecting other processes that share the tty. .. note:: - If opening ``/dev/tty`` fails, libuv falls back to blocking writes for non-readable - TTY streams. + If opening ``/dev/tty`` fails, libuv falls back to blocking writes for + non-readable TTY streams. + + .. versionchanged:: 1.5.0: trying to initialize a TTY stream with a file + descriptor that refers to a file returns `UV_EINVAL` + on UNIX. .. c:function:: int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode) - .. versionchanged:: 1.2.0: the mode is specified as a :c:type:`uv_tty_mode_t` - value. + .. versionchanged:: 1.2.0: the mode is specified as a + :c:type:`uv_tty_mode_t` value. Set the TTY using the specified terminal mode. diff --git a/deps/uv/docs/src/udp.rst b/deps/uv/docs/src/udp.rst index 9c4aa2102bdcfc..ec7ce56d38f52c 100644 --- a/deps/uv/docs/src/udp.rst +++ b/deps/uv/docs/src/udp.rst @@ -122,6 +122,10 @@ API .. versionchanged:: 1.2.1 the file descriptor is set to non-blocking mode. + .. note:: + The passed file descriptor or SOCKET is not checked for its type, but + it's required that it represents a valid datagram socket. + .. c:function:: int uv_udp_bind(uv_udp_t* handle, const struct sockaddr* addr, unsigned int flags) Bind the UDP handle to an IP address and port. diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h index 836d399d774a32..0b4e6d781c35f6 100644 --- a/deps/uv/include/uv-version.h +++ b/deps/uv/include/uv-version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 4 -#define UV_VERSION_PATCH 2 +#define UV_VERSION_MINOR 5 +#define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/include/uv-win.h b/deps/uv/include/uv-win.h index 24b22b31a9562b..fd844202b99a1a 100644 --- a/deps/uv/include/uv-win.h +++ b/deps/uv/include/uv-win.h @@ -43,16 +43,6 @@ typedef struct pollfd { # define LOCALE_INVARIANT 0x007f #endif -#ifndef _malloca -# if defined(_DEBUG) -# define _malloca(size) malloc(size) -# define _freea(ptr) free(ptr) -# else -# define _malloca(size) alloca(size) -# define _freea(ptr) -# endif -#endif - #include #include #include @@ -366,8 +356,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); struct { \ OVERLAPPED overlapped; \ size_t queued_bytes; \ - }; \ - }; \ + } io; \ + } u; \ struct uv_req_s* next_req; #define UV_WRITE_PRIVATE_FIELDS \ @@ -419,9 +409,9 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); int activecnt; \ uv_read_t read_req; \ union { \ - struct { uv_stream_connection_fields }; \ - struct { uv_stream_server_fields }; \ - }; + struct { uv_stream_connection_fields } conn; \ + struct { uv_stream_server_fields } serv; \ + } stream; #define uv_tcp_server_fields \ uv_tcp_accept_t* accept_reqs; \ @@ -437,9 +427,9 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); SOCKET socket; \ int delayed_error; \ union { \ - struct { uv_tcp_server_fields }; \ - struct { uv_tcp_connection_fields }; \ - }; + struct { uv_tcp_server_fields } serv; \ + struct { uv_tcp_connection_fields } conn; \ + } tcp; #define UV_UDP_PRIVATE_FIELDS \ SOCKET socket; \ @@ -476,9 +466,9 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); HANDLE handle; \ WCHAR* name; \ union { \ - struct { uv_pipe_server_fields }; \ - struct { uv_pipe_connection_fields }; \ - }; + struct { uv_pipe_server_fields } serv; \ + struct { uv_pipe_connection_fields } conn; \ + } pipe; /* TODO: put the parser states in an union - TTY handles are always */ /* half-duplex so read-state can safely overlap write-state. */ @@ -496,7 +486,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); unsigned char last_key_len; \ WCHAR last_utf16_high_surrogate; \ INPUT_RECORD last_input_record; \ - }; \ + } rd; \ struct { \ /* Used for writable TTY handles */ \ /* utf8-to-utf16 conversion state */ \ @@ -510,8 +500,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); unsigned short ansi_csi_argv[4]; \ COORD saved_position; \ WORD saved_attributes; \ - }; \ - }; + } wr; \ + } tty; #define UV_POLL_PRIVATE_FIELDS \ SOCKET socket; \ @@ -600,7 +590,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); /* TODO: remove me in 0.9. */ \ WCHAR* pathw; \ int fd; \ - }; \ + } file; \ union { \ struct { \ int mode; \ @@ -611,12 +601,12 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); uv_buf_t* bufs; \ int64_t offset; \ uv_buf_t bufsml[4]; \ - }; \ + } info; \ struct { \ double atime; \ double mtime; \ - }; \ - }; + } time; \ + } fs; #define UV_WORK_PRIVATE_FIELDS \ struct uv__work work_req; diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 55f75218b58682..75b3a4a5d2f8bf 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -644,13 +644,13 @@ UV_EXTERN int uv_tty_reset_mode(void); UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); #ifdef __cplusplus -} /* extern "C" */ +extern "C++" { inline int uv_tty_set_mode(uv_tty_t* handle, int mode) { return uv_tty_set_mode(handle, static_cast(mode)); } -extern "C" { +} #endif UV_EXTERN uv_handle_type uv_guess_handle(uv_file file); @@ -799,6 +799,7 @@ struct uv_getnameinfo_s { UV_REQ_FIELDS /* read-only */ uv_loop_t* loop; + /* host and service are marked as private, but they really aren't. */ UV_GETNAMEINFO_PRIVATE_FIELDS }; diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c index ec800c7a323f4b..e21a9cc78b6979 100644 --- a/deps/uv/src/unix/aix.c +++ b/deps/uv/src/unix/aix.c @@ -1111,19 +1111,19 @@ int uv_interface_addresses(uv_interface_address_t** addresses, *count = 0; if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) { - return -ENOSYS; + return -errno; } if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) { - uv__close(sockfd); - return -ENOSYS; + SAVE_ERRNO(uv__close(sockfd)); + return -errno; } ifc.ifc_req = (struct ifreq*)malloc(size); ifc.ifc_len = size; if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { - uv__close(sockfd); - return -ENOSYS; + SAVE_ERRNO(uv__close(sockfd)); + return -errno; } #define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) @@ -1141,8 +1141,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - uv__close(sockfd); - return -ENOSYS; + SAVE_ERRNO(uv__close(sockfd)); + return -errno; } if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) @@ -1218,16 +1218,23 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { struct pollfd* events; uintptr_t i; uintptr_t nfds; + struct poll_ctl pc; assert(loop->watchers != NULL); events = (struct pollfd*) loop->watchers[loop->nwatchers]; nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; - if (events == NULL) - return; - /* Invalidate events with same file descriptor */ - for (i = 0; i < nfds; i++) - if ((int) events[i].fd == fd) - events[i].fd = -1; + if (events != NULL) + /* Invalidate events with same file descriptor */ + for (i = 0; i < nfds; i++) + if ((int) events[i].fd == fd) + events[i].fd = -1; + + /* Remove the file descriptor from the poll set */ + pc.events = 0; + pc.cmd = PS_DELETE; + pc.fd = fd; + if(loop->backend_fd >= 0) + pollset_ctl(loop->backend_fd, &pc, 1); } diff --git a/deps/uv/src/unix/android-ifaddrs.c b/deps/uv/src/unix/android-ifaddrs.c index 3cda578dd1a94c..a99b0191d54808 100644 --- a/deps/uv/src/unix/android-ifaddrs.c +++ b/deps/uv/src/unix/android-ifaddrs.c @@ -24,6 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "android-ifaddrs.h" +#include "uv-common.h" #include #include diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index e7eee2f9abc4ed..7792801e9b6fd6 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -202,6 +202,44 @@ static ssize_t uv__fs_mkdtemp(uv_fs_t* req) { } +static ssize_t uv__fs_open(uv_fs_t* req) { + static int no_cloexec_support; + int r; + + /* Try O_CLOEXEC before entering locks */ + if (no_cloexec_support == 0) { +#ifdef O_CLOEXEC + r = open(req->path, req->flags | O_CLOEXEC, req->mode); + if (r >= 0) + return r; + if (errno != EINVAL) + return r; + no_cloexec_support = 1; +#endif /* O_CLOEXEC */ + } + + if (req->cb != NULL) + uv_rwlock_rdlock(&req->loop->cloexec_lock); + + r = open(req->path, req->flags, req->mode); + + /* In case of failure `uv__cloexec` will leave error in `errno`, + * so it is enough to just set `r` to `-1`. + */ + if (r >= 0 && uv__cloexec(r, 1) != 0) { + r = uv__close(r); + if (r != 0 && r != -EINPROGRESS) + abort(); + r = -1; + } + + if (req->cb != NULL) + uv_rwlock_rdunlock(&req->loop->cloexec_lock); + + return r; +} + + static ssize_t uv__fs_read(uv_fs_t* req) { #if defined(__linux__) static int no_preadv; @@ -661,8 +699,22 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) { dst->st_birthtim.tv_nsec = src->st_birthtimespec.tv_nsec; dst->st_flags = src->st_flags; dst->st_gen = src->st_gen; -#elif !defined(_AIX) && \ - (defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || defined(_XOPEN_SOURCE)) +#elif defined(__ANDROID__) + dst->st_atim.tv_sec = src->st_atime; + dst->st_atim.tv_nsec = src->st_atime_nsec; + dst->st_mtim.tv_sec = src->st_mtime; + dst->st_mtim.tv_nsec = src->st_mtime_nsec; + dst->st_ctim.tv_sec = src->st_ctime; + dst->st_ctim.tv_nsec = src->st_ctime_nsec; + dst->st_birthtim.tv_sec = src->st_ctime; + dst->st_birthtim.tv_nsec = src->st_ctime_nsec; + dst->st_flags = 0; + dst->st_gen = 0; +#elif !defined(_AIX) && ( \ + defined(_BSD_SOURCE) || \ + defined(_SVID_SOURCE) || \ + defined(_XOPEN_SOURCE) || \ + defined(_DEFAULT_SOURCE)) dst->st_atim.tv_sec = src->st_atim.tv_sec; dst->st_atim.tv_nsec = src->st_atim.tv_nsec; dst->st_mtim.tv_sec = src->st_mtim.tv_sec; @@ -729,9 +781,6 @@ static void uv__fs_work(struct uv__work* w) { int retry_on_eintr; uv_fs_t* req; ssize_t r; -#ifdef O_CLOEXEC - static int no_cloexec_support; -#endif /* O_CLOEXEC */ req = container_of(w, uv_fs_t, work_req); retry_on_eintr = !(req->fs_type == UV_FS_CLOSE); @@ -760,6 +809,7 @@ static void uv__fs_work(struct uv__work* w) { X(LINK, link(req->path, req->new_path)); X(MKDIR, mkdir(req->path, req->mode)); X(MKDTEMP, uv__fs_mkdtemp(req)); + X(OPEN, uv__fs_open(req)); X(READ, uv__fs_read(req)); X(SCANDIR, uv__fs_scandir(req)); X(READLINK, uv__fs_readlink(req)); @@ -771,41 +821,10 @@ static void uv__fs_work(struct uv__work* w) { X(UNLINK, unlink(req->path)); X(UTIME, uv__fs_utime(req)); X(WRITE, uv__fs_write(req)); - case UV_FS_OPEN: -#ifdef O_CLOEXEC - /* Try O_CLOEXEC before entering locks */ - if (!no_cloexec_support) { - r = open(req->path, req->flags | O_CLOEXEC, req->mode); - if (r >= 0) - break; - if (errno != EINVAL) - break; - no_cloexec_support = 1; - } -#endif /* O_CLOEXEC */ - if (req->cb != NULL) - uv_rwlock_rdlock(&req->loop->cloexec_lock); - r = open(req->path, req->flags, req->mode); - - /* - * In case of failure `uv__cloexec` will leave error in `errno`, - * so it is enough to just set `r` to `-1`. - */ - if (r >= 0 && uv__cloexec(r, 1) != 0) { - r = uv__close(r); - if (r != 0 && r != -EINPROGRESS) - abort(); - r = -1; - } - if (req->cb != NULL) - uv_rwlock_rdunlock(&req->loop->cloexec_lock); - break; default: abort(); } - #undef X - } - while (r == -1 && errno == EINTR && retry_on_eintr); + } while (r == -1 && errno == EINTR && retry_on_eintr); if (r == -1) req->result = -errno; diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 101dc745499f8d..31db5e29ea68b8 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -55,6 +55,9 @@ #define ACCESS_ONCE(type, var) \ (*(volatile type*) &(var)) +#define ROUND_UP(a, b) \ + ((a) % (b) ? ((a) + (b)) - ((a) % (b)) : (a)) + #define UNREACHABLE() \ do { \ assert(0 && "unreachable code"); \ diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index 33a735dc674f14..d07494dd654bb3 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -130,8 +130,13 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { * * We pass in a dummy epoll_event, to work around a bug in old kernels. */ - if (loop->backend_fd >= 0) + if (loop->backend_fd >= 0) { + /* Work around a bug in kernels 3.10 to 3.19 where passing a struct that + * has the EPOLLWAKEUP flag set generates spurious audit syslog warnings. + */ + memset(&dummy, 0, sizeof(dummy)); uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &dummy); + } } diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c index 7bf2c0f87dbea4..566e1f37cfed12 100644 --- a/deps/uv/src/unix/linux-syscalls.c +++ b/deps/uv/src/unix/linux-syscalls.c @@ -26,6 +26,13 @@ #include #include +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# define MSAN_ACTIVE 1 +# include +# endif +#endif + #if defined(__i386__) # ifndef __NR_socketcall # define __NR_socketcall 102 @@ -310,7 +317,13 @@ int uv__epoll_wait(int epfd, int nevents, int timeout) { #if defined(__NR_epoll_wait) - return syscall(__NR_epoll_wait, epfd, events, nevents, timeout); + int result; + result = syscall(__NR_epoll_wait, epfd, events, nevents, timeout); +#if MSAN_ACTIVE + if (result > 0) + __msan_unpoison(events, sizeof(events[0]) * result); +#endif + return result; #else return errno = ENOSYS, -1; #endif @@ -323,13 +336,19 @@ int uv__epoll_pwait(int epfd, int timeout, uint64_t sigmask) { #if defined(__NR_epoll_pwait) - return syscall(__NR_epoll_pwait, - epfd, - events, - nevents, - timeout, - &sigmask, - sizeof(sigmask)); + int result; + result = syscall(__NR_epoll_pwait, + epfd, + events, + nevents, + timeout, + &sigmask, + sizeof(sigmask)); +#if MSAN_ACTIVE + if (result > 0) + __msan_unpoison(events, sizeof(events[0]) * result); +#endif + return result; #else return errno = ENOSYS, -1; #endif @@ -374,7 +393,13 @@ int uv__inotify_rm_watch(int fd, int32_t wd) { int uv__pipe2(int pipefd[2], int flags) { #if defined(__NR_pipe2) - return syscall(__NR_pipe2, pipefd, flags); + int result; + result = syscall(__NR_pipe2, pipefd, flags); +#if MSAN_ACTIVE + if (!result) + __msan_unpoison(pipefd, sizeof(int[2])); +#endif + return result; #else return errno = ENOSYS, -1; #endif diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index be283b480d6a23..380f3db1dce7f4 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -280,6 +280,21 @@ static void uv__process_child_init(const uv_process_options_t* options, if (options->flags & UV_PROCESS_DETACHED) setsid(); + /* First duplicate low numbered fds, since it's not safe to duplicate them, + * they could get replaced. Example: swapping stdout and stderr; without + * this fd 2 (stderr) would be duplicated into fd 1, thus making both + * stdout and stderr go to the same fd, which was not the intention. */ + for (fd = 0; fd < stdio_count; fd++) { + use_fd = pipes[fd][1]; + if (use_fd < 0 || use_fd >= fd) + continue; + pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count); + if (pipes[fd][1] == -1) { + uv__write_int(error_fd, -errno); + _exit(127); + } + } + for (fd = 0; fd < stdio_count; fd++) { close_fd = pipes[fd][0]; use_fd = pipes[fd][1]; @@ -304,7 +319,12 @@ static void uv__process_child_init(const uv_process_options_t* options, if (fd == use_fd) uv__cloexec(use_fd, 0); else - dup2(use_fd, fd); + fd = dup2(use_fd, fd); + + if (fd == -1) { + uv__write_int(error_fd, -errno); + _exit(127); + } if (fd <= 2) uv__nonblock(fd, 0); @@ -316,8 +336,8 @@ static void uv__process_child_init(const uv_process_options_t* options, for (fd = 0; fd < stdio_count; fd++) { use_fd = pipes[fd][1]; - if (use_fd >= 0 && fd != use_fd) - close(use_fd); + if (use_fd >= stdio_count) + uv__close(use_fd); } if (options->cwd != NULL && chdir(options->cwd)) { @@ -367,6 +387,7 @@ int uv_spawn(uv_loop_t* loop, int err; int exec_errorno; int i; + int status; assert(options->file != NULL); assert(!(options->flags & ~(UV_PROCESS_DETACHED | @@ -453,11 +474,17 @@ int uv_spawn(uv_loop_t* loop, if (r == 0) ; /* okay, EOF */ - else if (r == sizeof(exec_errorno)) - ; /* okay, read errorno */ - else if (r == -1 && errno == EPIPE) - ; /* okay, got EPIPE */ - else + else if (r == sizeof(exec_errorno)) { + do + err = waitpid(pid, &status, 0); /* okay, read errorno */ + while (err == -1 && errno == EINTR); + assert(err == pid); + } else if (r == -1 && errno == EPIPE) { + do + err = waitpid(pid, &status, 0); /* okay, got EPIPE */ + while (err == -1 && errno == EINTR); + assert(err == pid); + } else abort(); uv__close(signal_pipe[0]); diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 518a2fce0f2e46..48827b65d36dee 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -88,7 +88,12 @@ void uv__stream_init(uv_loop_t* loop, stream->write_queue_size = 0; if (loop->emfile_fd == -1) { - err = uv__open_cloexec("/", O_RDONLY); + err = uv__open_cloexec("/dev/null", O_RDONLY); + if (err < 0) + /* In the rare case that "/dev/null" isn't mounted open "/" + * instead. + */ + err = uv__open_cloexec("/", O_RDONLY); if (err >= 0) loop->emfile_fd = err; } @@ -301,7 +306,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { if (fds[1] > max_fd) max_fd = fds[1]; - sread_sz = (max_fd + NBBY) / NBBY; + sread_sz = ROUND_UP(max_fd + 1, sizeof(uint32_t) * NBBY) / NBBY; swrite_sz = sread_sz; s = malloc(sizeof(*s) + sread_sz + swrite_sz); diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c index b1782df95b2010..7783548a6e987d 100644 --- a/deps/uv/src/unix/tty.c +++ b/deps/uv/src/unix/tty.c @@ -35,10 +35,19 @@ static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER; int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { + uv_handle_type type; int flags; int newfd; int r; + /* File descriptors that refer to files cannot be monitored with epoll. + * That restriction also applies to character devices like /dev/random + * (but obviously not /dev/tty.) + */ + type = uv_guess_handle(fd); + if (type == UV_FILE || type == UV_UNKNOWN_HANDLE) + return -EINVAL; + flags = 0; newfd = -1; @@ -54,7 +63,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { * different struct file, hence changing its properties doesn't affect * other processes. */ - if (isatty(fd)) { + if (type == UV_TTY) { r = uv__open_cloexec("/dev/tty", O_RDWR); if (r < 0) { @@ -237,8 +246,10 @@ uv_handle_type uv_guess_handle(uv_file file) { * critical section when the signal was raised. */ int uv_tty_reset_mode(void) { + int saved_errno; int err; + saved_errno = errno; if (!uv_spinlock_trylock(&termios_spinlock)) return -EBUSY; /* In uv_tty_set_mode(). */ @@ -248,5 +259,7 @@ int uv_tty_reset_mode(void) { err = -errno; uv_spinlock_unlock(&termios_spinlock); + errno = saved_errno; + return err; } diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index 941c0aec6e2f0b..22c2e1388e14ac 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -601,40 +601,47 @@ int uv_udp_set_membership(uv_udp_t* handle, } } - -static int uv__setsockopt_maybe_char(uv_udp_t* handle, - int option4, - int option6, - int val) { +static int uv__setsockopt(uv_udp_t* handle, + int option4, + int option6, + const void* val, + size_t size) { int r; -#if defined(__sun) || defined(_AIX) - char arg = val; -#else - int arg = val; -#endif - - if (val < 0 || val > 255) - return -EINVAL; if (handle->flags & UV_HANDLE_IPV6) r = setsockopt(handle->io_watcher.fd, IPPROTO_IPV6, option6, - &arg, - sizeof(arg)); + val, + size); else r = setsockopt(handle->io_watcher.fd, IPPROTO_IP, option4, - &arg, - sizeof(arg)); - + val, + size); if (r) return -errno; return 0; } +static int uv__setsockopt_maybe_char(uv_udp_t* handle, + int option4, + int option6, + int val) { +#if defined(__sun) || defined(_AIX) + char arg = val; +#else + int arg = val; +#endif + + if (val < 0 || val > 255) + return -EINVAL; + + return uv__setsockopt(handle, option4, option6, &arg, sizeof(arg)); +} + int uv_udp_set_broadcast(uv_udp_t* handle, int on) { if (setsockopt(handle->io_watcher.fd, @@ -653,6 +660,20 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { if (ttl < 1 || ttl > 255) return -EINVAL; +/* + * On Solaris and derivatives such as SmartOS, the length of socket options + * is sizeof(int) for IP_TTL and IPV6_UNICAST_HOPS, + * so hardcode the size of these options on this platform, + * and use the general uv__setsockopt_maybe_char call on other platforms. + */ +#if defined(__sun) + return uv__setsockopt(handle, + IP_TTL, + IPV6_UNICAST_HOPS, + &ttl, + sizeof(ttl)); +#endif /* defined(__sun) */ + return uv__setsockopt_maybe_char(handle, IP_TTL, IPV6_UNICAST_HOPS, @@ -661,6 +682,21 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { +/* + * On Solaris and derivatives such as SmartOS, the length of socket options + * is sizeof(int) for IPV6_MULTICAST_HOPS and sizeof(char) for + * IP_MULTICAST_TTL, so hardcode the size of the option in the IPv6 case, + * and use the general uv__setsockopt_maybe_char call otherwise. + */ +#if defined(__sun) + if (handle->flags & UV_HANDLE_IPV6) + return uv__setsockopt(handle, + IP_MULTICAST_TTL, + IPV6_MULTICAST_HOPS, + &ttl, + sizeof(ttl)); +#endif /* defined(__sun) */ + return uv__setsockopt_maybe_char(handle, IP_MULTICAST_TTL, IPV6_MULTICAST_HOPS, @@ -669,6 +705,21 @@ int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { +/* + * On Solaris and derivatives such as SmartOS, the length of socket options + * is sizeof(int) for IPV6_MULTICAST_LOOP and sizeof(char) for + * IP_MULTICAST_LOOP, so hardcode the size of the option in the IPv6 case, + * and use the general uv__setsockopt_maybe_char call otherwise. + */ +#if defined(__sun) + if (handle->flags & UV_HANDLE_IPV6) + return uv__setsockopt(handle, + IP_MULTICAST_LOOP, + IPV6_MULTICAST_LOOP, + &on, + sizeof(on)); +#endif /* defined(__sun) */ + return uv__setsockopt_maybe_char(handle, IP_MULTICAST_LOOP, IPV6_MULTICAST_LOOP, diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 791c09b4e28e77..02341f8b95d9c0 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -379,15 +379,28 @@ int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) { return 0; } +/* The windows implementation does not have the same structure layout as + * the unix implementation (nbufs is not directly inside req but is + * contained in a nested union/struct) so this function locates it. +*/ +static unsigned int* uv__get_nbufs(uv_fs_t* req) { +#ifdef _WIN32 + return &req->fs.info.nbufs; +#else + return &req->nbufs; +#endif +} void uv__fs_scandir_cleanup(uv_fs_t* req) { uv__dirent_t** dents; + unsigned int* nbufs = uv__get_nbufs(req); + dents = req->ptr; - if (req->nbufs > 0 && req->nbufs != (unsigned int) req->result) - req->nbufs--; - for (; req->nbufs < (unsigned int) req->result; req->nbufs++) - free(dents[req->nbufs]); + if (*nbufs > 0 && *nbufs != (unsigned int) req->result) + (*nbufs)--; + for (; *nbufs < (unsigned int) req->result; (*nbufs)++) + free(dents[*nbufs]); } @@ -395,20 +408,22 @@ int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { uv__dirent_t** dents; uv__dirent_t* dent; + unsigned int* nbufs = uv__get_nbufs(req); + dents = req->ptr; /* Free previous entity */ - if (req->nbufs > 0) - free(dents[req->nbufs - 1]); + if (*nbufs > 0) + free(dents[*nbufs - 1]); /* End was already reached */ - if (req->nbufs == (unsigned int) req->result) { + if (*nbufs == (unsigned int) req->result) { free(dents); req->ptr = NULL; return UV_EOF; } - dent = dents[req->nbufs++]; + dent = dents[(*nbufs)++]; ent->name = dent->d_name; #ifdef HAVE_DIRENT_TYPES @@ -522,6 +537,7 @@ void uv_loop_delete(uv_loop_t* loop) { default_loop = default_loop_ptr; err = uv_loop_close(loop); + (void) err; /* Squelch compiler warnings. */ assert(err == 0); if (loop != default_loop) free(loop); diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index a101159438341f..115449224f9651 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c index 5c5514736e8304..a265a272dced19 100644 --- a/deps/uv/src/win/error.c +++ b/deps/uv/src/win/error.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c index 7ad99a88b1ebef..640651b6c9634b 100644 --- a/deps/uv/src/win/fs-event.c +++ b/deps/uv/src/win/fs-event.c @@ -20,7 +20,6 @@ */ #include -#include #include #include #include @@ -39,7 +38,8 @@ static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop, assert(handle->dir_handle != INVALID_HANDLE_VALUE); assert(!handle->req_pending); - memset(&(handle->req.overlapped), 0, sizeof(handle->req.overlapped)); + memset(&(handle->req.u.io.overlapped), 0, + sizeof(handle->req.u.io.overlapped)); if (!ReadDirectoryChangesW(handle->dir_handle, handle->buffer, uv_directory_watcher_buffer_size, @@ -53,7 +53,7 @@ static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop, FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY, NULL, - &handle->req.overlapped, + &handle->req.u.io.overlapped, NULL)) { /* Make this req pending reporting an error. */ SET_REQ_ERROR(&handle->req, GetLastError()); @@ -232,7 +232,8 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } - memset(&(handle->req.overlapped), 0, sizeof(handle->req.overlapped)); + memset(&(handle->req.u.io.overlapped), 0, + sizeof(handle->req.u.io.overlapped)); if (!ReadDirectoryChangesW(handle->dir_handle, handle->buffer, @@ -247,7 +248,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY, NULL, - &handle->req.overlapped, + &handle->req.u.io.overlapped, NULL)) { last_error = GetLastError(); goto error; @@ -349,7 +350,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, file_info = (FILE_NOTIFY_INFORMATION*)(handle->buffer + offset); if (REQ_SUCCESS(req)) { - if (req->overlapped.InternalHigh > 0) { + if (req->u.io.overlapped.InternalHigh > 0) { do { file_info = (FILE_NOTIFY_INFORMATION*)((char*)file_info + offset); assert(!filename); diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 33bc9da304054f..af7ec74276f995 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -161,8 +160,8 @@ INLINE static int fs__capture_path(uv_loop_t* loop, uv_fs_t* req, if (buf_sz == 0) { - req->pathw = NULL; - req->new_pathw = NULL; + req->file.pathw = NULL; + req->fs.info.new_pathw = NULL; req->path = NULL; return 0; } @@ -182,10 +181,10 @@ INLINE static int fs__capture_path(uv_loop_t* loop, uv_fs_t* req, (WCHAR*) pos, pathw_len); assert(r == (DWORD) pathw_len); - req->pathw = (WCHAR*) pos; + req->file.pathw = (WCHAR*) pos; pos += r * sizeof(WCHAR); } else { - req->pathw = NULL; + req->file.pathw = NULL; } if (new_path != NULL) { @@ -196,10 +195,10 @@ INLINE static int fs__capture_path(uv_loop_t* loop, uv_fs_t* req, (WCHAR*) pos, new_pathw_len); assert(r == (DWORD) new_pathw_len); - req->new_pathw = (WCHAR*) pos; + req->fs.info.new_pathw = (WCHAR*) pos; pos += r * sizeof(WCHAR); } else { - req->new_pathw = NULL; + req->fs.info.new_pathw = NULL; } if (!copy_path) { @@ -388,7 +387,7 @@ void fs__open(uv_fs_t* req) { DWORD attributes = 0; HANDLE file; int fd, current_umask; - int flags = req->file_flags; + int flags = req->fs.info.file_flags; /* Obtain the active umask. umask() never fails and returns the previous */ /* umask. */ @@ -450,7 +449,7 @@ void fs__open(uv_fs_t* req) { attributes |= FILE_ATTRIBUTE_NORMAL; if (flags & _O_CREAT) { - if (!((req->mode & ~current_umask) & _S_IWRITE)) { + if (!((req->fs.info.mode & ~current_umask) & _S_IWRITE)) { attributes |= FILE_ATTRIBUTE_READONLY; } } @@ -480,7 +479,7 @@ void fs__open(uv_fs_t* req) { /* Setting this flag makes it possible to open a directory. */ attributes |= FILE_FLAG_BACKUP_SEMANTICS; - file = CreateFileW(req->pathw, + file = CreateFileW(req->file.pathw, access, share, NULL, @@ -512,6 +511,7 @@ void fs__open(uv_fs_t* req) { SET_REQ_WIN32_ERROR(req, GetLastError()); else SET_REQ_WIN32_ERROR(req, UV_UNKNOWN); + CloseHandle(file); return; } @@ -523,7 +523,7 @@ void fs__open(uv_fs_t* req) { } void fs__close(uv_fs_t* req) { - int fd = req->fd; + int fd = req->file.fd; int result; VERIFY_FD(fd, req); @@ -534,8 +534,8 @@ void fs__close(uv_fs_t* req) { void fs__read(uv_fs_t* req) { - int fd = req->fd; - int64_t offset = req->offset; + int fd = req->file.fd; + int64_t offset = req->fs.info.offset; HANDLE handle; OVERLAPPED overlapped, *overlapped_ptr; LARGE_INTEGER offset_; @@ -572,13 +572,13 @@ void fs__read(uv_fs_t* req) { } result = ReadFile(handle, - req->bufs[index].base, - req->bufs[index].len, + req->fs.info.bufs[index].base, + req->fs.info.bufs[index].len, &incremental_bytes, overlapped_ptr); bytes += incremental_bytes; ++index; - } while (result && index < req->nbufs); + } while (result && index < req->fs.info.nbufs); if (result || bytes > 0) { SET_REQ_RESULT(req, bytes); @@ -594,8 +594,8 @@ void fs__read(uv_fs_t* req) { void fs__write(uv_fs_t* req) { - int fd = req->fd; - int64_t offset = req->offset; + int fd = req->file.fd; + int64_t offset = req->fs.info.offset; HANDLE handle; OVERLAPPED overlapped, *overlapped_ptr; LARGE_INTEGER offset_; @@ -630,13 +630,13 @@ void fs__write(uv_fs_t* req) { } result = WriteFile(handle, - req->bufs[index].base, - req->bufs[index].len, + req->fs.info.bufs[index].base, + req->fs.info.bufs[index].len, &incremental_bytes, overlapped_ptr); bytes += incremental_bytes; ++index; - } while (result && index < req->nbufs); + } while (result && index < req->fs.info.nbufs); if (result || bytes > 0) { SET_REQ_RESULT(req, bytes); @@ -647,13 +647,13 @@ void fs__write(uv_fs_t* req) { void fs__rmdir(uv_fs_t* req) { - int result = _wrmdir(req->pathw); + int result = _wrmdir(req->file.pathw); SET_REQ_RESULT(req, result); } void fs__unlink(uv_fs_t* req) { - const WCHAR* pathw = req->pathw; + const WCHAR* pathw = req->file.pathw; HANDLE handle; BY_HANDLE_FILE_INFORMATION info; FILE_DISPOSITION_INFORMATION disposition; @@ -661,7 +661,7 @@ void fs__unlink(uv_fs_t* req) { NTSTATUS status; handle = CreateFileW(pathw, - FILE_READ_ATTRIBUTES | DELETE, + FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, @@ -703,6 +703,24 @@ void fs__unlink(uv_fs_t* req) { } } + if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + /* Remove read-only attribute */ + FILE_BASIC_INFORMATION basic = { 0 }; + + basic.FileAttributes = info.dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY); + + status = pNtSetInformationFile(handle, + &iosb, + &basic, + sizeof basic, + FileBasicInformation); + if (!NT_SUCCESS(status)) { + SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status)); + CloseHandle(handle); + return; + } + } + /* Try to set the delete flag. */ disposition.DeleteFile = TRUE; status = pNtSetInformationFile(handle, @@ -722,7 +740,7 @@ void fs__unlink(uv_fs_t* req) { void fs__mkdir(uv_fs_t* req) { /* TODO: use req->mode. */ - int result = _wmkdir(req->pathw); + int result = _wmkdir(req->file.pathw); SET_REQ_RESULT(req, result); } @@ -740,8 +758,8 @@ void fs__mkdtemp(uv_fs_t* req) { uint64_t v; BOOL released; - len = wcslen(req->pathw); - ep = req->pathw + len; + len = wcslen(req->file.pathw); + ep = req->file.pathw + len; if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) { SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); return; @@ -766,7 +784,7 @@ void fs__mkdtemp(uv_fs_t* req) { v /= num_chars; } - if (_wmkdir(req->pathw) == 0) { + if (_wmkdir(req->file.pathw) == 0) { len = strlen(req->path); wcstombs((char*) req->path + len - num_x, ep - num_x, num_x); SET_REQ_RESULT(req, 0); @@ -810,7 +828,7 @@ void fs__scandir(uv_fs_t* req) { /* Open the directory. */ dir_handle = - CreateFileW(req->pathw, + CreateFileW(req->file.pathw, FILE_LIST_DIRECTORY | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, @@ -956,7 +974,7 @@ void fs__scandir(uv_fs_t* req) { SET_REQ_RESULT(req, dirents_used); /* `nbufs` will be used as index by uv_fs_scandir_next. */ - req->nbufs = 0; + req->fs.info.nbufs = 0; return; @@ -1125,7 +1143,7 @@ INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) { flags |= FILE_FLAG_OPEN_REPARSE_POINT; } - handle = CreateFileW(req->pathw, + handle = CreateFileW(req->file.pathw, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, @@ -1159,19 +1177,19 @@ INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) { static void fs__stat(uv_fs_t* req) { - fs__stat_prepare_path(req->pathw); + fs__stat_prepare_path(req->file.pathw); fs__stat_impl(req, 0); } static void fs__lstat(uv_fs_t* req) { - fs__stat_prepare_path(req->pathw); + fs__stat_prepare_path(req->file.pathw); fs__stat_impl(req, 1); } static void fs__fstat(uv_fs_t* req) { - int fd = req->fd; + int fd = req->file.fd; HANDLE handle; VERIFY_FD(fd, req); @@ -1194,7 +1212,7 @@ static void fs__fstat(uv_fs_t* req) { static void fs__rename(uv_fs_t* req) { - if (!MoveFileExW(req->pathw, req->new_pathw, MOVEFILE_REPLACE_EXISTING)) { + if (!MoveFileExW(req->file.pathw, req->fs.info.new_pathw, MOVEFILE_REPLACE_EXISTING)) { SET_REQ_WIN32_ERROR(req, GetLastError()); return; } @@ -1204,7 +1222,7 @@ static void fs__rename(uv_fs_t* req) { INLINE static void fs__sync_impl(uv_fs_t* req) { - int fd = req->fd; + int fd = req->file.fd; int result; VERIFY_FD(fd, req); @@ -1229,7 +1247,7 @@ static void fs__fdatasync(uv_fs_t* req) { static void fs__ftruncate(uv_fs_t* req) { - int fd = req->fd; + int fd = req->file.fd; HANDLE handle; NTSTATUS status; IO_STATUS_BLOCK io_status; @@ -1239,7 +1257,7 @@ static void fs__ftruncate(uv_fs_t* req) { handle = uv__get_osfhandle(fd); - eof_info.EndOfFile.QuadPart = req->offset; + eof_info.EndOfFile.QuadPart = req->fs.info.offset; status = pNtSetInformationFile(handle, &io_status, @@ -1256,9 +1274,9 @@ static void fs__ftruncate(uv_fs_t* req) { static void fs__sendfile(uv_fs_t* req) { - int fd_in = req->fd, fd_out = req->fd_out; - size_t length = req->bufsml[0].len; - int64_t offset = req->offset; + int fd_in = req->file.fd, fd_out = req->fs.info.fd_out; + size_t length = req->fs.info.bufsml[0].len; + int64_t offset = req->fs.info.offset; const size_t max_buf_size = 65536; size_t buf_size = length < max_buf_size ? length : max_buf_size; int n, result = 0; @@ -1303,32 +1321,39 @@ static void fs__sendfile(uv_fs_t* req) { static void fs__access(uv_fs_t* req) { - DWORD attr = GetFileAttributesW(req->pathw); + DWORD attr = GetFileAttributesW(req->file.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))) { + /* + * Access is possible if + * - write access wasn't requested, + * - or the file isn't read-only, + * - or it's a directory. + * (Directories cannot be read-only on Windows.) + */ + if (!(req->flags & W_OK) || + !(attr & FILE_ATTRIBUTE_READONLY) || + (attr & FILE_ATTRIBUTE_DIRECTORY)) { + SET_REQ_RESULT(req, 0); + } else { 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); + int result = _wchmod(req->file.pathw, req->fs.info.mode); SET_REQ_RESULT(req, result); } static void fs__fchmod(uv_fs_t* req) { - int fd = req->fd; + int fd = req->file.fd; HANDLE handle; NTSTATUS nt_status; IO_STATUS_BLOCK io_status; @@ -1349,7 +1374,7 @@ static void fs__fchmod(uv_fs_t* req) { return; } - if (req->mode & _S_IWRITE) { + if (req->fs.info.mode & _S_IWRITE) { file_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; } else { file_info.FileAttributes |= FILE_ATTRIBUTE_READONLY; @@ -1387,7 +1412,7 @@ INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) { static void fs__utime(uv_fs_t* req) { HANDLE handle; - handle = CreateFileW(req->pathw, + handle = CreateFileW(req->file.pathw, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, @@ -1400,7 +1425,7 @@ static void fs__utime(uv_fs_t* req) { return; } - if (fs__utime_handle(handle, req->atime, req->mtime) != 0) { + if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) { SET_REQ_WIN32_ERROR(req, GetLastError()); CloseHandle(handle); return; @@ -1413,7 +1438,7 @@ static void fs__utime(uv_fs_t* req) { static void fs__futime(uv_fs_t* req) { - int fd = req->fd; + int fd = req->file.fd; HANDLE handle; VERIFY_FD(fd, req); @@ -1424,7 +1449,7 @@ static void fs__futime(uv_fs_t* req) { return; } - if (fs__utime_handle(handle, req->atime, req->mtime) != 0) { + if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) { SET_REQ_WIN32_ERROR(req, GetLastError()); return; } @@ -1434,7 +1459,7 @@ static void fs__futime(uv_fs_t* req) { static void fs__link(uv_fs_t* req) { - DWORD r = CreateHardLinkW(req->new_pathw, req->pathw, NULL); + DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL); if (r == 0) { SET_REQ_WIN32_ERROR(req, GetLastError()); } else { @@ -1614,9 +1639,9 @@ static void fs__create_junction(uv_fs_t* req, const WCHAR* path, static void fs__symlink(uv_fs_t* req) { - WCHAR* pathw = req->pathw; - WCHAR* new_pathw = req->new_pathw; - int flags = req->file_flags; + WCHAR* pathw = req->file.pathw; + WCHAR* new_pathw = req->fs.info.new_pathw; + int flags = req->fs.info.file_flags; int result; @@ -1640,7 +1665,7 @@ static void fs__symlink(uv_fs_t* req) { static void fs__readlink(uv_fs_t* req) { HANDLE handle; - handle = CreateFileW(req->pathw, + handle = CreateFileW(req->file.pathw, 0, 0, NULL, @@ -1739,14 +1764,14 @@ void uv_fs_req_cleanup(uv_fs_t* req) { return; if (req->flags & UV_FS_FREE_PATHS) - free(req->pathw); + free(req->file.pathw); if (req->flags & UV_FS_FREE_PTR) free(req->ptr); req->path = NULL; - req->pathw = NULL; - req->new_pathw = NULL; + req->file.pathw = NULL; + req->fs.info.new_pathw = NULL; req->ptr = NULL; req->flags |= UV_FS_CLEANEDUP; @@ -1764,8 +1789,8 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, return uv_translate_sys_error(err); } - req->file_flags = flags; - req->mode = mode; + req->fs.info.file_flags = flags; + req->fs.info.mode = mode; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -1779,7 +1804,7 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { uv_fs_req_init(loop, req, UV_FS_CLOSE, cb); - req->fd = fd; + req->file.fd = fd; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -1800,19 +1825,19 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_cb cb) { uv_fs_req_init(loop, req, UV_FS_READ, cb); - req->fd = fd; + req->file.fd = fd; - req->nbufs = nbufs; - req->bufs = req->bufsml; - if (nbufs > ARRAY_SIZE(req->bufsml)) - req->bufs = malloc(nbufs * sizeof(*bufs)); + req->fs.info.nbufs = nbufs; + req->fs.info.bufs = req->fs.info.bufsml; + if (nbufs > ARRAY_SIZE(req->fs.info.bufsml)) + req->fs.info.bufs = malloc(nbufs * sizeof(*bufs)); - if (req->bufs == NULL) + if (req->fs.info.bufs == NULL) return UV_ENOMEM; - memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); + memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs)); - req->offset = offset; + req->fs.info.offset = offset; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -1833,19 +1858,19 @@ int uv_fs_write(uv_loop_t* loop, uv_fs_cb cb) { uv_fs_req_init(loop, req, UV_FS_WRITE, cb); - req->fd = fd; + req->file.fd = fd; - req->nbufs = nbufs; - req->bufs = req->bufsml; - if (nbufs > ARRAY_SIZE(req->bufsml)) - req->bufs = malloc(nbufs * sizeof(*bufs)); + req->fs.info.nbufs = nbufs; + req->fs.info.bufs = req->fs.info.bufsml; + if (nbufs > ARRAY_SIZE(req->fs.info.bufsml)) + req->fs.info.bufs = malloc(nbufs * sizeof(*bufs)); - if (req->bufs == NULL) + if (req->fs.info.bufs == NULL) return UV_ENOMEM; - memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); + memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs)); - req->offset = offset; + req->fs.info.offset = offset; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -1889,7 +1914,7 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, return uv_translate_sys_error(err); } - req->mode = mode; + req->fs.info.mode = mode; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -1952,7 +1977,7 @@ int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, return uv_translate_sys_error(err); } - req->file_flags = flags; + req->fs.info.file_flags = flags; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -1996,7 +2021,7 @@ int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, return uv_translate_sys_error(err); } - req->file_flags = flags; + req->fs.info.file_flags = flags; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -2106,7 +2131,7 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { uv_fs_req_init(loop, req, UV_FS_FSTAT, cb); - req->fd = fd; + req->file.fd = fd; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -2141,7 +2166,7 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { uv_fs_req_init(loop, req, UV_FS_FSYNC, cb); - req->fd = fd; + req->file.fd = fd; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -2155,7 +2180,7 @@ int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { uv_fs_req_init(loop, req, UV_FS_FDATASYNC, cb); - req->fd = fd; + req->file.fd = fd; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -2171,8 +2196,8 @@ int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int64_t offset, uv_fs_cb cb) { uv_fs_req_init(loop, req, UV_FS_FTRUNCATE, cb); - req->fd = fd; - req->offset = offset; + req->file.fd = fd; + req->fs.info.offset = offset; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -2189,10 +2214,10 @@ int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out, uv_file fd_in, int64_t in_offset, size_t length, uv_fs_cb cb) { uv_fs_req_init(loop, req, UV_FS_SENDFILE, cb); - req->fd = fd_in; - req->fd_out = fd_out; - req->offset = in_offset; - req->bufsml[0].len = length; + req->file.fd = fd_in; + req->fs.info.fd_out = fd_out; + req->fs.info.offset = in_offset; + req->fs.info.bufsml[0].len = length; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -2240,7 +2265,7 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, return uv_translate_sys_error(err); } - req->mode = mode; + req->fs.info.mode = mode; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -2256,8 +2281,8 @@ int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int mode, uv_fs_cb cb) { uv_fs_req_init(loop, req, UV_FS_FCHMOD, cb); - req->fd = fd; - req->mode = mode; + req->file.fd = fd; + req->fs.info.mode = mode; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -2280,8 +2305,8 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, return uv_translate_sys_error(err); } - req->atime = atime; - req->mtime = mtime; + req->fs.time.atime = atime; + req->fs.time.mtime = mtime; if (cb) { QUEUE_FS_TP_JOB(loop, req); @@ -2297,9 +2322,9 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime, double mtime, uv_fs_cb cb) { uv_fs_req_init(loop, req, UV_FS_FUTIME, cb); - req->fd = fd; - req->atime = atime; - req->mtime = mtime; + req->file.fd = fd; + req->fs.time.atime = atime; + req->fs.time.mtime = mtime; if (cb) { QUEUE_FS_TP_JOB(loop, req); diff --git a/deps/uv/src/win/getaddrinfo.c b/deps/uv/src/win/getaddrinfo.c index f103f5fbd3418a..f3802cd5829208 100644 --- a/deps/uv/src/win/getaddrinfo.c +++ b/deps/uv/src/win/getaddrinfo.c @@ -20,7 +20,6 @@ */ #include -#include #include "uv.h" #include "internal.h" diff --git a/deps/uv/src/win/getnameinfo.c b/deps/uv/src/win/getnameinfo.c index b1d045c79bd9db..66b64b883248e3 100644 --- a/deps/uv/src/win/getnameinfo.c +++ b/deps/uv/src/win/getnameinfo.c @@ -20,7 +20,6 @@ */ #include -#include #include #include "uv.h" diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index 57fab065aa346b..5a0e5420847b12 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -95,15 +95,15 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { handle->reqs_pending = 0; handle->handle = INVALID_HANDLE_VALUE; handle->name = NULL; - handle->ipc_pid = 0; - handle->remaining_ipc_rawdata_bytes = 0; - QUEUE_INIT(&handle->pending_ipc_info.queue); - handle->pending_ipc_info.queue_len = 0; + handle->pipe.conn.ipc_pid = 0; + handle->pipe.conn.remaining_ipc_rawdata_bytes = 0; + QUEUE_INIT(&handle->pipe.conn.pending_ipc_info.queue); + handle->pipe.conn.pending_ipc_info.queue_len = 0; handle->ipc = ipc; - handle->non_overlapped_writes_tail = NULL; - handle->readfile_thread = NULL; + handle->pipe.conn.non_overlapped_writes_tail = NULL; + handle->pipe.conn.readfile_thread = NULL; - uv_req_init(loop, (uv_req_t*) &handle->ipc_header_write_req); + uv_req_init(loop, (uv_req_t*) &handle->pipe.conn.ipc_header_write_req); return 0; } @@ -112,11 +112,11 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { static void uv_pipe_connection_init(uv_pipe_t* handle) { uv_connection_init((uv_stream_t*) handle); handle->read_req.data = handle; - handle->eof_timer = NULL; + handle->pipe.conn.eof_timer = NULL; assert(!(handle->flags & UV_HANDLE_PIPESERVER)); if (pCancelSynchronousIo && handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { - uv_mutex_init(&handle->readfile_mutex); + uv_mutex_init(&handle->pipe.conn.readfile_mutex); handle->flags |= UV_HANDLE_PIPE_READ_CANCELABLE; } } @@ -330,16 +330,16 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { handle->flags &= ~UV_HANDLE_PIPE_READ_CANCELABLE; - uv_mutex_destroy(&handle->readfile_mutex); + uv_mutex_destroy(&handle->pipe.conn.readfile_mutex); } if ((handle->flags & UV_HANDLE_CONNECTION) && - handle->shutdown_req != NULL && - handle->write_reqs_pending == 0) { - req = handle->shutdown_req; + handle->stream.conn.shutdown_req != NULL && + handle->stream.conn.write_reqs_pending == 0) { + req = handle->stream.conn.shutdown_req; /* Clear the shutdown_req field so we don't go here again. */ - handle->shutdown_req = NULL; + handle->stream.conn.shutdown_req = NULL; if (handle->flags & UV__HANDLE_CLOSING) { UNREGISTER_HANDLE_REQ(loop, handle, req); @@ -408,11 +408,11 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { if (handle->flags & UV_HANDLE_CONNECTION) { /* Free pending sockets */ - while (!QUEUE_EMPTY(&handle->pending_ipc_info.queue)) { + while (!QUEUE_EMPTY(&handle->pipe.conn.pending_ipc_info.queue)) { QUEUE* q; SOCKET socket; - q = QUEUE_HEAD(&handle->pending_ipc_info.queue); + q = QUEUE_HEAD(&handle->pipe.conn.pending_ipc_info.queue); QUEUE_REMOVE(q); item = QUEUE_DATA(q, uv__ipc_queue_item_t, member); @@ -428,7 +428,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { if (socket != INVALID_SOCKET) closesocket(socket); } - handle->pending_ipc_info.queue_len = 0; + handle->pipe.conn.pending_ipc_info.queue_len = 0; if (handle->flags & UV_HANDLE_EMULATE_IOCP) { if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { @@ -443,9 +443,9 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { } if (handle->flags & UV_HANDLE_PIPESERVER) { - assert(handle->accept_reqs); - free(handle->accept_reqs); - handle->accept_reqs = NULL; + assert(handle->pipe.serv.accept_reqs); + free(handle->pipe.serv.accept_reqs); + handle->pipe.serv.accept_reqs = NULL; } uv__handle_close(handle); @@ -454,7 +454,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { void uv_pipe_pending_instances(uv_pipe_t* handle, int count) { - handle->pending_instances = count; + handle->pipe.serv.pending_instances = count; handle->flags |= UV_HANDLE_PIPESERVER; } @@ -474,17 +474,17 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { } if (!(handle->flags & UV_HANDLE_PIPESERVER)) { - handle->pending_instances = default_pending_pipe_instances; + handle->pipe.serv.pending_instances = default_pending_pipe_instances; } - handle->accept_reqs = (uv_pipe_accept_t*) - malloc(sizeof(uv_pipe_accept_t) * handle->pending_instances); - if (!handle->accept_reqs) { + handle->pipe.serv.accept_reqs = (uv_pipe_accept_t*) + malloc(sizeof(uv_pipe_accept_t) * handle->pipe.serv.pending_instances); + if (!handle->pipe.serv.accept_reqs) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } - for (i = 0; i < handle->pending_instances; i++) { - req = &handle->accept_reqs[i]; + for (i = 0; i < handle->pipe.serv.pending_instances; i++) { + req = &handle->pipe.serv.accept_reqs[i]; uv_req_init(loop, (uv_req_t*) req); req->type = UV_ACCEPT; req->data = handle; @@ -508,13 +508,13 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { * Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE. * If this fails then there's already a pipe server for the given pipe name. */ - handle->accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name, + handle->pipe.serv.accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); - if (handle->accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) { + if (handle->pipe.serv.accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) { err = GetLastError(); if (err == ERROR_ACCESS_DENIED) { err = WSAEADDRINUSE; /* Translates to UV_EADDRINUSE. */ @@ -524,12 +524,15 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { goto error; } - if (uv_set_pipe_handle(loop, handle, handle->accept_reqs[0].pipeHandle, 0)) { + if (uv_set_pipe_handle(loop, + handle, + handle->pipe.serv.accept_reqs[0].pipeHandle, + 0)) { err = GetLastError(); goto error; } - handle->pending_accepts = NULL; + handle->pipe.serv.pending_accepts = NULL; handle->flags |= UV_HANDLE_PIPESERVER; handle->flags |= UV_HANDLE_BOUND; @@ -541,9 +544,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { handle->name = NULL; } - if (handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) { - CloseHandle(handle->accept_reqs[0].pipeHandle); - handle->accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE; + if (handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) { + CloseHandle(handle->pipe.serv.accept_reqs[0].pipeHandle); + handle->pipe.serv.accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE; } return uv_translate_sys_error(err); @@ -677,15 +680,15 @@ void uv__pipe_pause_read(uv_pipe_t* handle) { any access to a NamedPipe to deadlock if any process has called ReadFile */ HANDLE h; - uv_mutex_lock(&handle->readfile_mutex); - h = handle->readfile_thread; + uv_mutex_lock(&handle->pipe.conn.readfile_mutex); + h = handle->pipe.conn.readfile_thread; while (h) { /* spinlock: we expect this to finish quickly, or we are probably about to deadlock anyways (in the kernel), so it doesn't matter */ pCancelSynchronousIo(h); SwitchToThread(); /* yield thread control briefly */ - h = handle->readfile_thread; + h = handle->pipe.conn.readfile_thread; } } } @@ -693,7 +696,7 @@ void uv__pipe_pause_read(uv_pipe_t* handle) { void uv__pipe_unpause_read(uv_pipe_t* handle) { if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - uv_mutex_unlock(&handle->readfile_mutex); + uv_mutex_unlock(&handle->pipe.conn.readfile_mutex); } } @@ -719,11 +722,11 @@ void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) { } if (handle->flags & UV_HANDLE_PIPESERVER) { - for (i = 0; i < handle->pending_instances; i++) { - pipeHandle = handle->accept_reqs[i].pipeHandle; + for (i = 0; i < handle->pipe.serv.pending_instances; i++) { + pipeHandle = handle->pipe.serv.accept_reqs[i].pipeHandle; if (pipeHandle != INVALID_HANDLE_VALUE) { CloseHandle(pipeHandle); - handle->accept_reqs[i].pipeHandle = INVALID_HANDLE_VALUE; + handle->pipe.serv.accept_reqs[i].pipeHandle = INVALID_HANDLE_VALUE; } } } @@ -796,9 +799,9 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle, assert(req->pipeHandle != INVALID_HANDLE_VALUE); /* Prepare the overlapped structure. */ - memset(&(req->overlapped), 0, sizeof(req->overlapped)); + memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped)); - if (!ConnectNamedPipe(req->pipeHandle, &req->overlapped) && + if (!ConnectNamedPipe(req->pipeHandle, &req->u.io.overlapped) && GetLastError() != ERROR_IO_PENDING) { if (GetLastError() == ERROR_PIPE_CONNECTED) { SET_REQ_SUCCESS(req); @@ -826,14 +829,14 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { int err; if (server->ipc) { - if (QUEUE_EMPTY(&server->pending_ipc_info.queue)) { + if (QUEUE_EMPTY(&server->pipe.conn.pending_ipc_info.queue)) { /* No valid pending sockets. */ return WSAEWOULDBLOCK; } - q = QUEUE_HEAD(&server->pending_ipc_info.queue); + q = QUEUE_HEAD(&server->pipe.conn.pending_ipc_info.queue); QUEUE_REMOVE(q); - server->pending_ipc_info.queue_len--; + server->pipe.conn.pending_ipc_info.queue_len--; item = QUEUE_DATA(q, uv__ipc_queue_item_t, member); err = uv_tcp_import((uv_tcp_t*)client, @@ -849,7 +852,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { /* Find a connection instance that has been connected, but not yet */ /* accepted. */ - req = server->pending_accepts; + req = server->pipe.serv.pending_accepts; if (!req) { /* No valid connections found, so we error out. */ @@ -862,7 +865,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { pipe_client->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; /* Prepare the req to pick up a new connection */ - server->pending_accepts = req->next_pending; + server->pipe.serv.pending_accepts = req->next_pending; req->next_pending = NULL; req->pipeHandle = INVALID_HANDLE_VALUE; @@ -881,7 +884,7 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { int i; if (handle->flags & UV_HANDLE_LISTENING) { - handle->connection_cb = cb; + handle->stream.serv.connection_cb = cb; } if (!(handle->flags & UV_HANDLE_BOUND)) { @@ -898,13 +901,13 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { handle->flags |= UV_HANDLE_LISTENING; INCREASE_ACTIVE_COUNT(loop, handle); - handle->connection_cb = cb; + handle->stream.serv.connection_cb = cb; /* First pipe handle should have already been created in uv_pipe_bind */ - assert(handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE); + assert(handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE); - for (i = 0; i < handle->pending_instances; i++) { - uv_pipe_queue_accept(loop, handle, &handle->accept_reqs[i], i == 0); + for (i = 0; i < handle->pipe.serv.pending_instances; i++) { + uv_pipe_queue_accept(loop, handle, &handle->pipe.serv.accept_reqs[i], i == 0); } return 0; @@ -919,7 +922,7 @@ static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) { uv_loop_t* loop = handle->loop; HANDLE hThread = NULL; DWORD err; - uv_mutex_t *m = &handle->readfile_mutex; + uv_mutex_t *m = &handle->pipe.conn.readfile_mutex; assert(req != NULL); assert(req->type == UV_READ); @@ -930,7 +933,7 @@ static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) { if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hThread, 0, TRUE, DUPLICATE_SAME_ACCESS)) { - handle->readfile_thread = hThread; + handle->pipe.conn.readfile_thread = hThread; } else { hThread = NULL; } @@ -948,10 +951,10 @@ static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) { handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { if (handle->flags & UV_HANDLE_READING) { /* just a brief break to do something else */ - handle->readfile_thread = NULL; + handle->pipe.conn.readfile_thread = NULL; /* resume after it is finished */ uv_mutex_lock(m); - handle->readfile_thread = hThread; + handle->pipe.conn.readfile_thread = hThread; uv_mutex_unlock(m); goto restart_readfile; } else { @@ -960,9 +963,9 @@ static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) { } } if (hThread) { - assert(hThread == handle->readfile_thread); + assert(hThread == handle->pipe.conn.readfile_thread); /* mutex does not control clearing readfile_thread */ - handle->readfile_thread = NULL; + handle->pipe.conn.readfile_thread = NULL; uv_mutex_lock(m); /* only when we hold the mutex lock is it safe to open or close the handle */ @@ -1017,9 +1020,9 @@ static void CALLBACK post_completion_read_wait(void* context, BOOLEAN timed_out) assert(!timed_out); if (!PostQueuedCompletionStatus(handle->loop->iocp, - req->overlapped.InternalHigh, + req->u.io.overlapped.InternalHigh, 0, - &req->overlapped)) { + &req->u.io.overlapped)) { uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); } } @@ -1036,9 +1039,9 @@ static void CALLBACK post_completion_write_wait(void* context, BOOLEAN timed_out assert(!timed_out); if (!PostQueuedCompletionStatus(handle->loop->iocp, - req->overlapped.InternalHigh, + req->u.io.overlapped.InternalHigh, 0, - &req->overlapped)) { + &req->u.io.overlapped)) { uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); } } @@ -1064,9 +1067,9 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { goto error; } } else { - memset(&req->overlapped, 0, sizeof(req->overlapped)); + memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1); + req->u.io.overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1); } /* Do 0-read */ @@ -1074,7 +1077,7 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { &uv_zero_, 0, NULL, - &req->overlapped); + &req->u.io.overlapped); if (!result && GetLastError() != ERROR_IO_PENDING) { /* Make this req pending reporting an error. */ @@ -1091,7 +1094,7 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { } if (req->wait_handle == INVALID_HANDLE_VALUE) { if (!RegisterWaitForSingleObject(&req->wait_handle, - req->overlapped.hEvent, post_completion_read_wait, (void*) req, + req->u.io.overlapped.hEvent, post_completion_read_wait, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { SET_REQ_ERROR(req, GetLastError()); goto error; @@ -1135,14 +1138,14 @@ int uv_pipe_read_start(uv_pipe_t* handle, static void uv_insert_non_overlapped_write_req(uv_pipe_t* handle, uv_write_t* req) { req->next_req = NULL; - if (handle->non_overlapped_writes_tail) { + if (handle->pipe.conn.non_overlapped_writes_tail) { req->next_req = - handle->non_overlapped_writes_tail->next_req; - handle->non_overlapped_writes_tail->next_req = (uv_req_t*)req; - handle->non_overlapped_writes_tail = req; + handle->pipe.conn.non_overlapped_writes_tail->next_req; + handle->pipe.conn.non_overlapped_writes_tail->next_req = (uv_req_t*)req; + handle->pipe.conn.non_overlapped_writes_tail = req; } else { req->next_req = (uv_req_t*)req; - handle->non_overlapped_writes_tail = req; + handle->pipe.conn.non_overlapped_writes_tail = req; } } @@ -1150,13 +1153,13 @@ static void uv_insert_non_overlapped_write_req(uv_pipe_t* handle, static uv_write_t* uv_remove_non_overlapped_write_req(uv_pipe_t* handle) { uv_write_t* req; - if (handle->non_overlapped_writes_tail) { - req = (uv_write_t*)handle->non_overlapped_writes_tail->next_req; + if (handle->pipe.conn.non_overlapped_writes_tail) { + req = (uv_write_t*)handle->pipe.conn.non_overlapped_writes_tail->next_req; - if (req == handle->non_overlapped_writes_tail) { - handle->non_overlapped_writes_tail = NULL; + if (req == handle->pipe.conn.non_overlapped_writes_tail) { + handle->pipe.conn.non_overlapped_writes_tail = NULL; } else { - handle->non_overlapped_writes_tail->next_req = + handle->pipe.conn.non_overlapped_writes_tail->next_req = req->next_req; } @@ -1213,7 +1216,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, req->ipc_header = 0; req->event_handle = NULL; req->wait_handle = INVALID_HANDLE_VALUE; - memset(&req->overlapped, 0, sizeof(req->overlapped)); + memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); if (handle->ipc) { assert(!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); @@ -1223,7 +1226,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, if (send_handle) { tcp_send_handle = (uv_tcp_t*)send_handle; - err = uv_tcp_duplicate_socket(tcp_send_handle, handle->ipc_pid, + err = uv_tcp_duplicate_socket(tcp_send_handle, handle->pipe.conn.ipc_pid, &ipc_frame.socket_info_ex.socket_info); if (err) { return err; @@ -1255,8 +1258,8 @@ static int uv_pipe_write_impl(uv_loop_t* loop, * Try to use the preallocated write req if it's available. * Otherwise allocate a new one. */ - if (handle->ipc_header_write_req.type != UV_WRITE) { - ipc_header_req = (uv_write_t*)&handle->ipc_header_write_req; + if (handle->pipe.conn.ipc_header_write_req.type != UV_WRITE) { + ipc_header_req = (uv_write_t*)&handle->pipe.conn.ipc_header_write_req; } else { ipc_header_req = (uv_write_t*)malloc(sizeof(uv_write_t)); if (!ipc_header_req) { @@ -1272,12 +1275,13 @@ static int uv_pipe_write_impl(uv_loop_t* loop, } /* Write the header or the whole frame. */ - memset(&ipc_header_req->overlapped, 0, sizeof(ipc_header_req->overlapped)); + memset(&ipc_header_req->u.io.overlapped, 0, + sizeof(ipc_header_req->u.io.overlapped)); /* Using overlapped IO, but wait for completion before returning. This write is blocking because ipc_frame is on stack. */ - ipc_header_req->overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); - if (!ipc_header_req->overlapped.hEvent) { + ipc_header_req->u.io.overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); + if (!ipc_header_req->u.io.overlapped.hEvent) { uv_fatal_error(GetLastError(), "CreateEvent"); } @@ -1286,29 +1290,29 @@ static int uv_pipe_write_impl(uv_loop_t* loop, ipc_frame.header.flags & UV_IPC_TCP_SERVER ? sizeof(ipc_frame) : sizeof(ipc_frame.header), NULL, - &ipc_header_req->overlapped); + &ipc_header_req->u.io.overlapped); if (!result && GetLastError() != ERROR_IO_PENDING) { err = GetLastError(); - CloseHandle(ipc_header_req->overlapped.hEvent); + CloseHandle(ipc_header_req->u.io.overlapped.hEvent); return err; } if (!result) { /* Request not completed immediately. Wait for it.*/ - if (WaitForSingleObject(ipc_header_req->overlapped.hEvent, INFINITE) != + if (WaitForSingleObject(ipc_header_req->u.io.overlapped.hEvent, INFINITE) != WAIT_OBJECT_0) { err = GetLastError(); - CloseHandle(ipc_header_req->overlapped.hEvent); + CloseHandle(ipc_header_req->u.io.overlapped.hEvent); return err; } } - ipc_header_req->queued_bytes = 0; - CloseHandle(ipc_header_req->overlapped.hEvent); - ipc_header_req->overlapped.hEvent = NULL; + ipc_header_req->u.io.queued_bytes = 0; + CloseHandle(ipc_header_req->u.io.overlapped.hEvent); + ipc_header_req->u.io.overlapped.hEvent = NULL; REGISTER_HANDLE_REQ(loop, handle, ipc_header_req); handle->reqs_pending++; - handle->write_reqs_pending++; + handle->stream.conn.write_reqs_pending++; /* If we don't have any raw data to write - we're done. */ if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { @@ -1331,28 +1335,28 @@ static int uv_pipe_write_impl(uv_loop_t* loop, return err; } else { /* Request completed immediately. */ - req->queued_bytes = 0; + req->u.io.queued_bytes = 0; } REGISTER_HANDLE_REQ(loop, handle, req); handle->reqs_pending++; - handle->write_reqs_pending++; + handle->stream.conn.write_reqs_pending++; POST_COMPLETION_FOR_REQ(loop, req); return 0; } else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { req->write_buffer = bufs[0]; uv_insert_non_overlapped_write_req(handle, req); - if (handle->write_reqs_pending == 0) { + if (handle->stream.conn.write_reqs_pending == 0) { uv_queue_non_overlapped_write(handle); } /* Request queued by the kernel. */ - req->queued_bytes = uv__count_bufs(bufs, nbufs); - handle->write_queue_size += req->queued_bytes; + req->u.io.queued_bytes = bufs[0].len; + handle->write_queue_size += req->u.io.queued_bytes; } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) { /* Using overlapped IO, but wait for completion before returning */ - req->overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); - if (!req->overlapped.hEvent) { + req->u.io.overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); + if (!req->u.io.overlapped.hEvent) { uv_fatal_error(GetLastError(), "CreateEvent"); } @@ -1360,40 +1364,40 @@ static int uv_pipe_write_impl(uv_loop_t* loop, bufs[0].base, bufs[0].len, NULL, - &req->overlapped); + &req->u.io.overlapped); if (!result && GetLastError() != ERROR_IO_PENDING) { err = GetLastError(); - CloseHandle(req->overlapped.hEvent); + CloseHandle(req->u.io.overlapped.hEvent); return err; } if (result) { /* Request completed immediately. */ - req->queued_bytes = 0; + req->u.io.queued_bytes = 0; } else { - assert(ipc_header_req != NULL); /* Request queued by the kernel. */ - if (WaitForSingleObject(ipc_header_req->overlapped.hEvent, INFINITE) != + req->u.io.queued_bytes = bufs[0].len; + handle->write_queue_size += req->u.io.queued_bytes; + if (WaitForSingleObject(req->u.io.overlapped.hEvent, INFINITE) != WAIT_OBJECT_0) { err = GetLastError(); - CloseHandle(ipc_header_req->overlapped.hEvent); + CloseHandle(req->u.io.overlapped.hEvent); return uv_translate_sys_error(err); } } - CloseHandle(req->overlapped.hEvent); + CloseHandle(req->u.io.overlapped.hEvent); REGISTER_HANDLE_REQ(loop, handle, req); handle->reqs_pending++; - handle->write_reqs_pending++; - POST_COMPLETION_FOR_REQ(loop, req); + handle->stream.conn.write_reqs_pending++; return 0; } else { result = WriteFile(handle->handle, bufs[0].base, bufs[0].len, NULL, - &req->overlapped); + &req->u.io.overlapped); if (!result && GetLastError() != ERROR_IO_PENDING) { return GetLastError(); @@ -1401,11 +1405,11 @@ static int uv_pipe_write_impl(uv_loop_t* loop, if (result) { /* Request completed immediately. */ - req->queued_bytes = 0; + req->u.io.queued_bytes = 0; } else { /* Request queued by the kernel. */ - req->queued_bytes = uv__count_bufs(bufs, nbufs); - handle->write_queue_size += req->queued_bytes; + req->u.io.queued_bytes = bufs[0].len; + handle->write_queue_size += req->u.io.queued_bytes; } if (handle->flags & UV_HANDLE_EMULATE_IOCP) { @@ -1414,7 +1418,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_fatal_error(GetLastError(), "CreateEvent"); } if (!RegisterWaitForSingleObject(&req->wait_handle, - req->overlapped.hEvent, post_completion_write_wait, (void*) req, + req->u.io.overlapped.hEvent, post_completion_write_wait, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { return GetLastError(); } @@ -1423,7 +1427,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, REGISTER_HANDLE_REQ(loop, handle, req); handle->reqs_pending++; - handle->write_reqs_pending++; + handle->stream.conn.write_reqs_pending++; return 0; } @@ -1500,8 +1504,8 @@ void uv__pipe_insert_pending_socket(uv_pipe_t* handle, memcpy(&item->socket_info_ex, info, sizeof(item->socket_info_ex)); item->tcp_connection = tcp_connection; - QUEUE_INSERT_TAIL(&handle->pending_ipc_info.queue, &item->member); - handle->pending_ipc_info.queue_len++; + QUEUE_INSERT_TAIL(&handle->pipe.conn.pending_ipc_info.queue, &item->member); + handle->pipe.conn.pending_ipc_info.queue_len++; } @@ -1544,7 +1548,7 @@ void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, if (handle->ipc) { /* Use the IPC framing protocol to read the incoming data. */ - if (handle->remaining_ipc_rawdata_bytes == 0) { + if (handle->pipe.conn.remaining_ipc_rawdata_bytes == 0) { /* We're reading a new frame. First, read the header. */ assert(avail >= sizeof(ipc_frame.header)); @@ -1587,12 +1591,12 @@ void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, } if (ipc_frame.header.flags & UV_IPC_RAW_DATA) { - handle->remaining_ipc_rawdata_bytes = + handle->pipe.conn.remaining_ipc_rawdata_bytes = ipc_frame.header.raw_data_length; continue; } } else { - avail = min(avail, (DWORD)handle->remaining_ipc_rawdata_bytes); + avail = min(avail, (DWORD)handle->pipe.conn.remaining_ipc_rawdata_bytes); } } @@ -1610,9 +1614,9 @@ void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, NULL)) { /* Successful read */ if (handle->ipc) { - assert(handle->remaining_ipc_rawdata_bytes >= bytes); - handle->remaining_ipc_rawdata_bytes = - handle->remaining_ipc_rawdata_bytes - bytes; + assert(handle->pipe.conn.remaining_ipc_rawdata_bytes >= bytes); + handle->pipe.conn.remaining_ipc_rawdata_bytes = + handle->pipe.conn.remaining_ipc_rawdata_bytes - bytes; } handle->read_cb((uv_stream_t*)handle, bytes, &buf); @@ -1643,8 +1647,8 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, assert(handle->type == UV_NAMED_PIPE); - assert(handle->write_queue_size >= req->queued_bytes); - handle->write_queue_size -= req->queued_bytes; + assert(handle->write_queue_size >= req->u.io.queued_bytes); + handle->write_queue_size -= req->u.io.queued_bytes; UNREGISTER_HANDLE_REQ(loop, handle, req); @@ -1660,7 +1664,7 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, } if (req->ipc_header) { - if (req == &handle->ipc_header_write_req) { + if (req == &handle->pipe.conn.ipc_header_write_req) { req->type = UV_UNKNOWN_REQ; } else { free(req); @@ -1672,16 +1676,16 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, } } - handle->write_reqs_pending--; + handle->stream.conn.write_reqs_pending--; if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE && - handle->non_overlapped_writes_tail) { - assert(handle->write_reqs_pending > 0); + handle->pipe.conn.non_overlapped_writes_tail) { + assert(handle->stream.conn.write_reqs_pending > 0); uv_queue_non_overlapped_write(handle); } - if (handle->shutdown_req != NULL && - handle->write_reqs_pending == 0) { + if (handle->stream.conn.shutdown_req != NULL && + handle->stream.conn.write_reqs_pending == 0) { uv_want_endgame(loop, (uv_handle_t*)handle); } @@ -1704,11 +1708,11 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, if (REQ_SUCCESS(req)) { assert(req->pipeHandle != INVALID_HANDLE_VALUE); - req->next_pending = handle->pending_accepts; - handle->pending_accepts = req; + req->next_pending = handle->pipe.serv.pending_accepts; + handle->pipe.serv.pending_accepts = req; - if (handle->connection_cb) { - handle->connection_cb((uv_stream_t*)handle, 0); + if (handle->stream.serv.connection_cb) { + handle->stream.serv.connection_cb((uv_stream_t*)handle, 0); } } else { if (req->pipeHandle != INVALID_HANDLE_VALUE) { @@ -1781,23 +1785,23 @@ void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, static void eof_timer_init(uv_pipe_t* pipe) { int r; - assert(pipe->eof_timer == NULL); + assert(pipe->pipe.conn.eof_timer == NULL); assert(pipe->flags & UV_HANDLE_CONNECTION); - pipe->eof_timer = (uv_timer_t*) malloc(sizeof *pipe->eof_timer); + pipe->pipe.conn.eof_timer = (uv_timer_t*) malloc(sizeof *pipe->pipe.conn.eof_timer); - r = uv_timer_init(pipe->loop, pipe->eof_timer); + r = uv_timer_init(pipe->loop, pipe->pipe.conn.eof_timer); assert(r == 0); /* timers can't fail */ - pipe->eof_timer->data = pipe; - uv_unref((uv_handle_t*) pipe->eof_timer); + pipe->pipe.conn.eof_timer->data = pipe; + uv_unref((uv_handle_t*) pipe->pipe.conn.eof_timer); } static void eof_timer_start(uv_pipe_t* pipe) { assert(pipe->flags & UV_HANDLE_CONNECTION); - if (pipe->eof_timer != NULL) { - uv_timer_start(pipe->eof_timer, eof_timer_cb, eof_timeout, 0); + if (pipe->pipe.conn.eof_timer != NULL) { + uv_timer_start(pipe->pipe.conn.eof_timer, eof_timer_cb, eof_timeout, 0); } } @@ -1805,8 +1809,8 @@ static void eof_timer_start(uv_pipe_t* pipe) { static void eof_timer_stop(uv_pipe_t* pipe) { assert(pipe->flags & UV_HANDLE_CONNECTION); - if (pipe->eof_timer != NULL) { - uv_timer_stop(pipe->eof_timer); + if (pipe->pipe.conn.eof_timer != NULL) { + uv_timer_stop(pipe->pipe.conn.eof_timer); } } @@ -1829,7 +1833,7 @@ static void eof_timer_cb(uv_timer_t* timer) { /* Therefore we check here if the read request has completed but will */ /* be processed later. */ if ((pipe->flags & UV_HANDLE_READ_PENDING) && - HasOverlappedIoCompleted(&pipe->read_req.overlapped)) { + HasOverlappedIoCompleted(&pipe->read_req.u.io.overlapped)) { return; } @@ -1850,9 +1854,9 @@ static void eof_timer_cb(uv_timer_t* timer) { static void eof_timer_destroy(uv_pipe_t* pipe) { assert(pipe->flags & UV_HANDLE_CONNECTION); - if (pipe->eof_timer) { - uv_close((uv_handle_t*) pipe->eof_timer, eof_timer_close_cb); - pipe->eof_timer = NULL; + if (pipe->pipe.conn.eof_timer) { + uv_close((uv_handle_t*) pipe->pipe.conn.eof_timer, eof_timer_close_cb); + pipe->pipe.conn.eof_timer = NULL; } } @@ -1903,8 +1907,8 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { if (pipe->ipc) { assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); - pipe->ipc_pid = uv_parent_pid(); - assert(pipe->ipc_pid != -1); + pipe->pipe.conn.ipc_pid = uv_parent_pid(); + assert(pipe->pipe.conn.ipc_pid != -1); } return 0; } @@ -2027,7 +2031,7 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) int uv_pipe_pending_count(uv_pipe_t* handle) { if (!handle->ipc) return 0; - return handle->pending_ipc_info.queue_len; + return handle->pipe.conn.pending_ipc_info.queue_len; } @@ -2060,7 +2064,7 @@ int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) { if (!handle->ipc) return UV_UNKNOWN_HANDLE; - if (handle->pending_ipc_info.queue_len == 0) + if (handle->pipe.conn.pending_ipc_info.queue_len == 0) return UV_UNKNOWN_HANDLE; else return UV_TCP; diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c index 4d8e1f99f65cb5..ce861d6ffc41eb 100644 --- a/deps/uv/src/win/poll.c +++ b/deps/uv/src/win/poll.c @@ -112,12 +112,12 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { afd_poll_info->Handles[0].Events |= AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL; } - memset(&req->overlapped, 0, sizeof req->overlapped); + memset(&req->u.io.overlapped, 0, sizeof req->u.io.overlapped); result = uv_msafd_poll((SOCKET) handle->peer_socket, afd_poll_info, afd_poll_info, - &req->overlapped); + &req->u.io.overlapped); if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) { /* Queue this req, reporting an error. */ SET_REQ_ERROR(req, WSAGetLastError()); @@ -380,7 +380,7 @@ static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) { } SET_REQ_SUCCESS(req); - req->overlapped.InternalHigh = (DWORD) reported_events; + req->u.io.overlapped.InternalHigh = (DWORD) reported_events; POST_COMPLETION_FOR_REQ(handle->loop, req); return 0; @@ -442,7 +442,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, } } else { /* Got some events. */ - int events = req->overlapped.InternalHigh & handle->events & ~mask_events; + int events = req->u.io.overlapped.InternalHigh & handle->events & ~mask_events; if (events != 0) { handle->poll_cb(handle, 0, events); } diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c index 3a0106f82d63e3..887595f89cc9b6 100644 --- a/deps/uv/src/win/process.c +++ b/deps/uv/src/win/process.c @@ -707,7 +707,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { } /* second pass: copy to UTF-16 environment block */ - dst_copy = _malloca(env_len * sizeof(WCHAR)); + dst_copy = malloc(env_len * sizeof(WCHAR)); if (!dst_copy) { return ERROR_OUTOFMEMORY; } @@ -725,7 +725,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { (int) (env_len - (ptr - dst_copy))); if (len <= 0) { DWORD err = GetLastError(); - _freea(dst_copy); + free(dst_copy); return err; } *ptr_copy++ = ptr; @@ -767,7 +767,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { /* final pass: copy, in sort order, and inserting required variables */ dst = malloc((1+env_len) * sizeof(WCHAR)); if (!dst) { - _freea(dst_copy); + free(dst_copy); return ERROR_OUTOFMEMORY; } @@ -812,7 +812,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { assert(env_len == (ptr - dst)); *ptr = L'\0'; - _freea(dst_copy); + free(dst_copy); *dst_ptr = dst; return 0; } @@ -1124,7 +1124,7 @@ int uv_spawn(uv_loop_t* loop, if (fdopt->flags & UV_CREATE_PIPE && fdopt->data.stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) fdopt->data.stream)->ipc) { - ((uv_pipe_t*) fdopt->data.stream)->ipc_pid = info.dwProcessId; + ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_pid = info.dwProcessId; } } diff --git a/deps/uv/src/win/req-inl.h b/deps/uv/src/win/req-inl.h index 46c7d9b106a869..b5e502eef5521a 100644 --- a/deps/uv/src/win/req-inl.h +++ b/deps/uv/src/win/req-inl.h @@ -29,7 +29,7 @@ #define SET_REQ_STATUS(req, status) \ - (req)->overlapped.Internal = (ULONG_PTR) (status) + (req)->u.io.overlapped.Internal = (ULONG_PTR) (status) #define SET_REQ_ERROR(req, error) \ SET_REQ_STATUS((req), NTSTATUS_FROM_WIN32((error))) @@ -38,7 +38,7 @@ SET_REQ_STATUS((req), STATUS_SUCCESS) #define GET_REQ_STATUS(req) \ - ((NTSTATUS) (req)->overlapped.Internal) + ((NTSTATUS) (req)->u.io.overlapped.Internal) #define REQ_SUCCESS(req) \ (NT_SUCCESS(GET_REQ_STATUS((req)))) @@ -74,7 +74,7 @@ if (!PostQueuedCompletionStatus((loop)->iocp, \ 0, \ 0, \ - &((req)->overlapped))) { \ + &((req)->u.io.overlapped))) { \ uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); \ } @@ -86,13 +86,24 @@ INLINE static void uv_req_init(uv_loop_t* loop, uv_req_t* req) { INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) { - return CONTAINING_RECORD(overlapped, uv_req_t, overlapped); + return CONTAINING_RECORD(overlapped, uv_req_t, u.io.overlapped); } INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) { req->next_req = NULL; if (loop->pending_reqs_tail) { +#ifdef _DEBUG + /* Ensure the request is not already in the queue, or the queue + * will get corrupted. + */ + uv_req_t* current = loop->pending_reqs_tail; + do { + assert(req != current); + current = current->next_req; + } while(current != loop->pending_reqs_tail); +#endif + req->next_req = loop->pending_reqs_tail->next_req; loop->pending_reqs_tail->next_req = req; loop->pending_reqs_tail = req; diff --git a/deps/uv/src/win/stream-inl.h b/deps/uv/src/win/stream-inl.h index 97a6b90b50560a..b7a3c11958c274 100644 --- a/deps/uv/src/win/stream-inl.h +++ b/deps/uv/src/win/stream-inl.h @@ -41,7 +41,7 @@ INLINE static void uv_stream_init(uv_loop_t* loop, INLINE static void uv_connection_init(uv_stream_t* handle) { handle->flags |= UV_HANDLE_CONNECTION; - handle->write_reqs_pending = 0; + handle->stream.conn.write_reqs_pending = 0; uv_req_init(handle->loop, (uv_req_t*) &(handle->read_req)); handle->read_req.event_handle = NULL; @@ -49,7 +49,7 @@ INLINE static void uv_connection_init(uv_stream_t* handle) { handle->read_req.type = UV_READ; handle->read_req.data = handle; - handle->shutdown_req = NULL; + handle->stream.conn.shutdown_req = NULL; } diff --git a/deps/uv/src/win/stream.c b/deps/uv/src/win/stream.c index 36d88d00bd9893..a2466e5e9db8ba 100644 --- a/deps/uv/src/win/stream.c +++ b/deps/uv/src/win/stream.c @@ -216,7 +216,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { req->cb = cb; handle->flags &= ~UV_HANDLE_WRITABLE; - handle->shutdown_req = req; + handle->stream.conn.shutdown_req = req; handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index c5ddbed08f75ae..8b0e18c7cf3256 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -149,13 +149,13 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) { uv_stream_init(loop, (uv_stream_t*) handle, UV_TCP); - handle->accept_reqs = NULL; - handle->pending_accepts = NULL; + handle->tcp.serv.accept_reqs = NULL; + handle->tcp.serv.pending_accepts = NULL; handle->socket = INVALID_SOCKET; handle->reqs_pending = 0; - handle->func_acceptex = NULL; - handle->func_connectex = NULL; - handle->processed_accepts = 0; + handle->tcp.serv.func_acceptex = NULL; + handle->tcp.conn.func_connectex = NULL; + handle->tcp.serv.processed_accepts = 0; handle->delayed_error = 0; return 0; @@ -168,10 +168,10 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { uv_tcp_accept_t* req; if (handle->flags & UV_HANDLE_CONNECTION && - handle->shutdown_req != NULL && - handle->write_reqs_pending == 0) { + handle->stream.conn.shutdown_req != NULL && + handle->stream.conn.write_reqs_pending == 0) { - UNREGISTER_HANDLE_REQ(loop, handle, handle->shutdown_req); + UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req); err = 0; if (handle->flags & UV__HANDLE_CLOSING) { @@ -180,12 +180,12 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { err = WSAGetLastError(); } - if (handle->shutdown_req->cb) { - handle->shutdown_req->cb(handle->shutdown_req, + if (handle->stream.conn.shutdown_req->cb) { + handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, uv_translate_sys_error(err)); } - handle->shutdown_req = NULL; + handle->stream.conn.shutdown_req = NULL; DECREASE_PENDING_REQ_COUNT(handle); return; } @@ -200,10 +200,10 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { handle->flags |= UV_HANDLE_TCP_SOCKET_CLOSED; } - if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->accept_reqs) { + if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) { if (handle->flags & UV_HANDLE_EMULATE_IOCP) { for (i = 0; i < uv_simultaneous_server_accepts; i++) { - req = &handle->accept_reqs[i]; + req = &handle->tcp.serv.accept_reqs[i]; if (req->wait_handle != INVALID_HANDLE_VALUE) { UnregisterWait(req->wait_handle); req->wait_handle = INVALID_HANDLE_VALUE; @@ -215,8 +215,8 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { } } - free(handle->accept_reqs); - handle->accept_reqs = NULL; + free(handle->tcp.serv.accept_reqs); + handle->tcp.serv.accept_reqs = NULL; } if (handle->flags & UV_HANDLE_CONNECTION && @@ -327,9 +327,9 @@ static void CALLBACK post_completion(void* context, BOOLEAN timed_out) { assert(!timed_out); if (!PostQueuedCompletionStatus(handle->loop->iocp, - req->overlapped.InternalHigh, + req->u.io.overlapped.InternalHigh, 0, - &req->overlapped)) { + &req->u.io.overlapped)) { uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); } } @@ -346,9 +346,9 @@ static void CALLBACK post_write_completion(void* context, BOOLEAN timed_out) { assert(!timed_out); if (!PostQueuedCompletionStatus(handle->loop->iocp, - req->overlapped.InternalHigh, + req->u.io.overlapped.InternalHigh, 0, - &req->overlapped)) { + &req->u.io.overlapped)) { uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); } } @@ -390,19 +390,19 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { } /* Prepare the overlapped structure. */ - memset(&(req->overlapped), 0, sizeof(req->overlapped)); + memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); + req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); } - success = handle->func_acceptex(handle->socket, - accept_socket, - (void*)req->accept_buffer, - 0, - sizeof(struct sockaddr_storage), - sizeof(struct sockaddr_storage), - &bytes, - &req->overlapped); + success = handle->tcp.serv.func_acceptex(handle->socket, + accept_socket, + (void*)req->accept_buffer, + 0, + sizeof(struct sockaddr_storage), + sizeof(struct sockaddr_storage), + &bytes, + &req->u.io.overlapped); if (UV_SUCCEEDED_WITHOUT_IOCP(success)) { /* Process the req without IOCP. */ @@ -432,7 +432,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { closesocket(accept_socket); /* Destroy the event handle */ if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - CloseHandle(req->overlapped.hEvent); + CloseHandle(req->u.io.overlapped.hEvent); req->event_handle = NULL; } } @@ -449,7 +449,7 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { assert(!(handle->flags & UV_HANDLE_READ_PENDING)); req = &handle->read_req; - memset(&req->overlapped, 0, sizeof(req->overlapped)); + memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); /* * Preallocate a read buffer if the number of active streams is below @@ -457,13 +457,13 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { */ if (loop->active_tcp_streams < uv_active_tcp_streams_threshold) { handle->flags &= ~UV_HANDLE_ZERO_READ; - handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->read_buffer); - if (handle->read_buffer.len == 0) { - handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &handle->read_buffer); + handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->tcp.conn.read_buffer); + if (handle->tcp.conn.read_buffer.len == 0) { + handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &handle->tcp.conn.read_buffer); return; } - assert(handle->read_buffer.base != NULL); - buf = handle->read_buffer; + assert(handle->tcp.conn.read_buffer.base != NULL); + buf = handle->tcp.conn.read_buffer; } else { handle->flags |= UV_HANDLE_ZERO_READ; buf.base = (char*) &uv_zero_; @@ -471,10 +471,10 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { } /* Prepare the overlapped structure. */ - memset(&(req->overlapped), 0, sizeof(req->overlapped)); + memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { assert(req->event_handle); - req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); + req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); } flags = 0; @@ -483,13 +483,13 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { 1, &bytes, &flags, - &req->overlapped, + &req->u.io.overlapped, NULL); if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Process the req without IOCP. */ handle->flags |= UV_HANDLE_READ_PENDING; - req->overlapped.InternalHigh = bytes; + req->u.io.overlapped.InternalHigh = bytes; handle->reqs_pending++; uv_insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { @@ -522,7 +522,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { assert(backlog > 0); if (handle->flags & UV_HANDLE_LISTENING) { - handle->connection_cb = cb; + handle->stream.serv.connection_cb = cb; } if (handle->flags & UV_HANDLE_READING) { @@ -544,8 +544,8 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { return handle->delayed_error; } - if (!handle->func_acceptex) { - if (!uv_get_acceptex_function(handle->socket, &handle->func_acceptex)) { + if (!handle->tcp.serv.func_acceptex) { + if (!uv_get_acceptex_function(handle->socket, &handle->tcp.serv.func_acceptex)) { return WSAEAFNOSUPPORT; } } @@ -556,21 +556,21 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { } handle->flags |= UV_HANDLE_LISTENING; - handle->connection_cb = cb; + handle->stream.serv.connection_cb = cb; INCREASE_ACTIVE_COUNT(loop, handle); simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1 : uv_simultaneous_server_accepts; - if(!handle->accept_reqs) { - handle->accept_reqs = (uv_tcp_accept_t*) + if(!handle->tcp.serv.accept_reqs) { + handle->tcp.serv.accept_reqs = (uv_tcp_accept_t*) malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t)); - if (!handle->accept_reqs) { + if (!handle->tcp.serv.accept_reqs) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } for (i = 0; i < simultaneous_accepts; i++) { - req = &handle->accept_reqs[i]; + req = &handle->tcp.serv.accept_reqs[i]; uv_req_init(loop, (uv_req_t*)req); req->type = UV_ACCEPT; req->accept_socket = INVALID_SOCKET; @@ -593,7 +593,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { /* doesn't know how how many requests were initialized, so it will */ /* try to clean up {uv_simultaneous_server_accepts} requests. */ for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) { - req = &handle->accept_reqs[i]; + req = &handle->tcp.serv.accept_reqs[i]; uv_req_init(loop, (uv_req_t*) req); req->type = UV_ACCEPT; req->accept_socket = INVALID_SOCKET; @@ -612,7 +612,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { int err = 0; int family; - uv_tcp_accept_t* req = server->pending_accepts; + uv_tcp_accept_t* req = server->tcp.serv.pending_accepts; if (!req) { /* No valid connections found, so we error out. */ @@ -643,7 +643,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { } /* Prepare the req to pick up a new connection */ - server->pending_accepts = req->next_pending; + server->tcp.serv.pending_accepts = req->next_pending; req->next_pending = NULL; req->accept_socket = INVALID_SOCKET; @@ -655,15 +655,15 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { /* We better be switching to a single pending accept. */ assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT); - server->processed_accepts++; + server->tcp.serv.processed_accepts++; - if (server->processed_accepts >= uv_simultaneous_server_accepts) { - server->processed_accepts = 0; + if (server->tcp.serv.processed_accepts >= uv_simultaneous_server_accepts) { + server->tcp.serv.processed_accepts = 0; /* * All previously queued accept requests are now processed. * We now switch to queueing just a single accept. */ - uv_tcp_queue_accept(server, &server->accept_reqs[0]); + uv_tcp_queue_accept(server, &server->tcp.serv.accept_reqs[0]); server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING; server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; } @@ -732,8 +732,8 @@ static int uv_tcp_try_connect(uv_connect_t* req, return handle->delayed_error; } - if (!handle->func_connectex) { - if (!uv_get_connectex_function(handle->socket, &handle->func_connectex)) { + if (!handle->tcp.conn.func_connectex) { + if (!uv_get_connectex_function(handle->socket, &handle->tcp.conn.func_connectex)) { return WSAEAFNOSUPPORT; } } @@ -742,15 +742,15 @@ static int uv_tcp_try_connect(uv_connect_t* req, req->type = UV_CONNECT; req->handle = (uv_stream_t*) handle; req->cb = cb; - memset(&req->overlapped, 0, sizeof(req->overlapped)); + memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - success = handle->func_connectex(handle->socket, - addr, - addrlen, - NULL, - 0, - &bytes, - &req->overlapped); + success = handle->tcp.conn.func_connectex(handle->socket, + addr, + addrlen, + NULL, + 0, + &bytes, + &req->u.io.overlapped); if (UV_SUCCEEDED_WITHOUT_IOCP(success)) { /* Process the req without IOCP. */ @@ -828,13 +828,13 @@ int uv_tcp_write(uv_loop_t* loop, req->cb = cb; /* Prepare the overlapped structure. */ - memset(&(req->overlapped), 0, sizeof(req->overlapped)); + memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->event_handle = CreateEvent(NULL, 0, 0, NULL); if (!req->event_handle) { uv_fatal_error(GetLastError(), "CreateEvent"); } - req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); + req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); req->wait_handle = INVALID_HANDLE_VALUE; } @@ -843,23 +843,23 @@ int uv_tcp_write(uv_loop_t* loop, nbufs, &bytes, 0, - &req->overlapped, + &req->u.io.overlapped, NULL); if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Request completed immediately. */ - req->queued_bytes = 0; + req->u.io.queued_bytes = 0; handle->reqs_pending++; - handle->write_reqs_pending++; + handle->stream.conn.write_reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); uv_insert_pending_req(loop, (uv_req_t*) req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* Request queued by the kernel. */ - req->queued_bytes = uv__count_bufs(bufs, nbufs); + req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs); handle->reqs_pending++; - handle->write_reqs_pending++; + handle->stream.conn.write_reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); - handle->write_queue_size += req->queued_bytes; + handle->write_queue_size += req->u.io.queued_bytes; if (handle->flags & UV_HANDLE_EMULATE_IOCP && !RegisterWaitForSingleObject(&req->wait_handle, req->event_handle, post_write_completion, (void*) req, @@ -868,8 +868,13 @@ int uv_tcp_write(uv_loop_t* loop, uv_insert_pending_req(loop, (uv_req_t*)req); } } else { - /* Send failed due to an error. */ - return WSAGetLastError(); + /* Send failed due to an error, report it later */ + req->u.io.queued_bytes = 0; + handle->reqs_pending++; + handle->stream.conn.write_reqs_pending++; + REGISTER_HANDLE_REQ(loop, handle, req); + SET_REQ_ERROR(req, WSAGetLastError()); + uv_insert_pending_req(loop, (uv_req_t*) req); } return 0; @@ -882,7 +887,7 @@ int uv__tcp_try_write(uv_tcp_t* handle, int result; DWORD bytes; - if (handle->write_reqs_pending > 0) + if (handle->stream.conn.write_reqs_pending > 0) return UV_EAGAIN; result = WSASend(handle->socket, @@ -916,7 +921,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, handle->flags &= ~UV_HANDLE_READING; DECREASE_ACTIVE_COUNT(loop, handle); buf = (handle->flags & UV_HANDLE_ZERO_READ) ? - uv_buf_init(NULL, 0) : handle->read_buffer; + uv_buf_init(NULL, 0) : handle->tcp.conn.read_buffer; err = GET_REQ_SOCK_ERROR(req); @@ -934,13 +939,13 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, } else { if (!(handle->flags & UV_HANDLE_ZERO_READ)) { /* The read was done with a non-zero buffer length. */ - if (req->overlapped.InternalHigh > 0) { + if (req->u.io.overlapped.InternalHigh > 0) { /* Successful read */ handle->read_cb((uv_stream_t*)handle, - req->overlapped.InternalHigh, - &handle->read_buffer); + req->u.io.overlapped.InternalHigh, + &handle->tcp.conn.read_buffer); /* Read again only if bytes == buf.len */ - if (req->overlapped.InternalHigh < handle->read_buffer.len) { + if (req->u.io.overlapped.InternalHigh < handle->tcp.conn.read_buffer.len) { goto done; } } else { @@ -953,7 +958,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, buf.base = 0; buf.len = 0; - handle->read_cb((uv_stream_t*)handle, UV_EOF, &handle->read_buffer); + handle->read_cb((uv_stream_t*)handle, UV_EOF, &handle->tcp.conn.read_buffer); goto done; } } @@ -1032,8 +1037,8 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, assert(handle->type == UV_TCP); - assert(handle->write_queue_size >= req->queued_bytes); - handle->write_queue_size -= req->queued_bytes; + assert(handle->write_queue_size >= req->u.io.queued_bytes); + handle->write_queue_size -= req->u.io.queued_bytes; UNREGISTER_HANDLE_REQ(loop, handle, req); @@ -1057,9 +1062,9 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, req->cb(req, err); } - handle->write_reqs_pending--; - if (handle->shutdown_req != NULL && - handle->write_reqs_pending == 0) { + handle->stream.conn.write_reqs_pending--; + if (handle->stream.conn.shutdown_req != NULL && + handle->stream.conn.write_reqs_pending == 0) { uv_want_endgame(loop, (uv_handle_t*)handle); } @@ -1082,10 +1087,10 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, if (handle->flags & UV_HANDLE_LISTENING) { handle->flags &= ~UV_HANDLE_LISTENING; DECREASE_ACTIVE_COUNT(loop, handle); - if (handle->connection_cb) { + if (handle->stream.serv.connection_cb) { err = GET_REQ_SOCK_ERROR(req); - handle->connection_cb((uv_stream_t*)handle, - uv_translate_sys_error(err)); + handle->stream.serv.connection_cb((uv_stream_t*)handle, + uv_translate_sys_error(err)); } } } else if (REQ_SUCCESS(req) && @@ -1094,12 +1099,12 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, SO_UPDATE_ACCEPT_CONTEXT, (char*)&handle->socket, sizeof(handle->socket)) == 0) { - req->next_pending = handle->pending_accepts; - handle->pending_accepts = req; + req->next_pending = handle->tcp.serv.pending_accepts; + handle->tcp.serv.pending_accepts = req; /* Accept and SO_UPDATE_ACCEPT_CONTEXT were successful. */ - if (handle->connection_cb) { - handle->connection_cb((uv_stream_t*)handle, 0); + if (handle->stream.serv.connection_cb) { + handle->stream.serv.connection_cb((uv_stream_t*)handle, 0); } } else { /* Error related to accepted socket is ignored because the server */ @@ -1357,7 +1362,7 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { } } else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) && - tcp->accept_reqs != NULL) { + tcp->tcp.serv.accept_reqs != NULL) { /* Under normal circumstances closesocket() will ensure that all pending */ /* accept reqs are canceled. However, when the socket is shared the */ /* presence of another reference to the socket in another process will */ @@ -1371,9 +1376,9 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { /* cause the connection to be aborted. */ unsigned int i; for (i = 0; i < uv_simultaneous_server_accepts; i++) { - uv_tcp_accept_t* req = &tcp->accept_reqs[i]; + uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i]; if (req->accept_socket != INVALID_SOCKET && - !HasOverlappedIoCompleted(&req->overlapped)) { + !HasOverlappedIoCompleted(&req->u.io.overlapped)) { closesocket(req->accept_socket); req->accept_socket = INVALID_SOCKET; } diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index 603421045cac58..7b1e4ba0557fca 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -142,28 +142,28 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { if (readable) { /* Initialize TTY input specific fields. */ tty->flags |= UV_HANDLE_TTY_READABLE | UV_HANDLE_READABLE; - tty->read_line_handle = NULL; - tty->read_line_buffer = uv_null_buf_; - tty->read_raw_wait = NULL; + tty->tty.rd.read_line_handle = NULL; + tty->tty.rd.read_line_buffer = uv_null_buf_; + tty->tty.rd.read_raw_wait = NULL; /* Init keycode-to-vt100 mapper state. */ - tty->last_key_len = 0; - tty->last_key_offset = 0; - tty->last_utf16_high_surrogate = 0; - memset(&tty->last_input_record, 0, sizeof tty->last_input_record); + tty->tty.rd.last_key_len = 0; + tty->tty.rd.last_key_offset = 0; + tty->tty.rd.last_utf16_high_surrogate = 0; + memset(&tty->tty.rd.last_input_record, 0, sizeof tty->tty.rd.last_input_record); } else { /* TTY output specific fields. */ tty->flags |= UV_HANDLE_WRITABLE; /* Init utf8-to-utf16 conversion state. */ - tty->utf8_bytes_left = 0; - tty->utf8_codepoint = 0; + tty->tty.wr.utf8_bytes_left = 0; + tty->tty.wr.utf8_codepoint = 0; /* Initialize eol conversion state */ - tty->previous_eol = 0; + tty->tty.wr.previous_eol = 0; /* Init ANSI parser state. */ - tty->ansi_parser_state = ANSI_NORMAL; + tty->tty.wr.ansi_parser_state = ANSI_NORMAL; } return 0; @@ -268,8 +268,8 @@ static void CALLBACK uv_tty_post_raw_read(void* data, BOOLEAN didTimeout) { handle = (uv_tty_t*) req->data; loop = handle->loop; - UnregisterWait(handle->read_raw_wait); - handle->read_raw_wait = NULL; + UnregisterWait(handle->tty.rd.read_raw_wait); + handle->tty.rd.read_raw_wait = NULL; SET_REQ_SUCCESS(req); POST_COMPLETION_FOR_REQ(loop, req); @@ -285,19 +285,19 @@ static void uv_tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) { assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE); - handle->read_line_buffer = uv_null_buf_; + handle->tty.rd.read_line_buffer = uv_null_buf_; req = &handle->read_req; - memset(&req->overlapped, 0, sizeof(req->overlapped)); + memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - r = RegisterWaitForSingleObject(&handle->read_raw_wait, + r = RegisterWaitForSingleObject(&handle->tty.rd.read_raw_wait, handle->handle, uv_tty_post_raw_read, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); if (!r) { - handle->read_raw_wait = NULL; + handle->tty.rd.read_raw_wait = NULL; SET_REQ_ERROR(req, GetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); } @@ -321,12 +321,12 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) { handle = (uv_tty_t*) req->data; loop = handle->loop; - assert(handle->read_line_buffer.base != NULL); - assert(handle->read_line_buffer.len > 0); + assert(handle->tty.rd.read_line_buffer.base != NULL); + assert(handle->tty.rd.read_line_buffer.len > 0); /* ReadConsole can't handle big buffers. */ - if (handle->read_line_buffer.len < MAX_INPUT_BUFFER_LENGTH) { - bytes = handle->read_line_buffer.len; + if (handle->tty.rd.read_line_buffer.len < MAX_INPUT_BUFFER_LENGTH) { + bytes = handle->tty.rd.read_line_buffer.len; } else { bytes = MAX_INPUT_BUFFER_LENGTH; } @@ -335,7 +335,7 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) { /* One utf-16 codeunit never takes more than 3 utf-8 codeunits to encode */ chars = bytes / 3; - if (ReadConsoleW(handle->read_line_handle, + if (ReadConsoleW(handle->tty.rd.read_line_handle, (void*) utf16, chars, &read_chars, @@ -344,12 +344,12 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) { 0, utf16, read_chars, - handle->read_line_buffer.base, + handle->tty.rd.read_line_buffer.base, bytes, NULL, NULL); SET_REQ_SUCCESS(req); - req->overlapped.InternalHigh = read_bytes; + req->u.io.overlapped.InternalHigh = read_bytes; } else { SET_REQ_ERROR(req, GetLastError()); } @@ -368,30 +368,30 @@ static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) { assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE); req = &handle->read_req; - memset(&req->overlapped, 0, sizeof(req->overlapped)); + memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - handle->alloc_cb((uv_handle_t*) handle, 8192, &handle->read_line_buffer); - if (handle->read_line_buffer.len == 0) { + handle->alloc_cb((uv_handle_t*) handle, 8192, &handle->tty.rd.read_line_buffer); + if (handle->tty.rd.read_line_buffer.len == 0) { handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, - &handle->read_line_buffer); + &handle->tty.rd.read_line_buffer); return; } - assert(handle->read_line_buffer.base != NULL); + assert(handle->tty.rd.read_line_buffer.base != NULL); /* Duplicate the console handle, so if we want to cancel the read, we can */ /* just close this handle duplicate. */ - if (handle->read_line_handle == NULL) { + if (handle->tty.rd.read_line_handle == NULL) { HANDLE this_process = GetCurrentProcess(); r = DuplicateHandle(this_process, handle->handle, this_process, - &handle->read_line_handle, + &handle->tty.rd.read_line_handle, 0, 0, DUPLICATE_SAME_ACCESS); if (!r) { - handle->read_line_handle = NULL; + handle->tty.rd.read_line_handle = NULL; SET_REQ_ERROR(req, GetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); goto out; @@ -489,8 +489,8 @@ static const char* get_vt100_fn_key(DWORD code, char shift, char ctrl, void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* req) { - /* Shortcut for handle->last_input_record.Event.KeyEvent. */ -#define KEV handle->last_input_record.Event.KeyEvent + /* Shortcut for handle->tty.rd.last_input_record.Event.KeyEvent. */ +#define KEV handle->tty.rd.last_input_record.Event.KeyEvent DWORD records_left, records_read; uv_buf_t buf; @@ -531,12 +531,12 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, buf = uv_null_buf_; buf_used = 0; - while ((records_left > 0 || handle->last_key_len > 0) && + while ((records_left > 0 || handle->tty.rd.last_key_len > 0) && (handle->flags & UV_HANDLE_READING)) { - if (handle->last_key_len == 0) { + if (handle->tty.rd.last_key_len == 0) { /* Read the next input record */ if (!ReadConsoleInputW(handle->handle, - &handle->last_input_record, + &handle->tty.rd.last_input_record, 1, &records_read)) { handle->flags &= ~UV_HANDLE_READING; @@ -551,7 +551,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, /* If the window was resized, recompute the virtual window size. This */ /* will trigger a SIGWINCH signal if the window size changed in an */ /* way that matters to libuv. */ - if (handle->last_input_record.EventType == WINDOW_BUFFER_SIZE_EVENT) { + if (handle->tty.rd.last_input_record.EventType == WINDOW_BUFFER_SIZE_EVENT) { CONSOLE_SCREEN_BUFFER_INFO info; EnterCriticalSection(&uv_tty_output_lock); @@ -567,7 +567,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, } /* Ignore other events that are not key or resize events. */ - if (handle->last_input_record.EventType != KEY_EVENT) { + if (handle->tty.rd.last_input_record.EventType != KEY_EVENT) { continue; } @@ -613,7 +613,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, if (KEV.uChar.UnicodeChar >= 0xD800 && KEV.uChar.UnicodeChar < 0xDC00) { /* UTF-16 high surrogate */ - handle->last_utf16_high_surrogate = KEV.uChar.UnicodeChar; + handle->tty.rd.last_utf16_high_surrogate = KEV.uChar.UnicodeChar; continue; } @@ -622,7 +622,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) && !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) { - handle->last_key[0] = '\033'; + handle->tty.rd.last_key[0] = '\033'; prefix_len = 1; } else { prefix_len = 0; @@ -631,14 +631,14 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, if (KEV.uChar.UnicodeChar >= 0xDC00 && KEV.uChar.UnicodeChar < 0xE000) { /* UTF-16 surrogate pair */ - WCHAR utf16_buffer[2] = { handle->last_utf16_high_surrogate, + WCHAR utf16_buffer[2] = { handle->tty.rd.last_utf16_high_surrogate, KEV.uChar.UnicodeChar}; char_len = WideCharToMultiByte(CP_UTF8, 0, utf16_buffer, 2, - &handle->last_key[prefix_len], - sizeof handle->last_key, + &handle->tty.rd.last_key[prefix_len], + sizeof handle->tty.rd.last_key, NULL, NULL); } else { @@ -647,14 +647,14 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, 0, &KEV.uChar.UnicodeChar, 1, - &handle->last_key[prefix_len], - sizeof handle->last_key, + &handle->tty.rd.last_key[prefix_len], + sizeof handle->tty.rd.last_key, NULL, NULL); } /* Whatever happened, the last character wasn't a high surrogate. */ - handle->last_utf16_high_surrogate = 0; + handle->tty.rd.last_utf16_high_surrogate = 0; /* If the utf16 character(s) couldn't be converted something must */ /* be wrong. */ @@ -667,8 +667,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, goto out; } - handle->last_key_len = (unsigned char) (prefix_len + char_len); - handle->last_key_offset = 0; + handle->tty.rd.last_key_len = (unsigned char) (prefix_len + char_len); + handle->tty.rd.last_key_offset = 0; continue; } else { @@ -690,23 +690,23 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, /* Prefix with \x033 when the alt key was held. */ if (KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { - handle->last_key[0] = '\033'; + handle->tty.rd.last_key[0] = '\033'; prefix_len = 1; } else { prefix_len = 0; } /* Copy the vt100 sequence to the handle buffer. */ - assert(prefix_len + vt100_len < sizeof handle->last_key); - memcpy(&handle->last_key[prefix_len], vt100, vt100_len); + assert(prefix_len + vt100_len < sizeof handle->tty.rd.last_key); + memcpy(&handle->tty.rd.last_key[prefix_len], vt100, vt100_len); - handle->last_key_len = (unsigned char) (prefix_len + vt100_len); - handle->last_key_offset = 0; + handle->tty.rd.last_key_len = (unsigned char) (prefix_len + vt100_len); + handle->tty.rd.last_key_offset = 0; continue; } } else { /* Copy any bytes left from the last keypress to the user buffer. */ - if (handle->last_key_offset < handle->last_key_len) { + if (handle->tty.rd.last_key_offset < handle->tty.rd.last_key_len) { /* Allocate a buffer if needed */ if (buf_used == 0) { handle->alloc_cb((uv_handle_t*) handle, 1024, &buf); @@ -717,7 +717,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, assert(buf.base != NULL); } - buf.base[buf_used++] = handle->last_key[handle->last_key_offset++]; + buf.base[buf_used++] = handle->tty.rd.last_key[handle->tty.rd.last_key_offset++]; /* If the buffer is full, emit it */ if ((size_t) buf_used == buf.len) { @@ -731,11 +731,11 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, /* Apply dwRepeat from the last input record. */ if (--KEV.wRepeatCount > 0) { - handle->last_key_offset = 0; + handle->tty.rd.last_key_offset = 0; continue; } - handle->last_key_len = 0; + handle->tty.rd.last_key_len = 0; continue; } } @@ -766,15 +766,15 @@ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle, assert(handle->type == UV_TTY); assert(handle->flags & UV_HANDLE_TTY_READABLE); - buf = handle->read_line_buffer; + buf = handle->tty.rd.read_line_buffer; handle->flags &= ~UV_HANDLE_READ_PENDING; - handle->read_line_buffer = uv_null_buf_; + handle->tty.rd.read_line_buffer = uv_null_buf_; if (!REQ_SUCCESS(req)) { /* Read was not successful */ if ((handle->flags & UV_HANDLE_READING) && - handle->read_line_handle != NULL) { + handle->tty.rd.read_line_handle != NULL) { /* Real error */ handle->flags &= ~UV_HANDLE_READING; DECREASE_ACTIVE_COUNT(loop, handle); @@ -789,7 +789,7 @@ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle, } else { /* Read successful */ /* TODO: read unicode, convert to utf-8 */ - DWORD bytes = req->overlapped.InternalHigh; + DWORD bytes = req->u.io.overlapped.InternalHigh; handle->read_cb((uv_stream_t*) handle, bytes, &buf); } @@ -811,7 +811,7 @@ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, /* If the read_line_buffer member is zero, it must have been an raw read. */ /* Otherwise it was a line-buffered read. */ /* FIXME: This is quite obscure. Use a flag or something. */ - if (handle->read_line_buffer.len == 0) { + if (handle->tty.rd.read_line_buffer.len == 0) { uv_process_tty_read_raw_req(loop, handle, req); } else { uv_process_tty_read_line_req(loop, handle, req); @@ -840,7 +840,7 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, /* Maybe the user stopped reading half-way while processing key events. */ /* Short-circuit if this could be the case. */ - if (handle->last_key_len > 0) { + if (handle->tty.rd.last_key_len > 0) { SET_REQ_SUCCESS(&handle->read_req); uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req); return 0; @@ -869,10 +869,10 @@ int uv_tty_read_stop(uv_tty_t* handle) { } /* Cancel line-buffered read */ - if (handle->read_line_handle != NULL) { + if (handle->tty.rd.read_line_handle != NULL) { /* Closing this handle will cancel the ReadConsole operation */ - CloseHandle(handle->read_line_handle); - handle->read_line_handle = NULL; + CloseHandle(handle->tty.rd.read_line_handle); + handle->tty.rd.read_line_handle = NULL; } @@ -1149,8 +1149,8 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen, } while (0) static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { - unsigned short argc = handle->ansi_csi_argc; - unsigned short* argv = handle->ansi_csi_argv; + unsigned short argc = handle->tty.wr.ansi_csi_argc; + unsigned short* argv = handle->tty.wr.ansi_csi_argv; int i; CONSOLE_SCREEN_BUFFER_INFO info; @@ -1319,12 +1319,12 @@ static int uv_tty_save_state(uv_tty_t* handle, unsigned char save_attributes, uv_tty_update_virtual_window(&info); - handle->saved_position.X = info.dwCursorPosition.X; - handle->saved_position.Y = info.dwCursorPosition.Y - uv_tty_virtual_offset; + handle->tty.wr.saved_position.X = info.dwCursorPosition.X; + handle->tty.wr.saved_position.Y = info.dwCursorPosition.Y - uv_tty_virtual_offset; handle->flags |= UV_HANDLE_TTY_SAVED_POSITION; if (save_attributes) { - handle->saved_attributes = info.wAttributes & + handle->tty.wr.saved_attributes = info.wAttributes & (FOREGROUND_INTENSITY | BACKGROUND_INTENSITY); handle->flags |= UV_HANDLE_TTY_SAVED_ATTRIBUTES; } @@ -1344,9 +1344,9 @@ static int uv_tty_restore_state(uv_tty_t* handle, if (handle->flags & UV_HANDLE_TTY_SAVED_POSITION) { if (uv_tty_move_caret(handle, - handle->saved_position.X, + handle->tty.wr.saved_position.X, 0, - handle->saved_position.Y, + handle->tty.wr.saved_position.Y, 0, error) != 0) { return -1; @@ -1362,7 +1362,7 @@ static int uv_tty_restore_state(uv_tty_t* handle, new_attributes = info.wAttributes; new_attributes &= ~(FOREGROUND_INTENSITY | BACKGROUND_INTENSITY); - new_attributes |= handle->saved_attributes; + new_attributes |= handle->tty.wr.saved_attributes; if (!SetConsoleTextAttribute(handle->handle, new_attributes)) { *error = GetLastError(); @@ -1412,10 +1412,10 @@ static int uv_tty_write_bufs(uv_tty_t* handle, } while (0) /* Cache for fast access */ - unsigned char utf8_bytes_left = handle->utf8_bytes_left; - unsigned int utf8_codepoint = handle->utf8_codepoint; - unsigned char previous_eol = handle->previous_eol; - unsigned char ansi_parser_state = handle->ansi_parser_state; + unsigned char utf8_bytes_left = handle->tty.wr.utf8_bytes_left; + unsigned int utf8_codepoint = handle->tty.wr.utf8_codepoint; + unsigned char previous_eol = handle->tty.wr.previous_eol; + unsigned char ansi_parser_state = handle->tty.wr.ansi_parser_state; /* Store the error here. If we encounter an error, stop trying to do i/o */ /* but keep parsing the buffer so we leave the parser in a consistent */ @@ -1492,7 +1492,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, case 0233: ansi_parser_state = ANSI_CSI; - handle->ansi_csi_argc = 0; + handle->tty.wr.ansi_csi_argc = 0; continue; } @@ -1500,7 +1500,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, switch (utf8_codepoint) { case '[': ansi_parser_state = ANSI_CSI; - handle->ansi_csi_argc = 0; + handle->tty.wr.ansi_csi_argc = 0; continue; case '^': @@ -1557,20 +1557,20 @@ static int uv_tty_write_bufs(uv_tty_t* handle, /* We were not currently parsing a number */ /* Check for too many arguments */ - if (handle->ansi_csi_argc >= ARRAY_SIZE(handle->ansi_csi_argv)) { + if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) { ansi_parser_state |= ANSI_IGNORE; continue; } ansi_parser_state |= ANSI_IN_ARG; - handle->ansi_csi_argc++; - handle->ansi_csi_argv[handle->ansi_csi_argc - 1] = + handle->tty.wr.ansi_csi_argc++; + handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = (unsigned short) utf8_codepoint - '0'; continue; } else { /* We were already parsing a number. Parse next digit. */ uint32_t value = 10 * - handle->ansi_csi_argv[handle->ansi_csi_argc - 1]; + handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1]; /* Check for overflow. */ if (value > UINT16_MAX) { @@ -1578,7 +1578,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, continue; } - handle->ansi_csi_argv[handle->ansi_csi_argc - 1] = + handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = (unsigned short) value + (utf8_codepoint - '0'); continue; } @@ -1593,25 +1593,25 @@ static int uv_tty_write_bufs(uv_tty_t* handle, /* If ANSI_IN_ARG is not set, add another argument and */ /* default it to 0. */ /* Check for too many arguments */ - if (handle->ansi_csi_argc >= ARRAY_SIZE(handle->ansi_csi_argv)) { + if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) { ansi_parser_state |= ANSI_IGNORE; continue; } - handle->ansi_csi_argc++; - handle->ansi_csi_argv[handle->ansi_csi_argc - 1] = 0; + handle->tty.wr.ansi_csi_argc++; + handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = 0; continue; } } else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) && - handle->ansi_csi_argc == 0) { + handle->tty.wr.ansi_csi_argc == 0) { /* Ignores '?' if it is the first character after CSI[ */ /* This is an extension character from the VT100 codeset */ /* that is supported and used by most ANSI terminals today. */ continue; } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' && - (handle->ansi_csi_argc > 0 || utf8_codepoint != '[')) { + (handle->tty.wr.ansi_csi_argc > 0 || utf8_codepoint != '[')) { int x, y, d; /* Command byte */ @@ -1619,50 +1619,50 @@ static int uv_tty_write_bufs(uv_tty_t* handle, case 'A': /* cursor up */ FLUSH_TEXT(); - y = -(handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1); + y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1); uv_tty_move_caret(handle, 0, 1, y, 1, error); break; case 'B': /* cursor down */ FLUSH_TEXT(); - y = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1; + y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1; uv_tty_move_caret(handle, 0, 1, y, 1, error); break; case 'C': /* cursor forward */ FLUSH_TEXT(); - x = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1; + x = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1; uv_tty_move_caret(handle, x, 1, 0, 1, error); break; case 'D': /* cursor back */ FLUSH_TEXT(); - x = -(handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1); + x = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1); uv_tty_move_caret(handle, x, 1, 0, 1, error); break; case 'E': /* cursor next line */ FLUSH_TEXT(); - y = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1; + y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1; uv_tty_move_caret(handle, 0, 0, y, 1, error); break; case 'F': /* cursor previous line */ FLUSH_TEXT(); - y = -(handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 1); + y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1); uv_tty_move_caret(handle, 0, 0, y, 1, error); break; case 'G': /* cursor horizontal move absolute */ FLUSH_TEXT(); - x = (handle->ansi_csi_argc >= 1 && handle->ansi_csi_argv[0]) - ? handle->ansi_csi_argv[0] - 1 : 0; + x = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0]) + ? handle->tty.wr.ansi_csi_argv[0] - 1 : 0; uv_tty_move_caret(handle, x, 0, 0, 1, error); break; @@ -1670,17 +1670,17 @@ static int uv_tty_write_bufs(uv_tty_t* handle, case 'f': /* cursor move absolute */ FLUSH_TEXT(); - y = (handle->ansi_csi_argc >= 1 && handle->ansi_csi_argv[0]) - ? handle->ansi_csi_argv[0] - 1 : 0; - x = (handle->ansi_csi_argc >= 2 && handle->ansi_csi_argv[1]) - ? handle->ansi_csi_argv[1] - 1 : 0; + y = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0]) + ? handle->tty.wr.ansi_csi_argv[0] - 1 : 0; + x = (handle->tty.wr.ansi_csi_argc >= 2 && handle->tty.wr.ansi_csi_argv[1]) + ? handle->tty.wr.ansi_csi_argv[1] - 1 : 0; uv_tty_move_caret(handle, x, 0, y, 0, error); break; case 'J': /* Erase screen */ FLUSH_TEXT(); - d = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 0; + d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0; if (d >= 0 && d <= 2) { uv_tty_clear(handle, d, 1, error); } @@ -1689,7 +1689,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, case 'K': /* Erase line */ FLUSH_TEXT(); - d = handle->ansi_csi_argc ? handle->ansi_csi_argv[0] : 0; + d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0; if (d >= 0 && d <= 2) { uv_tty_clear(handle, d, 0, error); } @@ -1715,8 +1715,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, case 'l': /* Hide the cursor */ - if (handle->ansi_csi_argc == 1 && - handle->ansi_csi_argv[0] == 25) { + if (handle->tty.wr.ansi_csi_argc == 1 && + handle->tty.wr.ansi_csi_argv[0] == 25) { FLUSH_TEXT(); uv_tty_set_cursor_visibility(handle, 0, error); } @@ -1724,8 +1724,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, case 'h': /* Show the cursor */ - if (handle->ansi_csi_argc == 1 && - handle->ansi_csi_argv[0] == 25) { + if (handle->tty.wr.ansi_csi_argc == 1 && + handle->tty.wr.ansi_csi_argv[0] == 25) { FLUSH_TEXT(); uv_tty_set_cursor_visibility(handle, 1, error); } @@ -1830,10 +1830,10 @@ static int uv_tty_write_bufs(uv_tty_t* handle, FLUSH_TEXT(); /* Copy cached values back to struct. */ - handle->utf8_bytes_left = utf8_bytes_left; - handle->utf8_codepoint = utf8_codepoint; - handle->previous_eol = previous_eol; - handle->ansi_parser_state = ansi_parser_state; + handle->tty.wr.utf8_bytes_left = utf8_bytes_left; + handle->tty.wr.utf8_codepoint = utf8_codepoint; + handle->tty.wr.previous_eol = previous_eol; + handle->tty.wr.ansi_parser_state = ansi_parser_state; LeaveCriticalSection(&uv_tty_output_lock); @@ -1861,10 +1861,10 @@ int uv_tty_write(uv_loop_t* loop, req->cb = cb; handle->reqs_pending++; - handle->write_reqs_pending++; + handle->stream.conn.write_reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); - req->queued_bytes = 0; + req->u.io.queued_bytes = 0; if (!uv_tty_write_bufs(handle, bufs, nbufs, &error)) { SET_REQ_SUCCESS(req); @@ -1883,7 +1883,7 @@ int uv__tty_try_write(uv_tty_t* handle, unsigned int nbufs) { DWORD error; - if (handle->write_reqs_pending > 0) + if (handle->stream.conn.write_reqs_pending > 0) return UV_EAGAIN; if (uv_tty_write_bufs(handle, bufs, nbufs, &error)) @@ -1897,7 +1897,7 @@ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, uv_write_t* req) { int err; - handle->write_queue_size -= req->queued_bytes; + handle->write_queue_size -= req->u.io.queued_bytes; UNREGISTER_HANDLE_REQ(loop, handle, req); if (req->cb) { @@ -1905,9 +1905,9 @@ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, req->cb(req, uv_translate_sys_error(err)); } - handle->write_reqs_pending--; - if (handle->shutdown_req != NULL && - handle->write_reqs_pending == 0) { + handle->stream.conn.write_reqs_pending--; + if (handle->stream.conn.shutdown_req != NULL && + handle->stream.conn.write_reqs_pending == 0) { uv_want_endgame(loop, (uv_handle_t*)handle); } @@ -1933,20 +1933,20 @@ void uv_tty_close(uv_tty_t* handle) { void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { if (!(handle->flags & UV_HANDLE_TTY_READABLE) && - handle->shutdown_req != NULL && - handle->write_reqs_pending == 0) { - UNREGISTER_HANDLE_REQ(loop, handle, handle->shutdown_req); + handle->stream.conn.shutdown_req != NULL && + handle->stream.conn.write_reqs_pending == 0) { + UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req); /* TTY shutdown is really just a no-op */ - if (handle->shutdown_req->cb) { + if (handle->stream.conn.shutdown_req->cb) { if (handle->flags & UV__HANDLE_CLOSING) { - handle->shutdown_req->cb(handle->shutdown_req, UV_ECANCELED); + handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, UV_ECANCELED); } else { - handle->shutdown_req->cb(handle->shutdown_req, 0); + handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, 0); } } - handle->shutdown_req = NULL; + handle->stream.conn.shutdown_req = NULL; DECREASE_PENDING_REQ_COUNT(handle); return; @@ -1957,12 +1957,12 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { /* The console handle duplicate used for line reading should be destroyed */ /* by uv_tty_read_stop. */ assert(!(handle->flags & UV_HANDLE_TTY_READABLE) || - handle->read_line_handle == NULL); + handle->tty.rd.read_line_handle == NULL); /* The wait handle used for raw reading should be unregistered when the */ /* wait callback runs. */ assert(!(handle->flags & UV_HANDLE_TTY_READABLE) || - handle->read_raw_wait == NULL); + handle->tty.rd.read_raw_wait == NULL); assert(!(handle->flags & UV_HANDLE_CLOSED)); uv__handle_close(handle); diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c index 73b5bd5e467b40..197e5d828f2ad4 100644 --- a/deps/uv/src/win/udp.c +++ b/deps/uv/src/win/udp.c @@ -244,7 +244,7 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { assert(!(handle->flags & UV_HANDLE_READ_PENDING)); req = &handle->recv_req; - memset(&req->overlapped, 0, sizeof(req->overlapped)); + memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); /* * Preallocate a read buffer if the number of active streams is below @@ -272,13 +272,13 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { &flags, (struct sockaddr*) &handle->recv_from, &handle->recv_from_len, - &req->overlapped, + &req->u.io.overlapped, NULL); if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Process the req without IOCP. */ handle->flags |= UV_HANDLE_READ_PENDING; - req->overlapped.InternalHigh = bytes; + req->u.io.overlapped.InternalHigh = bytes; handle->reqs_pending++; uv_insert_pending_req(loop, req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { @@ -304,13 +304,13 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { 1, &bytes, &flags, - &req->overlapped, + &req->u.io.overlapped, NULL); if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Process the req without IOCP. */ handle->flags |= UV_HANDLE_READ_PENDING; - req->overlapped.InternalHigh = bytes; + req->u.io.overlapped.InternalHigh = bytes; handle->reqs_pending++; uv_insert_pending_req(loop, req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { @@ -384,7 +384,7 @@ static int uv__send(uv_udp_send_t* req, req->type = UV_UDP_SEND; req->handle = handle; req->cb = cb; - memset(&req->overlapped, 0, sizeof(req->overlapped)); + memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); result = WSASendTo(handle->socket, (WSABUF*)bufs, @@ -393,22 +393,22 @@ static int uv__send(uv_udp_send_t* req, 0, addr, addrlen, - &req->overlapped, + &req->u.io.overlapped, NULL); if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Request completed immediately. */ - req->queued_bytes = 0; + req->u.io.queued_bytes = 0; handle->reqs_pending++; - handle->send_queue_size += req->queued_bytes; + handle->send_queue_size += req->u.io.queued_bytes; handle->send_queue_count++; REGISTER_HANDLE_REQ(loop, handle, req); uv_insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* Request queued by the kernel. */ - req->queued_bytes = uv__count_bufs(bufs, nbufs); + req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs); handle->reqs_pending++; - handle->send_queue_size += req->queued_bytes; + handle->send_queue_size += req->u.io.queued_bytes; handle->send_queue_count++; REGISTER_HANDLE_REQ(loop, handle, req); } else { @@ -459,7 +459,7 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, /* Successful read */ partial = !REQ_SUCCESS(req); handle->recv_cb(handle, - req->overlapped.InternalHigh, + req->u.io.overlapped.InternalHigh, &handle->recv_buffer, (const struct sockaddr*) &handle->recv_from, partial ? UV_UDP_PARTIAL : 0); @@ -536,9 +536,9 @@ void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle, assert(handle->type == UV_UDP); - assert(handle->send_queue_size >= req->queued_bytes); + assert(handle->send_queue_size >= req->u.io.queued_bytes); assert(handle->send_queue_count >= 1); - handle->send_queue_size -= req->queued_bytes; + handle->send_queue_size -= req->u.io.queued_bytes; handle->send_queue_count--; UNREGISTER_HANDLE_REQ(loop, handle, req); diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 43d843ff5c42b5..3697d5aa6aaf20 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -535,14 +534,14 @@ int uv_uptime(double* uptime) { return uv_translate_sys_error(result); } - free(malloced_buffer); - buffer_size *= 2; /* Don't let the buffer grow infinitely. */ if (buffer_size > 1 << 20) { goto internalError; } + free(malloced_buffer); + buffer = malloced_buffer = (BYTE*) malloc(buffer_size); if (malloced_buffer == NULL) { *uptime = 0; diff --git a/deps/uv/test/benchmark-getaddrinfo.c b/deps/uv/test/benchmark-getaddrinfo.c index c7f99a2fcb8720..1dbc23ddba009d 100644 --- a/deps/uv/test/benchmark-getaddrinfo.c +++ b/deps/uv/test/benchmark-getaddrinfo.c @@ -83,8 +83,9 @@ BENCHMARK_IMPL(getaddrinfo) { ASSERT(calls_initiated == TOTAL_CALLS); ASSERT(calls_completed == TOTAL_CALLS); - LOGF("getaddrinfo: %.0f req/s\n", - (double) calls_completed / (double) (end_time - start_time) * 1000.0); + fprintf(stderr, "getaddrinfo: %.0f req/s\n", + (double) calls_completed / (double) (end_time - start_time) * 1000.0); + fflush(stderr); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/uv/test/benchmark-loop-count.c b/deps/uv/test/benchmark-loop-count.c index 5cb813238d4f75..970a94c2fecb5c 100644 --- a/deps/uv/test/benchmark-loop-count.c +++ b/deps/uv/test/benchmark-loop-count.c @@ -62,10 +62,11 @@ BENCHMARK_IMPL(loop_count) { ASSERT(ticks == NUM_TICKS); - LOGF("loop_count: %d ticks in %.2fs (%.0f/s)\n", - NUM_TICKS, - ns / 1e9, - NUM_TICKS / (ns / 1e9)); + fprintf(stderr, "loop_count: %d ticks in %.2fs (%.0f/s)\n", + NUM_TICKS, + ns / 1e9, + NUM_TICKS / (ns / 1e9)); + fflush(stderr); MAKE_VALGRIND_HAPPY(); return 0; @@ -83,7 +84,8 @@ BENCHMARK_IMPL(loop_count_timed) { uv_run(loop, UV_RUN_DEFAULT); - LOGF("loop_count: %lu ticks (%.0f ticks/s)\n", ticks, ticks / 5.0); + fprintf(stderr, "loop_count: %lu ticks (%.0f ticks/s)\n", ticks, ticks / 5.0); + fflush(stderr); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/uv/test/benchmark-million-timers.c b/deps/uv/test/benchmark-million-timers.c index 6027d6088aa789..60a308bef13d40 100644 --- a/deps/uv/test/benchmark-million-timers.c +++ b/deps/uv/test/benchmark-million-timers.c @@ -75,10 +75,11 @@ BENCHMARK_IMPL(million_timers) { ASSERT(close_cb_called == NUM_TIMERS); free(timers); - LOGF("%.2f seconds total\n", (after_all - before_all) / 1e9); - LOGF("%.2f seconds init\n", (before_run - before_all) / 1e9); - LOGF("%.2f seconds dispatch\n", (after_run - before_run) / 1e9); - LOGF("%.2f seconds cleanup\n", (after_all - after_run) / 1e9); + fprintf(stderr, "%.2f seconds total\n", (after_all - before_all) / 1e9); + fprintf(stderr, "%.2f seconds init\n", (before_run - before_all) / 1e9); + fprintf(stderr, "%.2f seconds dispatch\n", (after_run - before_run) / 1e9); + fprintf(stderr, "%.2f seconds cleanup\n", (after_all - after_run) / 1e9); + fflush(stderr); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/uv/test/benchmark-ping-pongs.c b/deps/uv/test/benchmark-ping-pongs.c index bb560d7d21fd6b..646a7df9447036 100644 --- a/deps/uv/test/benchmark-ping-pongs.c +++ b/deps/uv/test/benchmark-ping-pongs.c @@ -80,7 +80,8 @@ static void pinger_close_cb(uv_handle_t* handle) { pinger_t* pinger; pinger = (pinger_t*)handle->data; - LOGF("ping_pongs: %d roundtrips/s\n", (1000 * pinger->pongs) / TIME); + fprintf(stderr, "ping_pongs: %d roundtrips/s\n", (1000 * pinger->pongs) / TIME); + fflush(stderr); free(pinger); diff --git a/deps/uv/test/benchmark-pound.c b/deps/uv/test/benchmark-pound.c index 587928549eac8a..79f36345037cd4 100644 --- a/deps/uv/test/benchmark-pound.c +++ b/deps/uv/test/benchmark-pound.c @@ -299,11 +299,12 @@ static int pound_it(int concurrency, /* Number of fractional seconds it took to run the benchmark. */ secs = (double)(end_time - start_time) / NANOSEC; - LOGF("%s-conn-pound-%d: %.0f accepts/s (%d failed)\n", - type, - concurrency, - closed_streams / secs, - conns_failed); + fprintf(stderr, "%s-conn-pound-%d: %.0f accepts/s (%d failed)\n", + type, + concurrency, + closed_streams / secs, + conns_failed); + fflush(stderr); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/uv/test/benchmark-pump.c b/deps/uv/test/benchmark-pump.c index d58f46a384b899..88f2dc5c658e27 100644 --- a/deps/uv/test/benchmark-pump.c +++ b/deps/uv/test/benchmark-pump.c @@ -90,9 +90,10 @@ static void show_stats(uv_timer_t* handle) { int i; #if PRINT_STATS - LOGF("connections: %d, write: %.1f gbit/s\n", - write_sockets, - gbit(nsent, STATS_INTERVAL)); + fprintf(stderr, "connections: %d, write: %.1f gbit/s\n", + write_sockets, + gbit(nsent, STATS_INTERVAL)); + fflush(stderr); #endif /* Exit if the show is over */ @@ -101,10 +102,11 @@ static void show_stats(uv_timer_t* handle) { uv_update_time(loop); diff = uv_now(loop) - start_time; - LOGF("%s_pump%d_client: %.1f gbit/s\n", - type == TCP ? "tcp" : "pipe", - write_sockets, - gbit(nsent_total, diff)); + fprintf(stderr, "%s_pump%d_client: %.1f gbit/s\n", + type == TCP ? "tcp" : "pipe", + write_sockets, + gbit(nsent_total, diff)); + fflush(stderr); for (i = 0; i < write_sockets; i++) { if (type == TCP) @@ -128,10 +130,11 @@ static void read_show_stats(void) { uv_update_time(loop); diff = uv_now(loop) - start_time; - LOGF("%s_pump%d_server: %.1f gbit/s\n", - type == TCP ? "tcp" : "pipe", - max_read_sockets, - gbit(nrecv_total, diff)); + fprintf(stderr, "%s_pump%d_server: %.1f gbit/s\n", + type == TCP ? "tcp" : "pipe", + max_read_sockets, + gbit(nrecv_total, diff)); + fflush(stderr); } @@ -213,7 +216,10 @@ static void do_write(uv_stream_t* stream) { static void connect_cb(uv_connect_t* req, int status) { int i; - if (status) LOG(uv_strerror(status)); + if (status) { + fprintf(stderr, "%s", uv_strerror(status)); + fflush(stderr); + } ASSERT(status == 0); write_sockets++; diff --git a/deps/uv/test/benchmark-sizes.c b/deps/uv/test/benchmark-sizes.c index 8ccf10ee475fb1..9bf42f91537d58 100644 --- a/deps/uv/test/benchmark-sizes.c +++ b/deps/uv/test/benchmark-sizes.c @@ -24,22 +24,23 @@ BENCHMARK_IMPL(sizes) { - LOGF("uv_shutdown_t: %u bytes\n", (unsigned int) sizeof(uv_shutdown_t)); - LOGF("uv_write_t: %u bytes\n", (unsigned int) sizeof(uv_write_t)); - LOGF("uv_connect_t: %u bytes\n", (unsigned int) sizeof(uv_connect_t)); - LOGF("uv_udp_send_t: %u bytes\n", (unsigned int) sizeof(uv_udp_send_t)); - LOGF("uv_tcp_t: %u bytes\n", (unsigned int) sizeof(uv_tcp_t)); - LOGF("uv_pipe_t: %u bytes\n", (unsigned int) sizeof(uv_pipe_t)); - LOGF("uv_tty_t: %u bytes\n", (unsigned int) sizeof(uv_tty_t)); - LOGF("uv_prepare_t: %u bytes\n", (unsigned int) sizeof(uv_prepare_t)); - LOGF("uv_check_t: %u bytes\n", (unsigned int) sizeof(uv_check_t)); - LOGF("uv_idle_t: %u bytes\n", (unsigned int) sizeof(uv_idle_t)); - LOGF("uv_async_t: %u bytes\n", (unsigned int) sizeof(uv_async_t)); - LOGF("uv_timer_t: %u bytes\n", (unsigned int) sizeof(uv_timer_t)); - LOGF("uv_fs_poll_t: %u bytes\n", (unsigned int) sizeof(uv_fs_poll_t)); - LOGF("uv_fs_event_t: %u bytes\n", (unsigned int) sizeof(uv_fs_event_t)); - LOGF("uv_process_t: %u bytes\n", (unsigned int) sizeof(uv_process_t)); - LOGF("uv_poll_t: %u bytes\n", (unsigned int) sizeof(uv_poll_t)); - LOGF("uv_loop_t: %u bytes\n", (unsigned int) sizeof(uv_loop_t)); + fprintf(stderr, "uv_shutdown_t: %u bytes\n", (unsigned int) sizeof(uv_shutdown_t)); + fprintf(stderr, "uv_write_t: %u bytes\n", (unsigned int) sizeof(uv_write_t)); + fprintf(stderr, "uv_connect_t: %u bytes\n", (unsigned int) sizeof(uv_connect_t)); + fprintf(stderr, "uv_udp_send_t: %u bytes\n", (unsigned int) sizeof(uv_udp_send_t)); + fprintf(stderr, "uv_tcp_t: %u bytes\n", (unsigned int) sizeof(uv_tcp_t)); + fprintf(stderr, "uv_pipe_t: %u bytes\n", (unsigned int) sizeof(uv_pipe_t)); + fprintf(stderr, "uv_tty_t: %u bytes\n", (unsigned int) sizeof(uv_tty_t)); + fprintf(stderr, "uv_prepare_t: %u bytes\n", (unsigned int) sizeof(uv_prepare_t)); + fprintf(stderr, "uv_check_t: %u bytes\n", (unsigned int) sizeof(uv_check_t)); + fprintf(stderr, "uv_idle_t: %u bytes\n", (unsigned int) sizeof(uv_idle_t)); + fprintf(stderr, "uv_async_t: %u bytes\n", (unsigned int) sizeof(uv_async_t)); + fprintf(stderr, "uv_timer_t: %u bytes\n", (unsigned int) sizeof(uv_timer_t)); + fprintf(stderr, "uv_fs_poll_t: %u bytes\n", (unsigned int) sizeof(uv_fs_poll_t)); + fprintf(stderr, "uv_fs_event_t: %u bytes\n", (unsigned int) sizeof(uv_fs_event_t)); + fprintf(stderr, "uv_process_t: %u bytes\n", (unsigned int) sizeof(uv_process_t)); + fprintf(stderr, "uv_poll_t: %u bytes\n", (unsigned int) sizeof(uv_poll_t)); + fprintf(stderr, "uv_loop_t: %u bytes\n", (unsigned int) sizeof(uv_loop_t)); + fflush(stderr); return 0; } diff --git a/deps/uv/test/benchmark-spawn.c b/deps/uv/test/benchmark-spawn.c index 9cae41a83afd61..ed9ad608f3790e 100644 --- a/deps/uv/test/benchmark-spawn.c +++ b/deps/uv/test/benchmark-spawn.c @@ -155,8 +155,9 @@ BENCHMARK_IMPL(spawn) { uv_update_time(loop); end_time = uv_now(loop); - LOGF("spawn: %.0f spawns/s\n", - (double) N / (double) (end_time - start_time) * 1000.0); + fprintf(stderr, "spawn: %.0f spawns/s\n", + (double) N / (double) (end_time - start_time) * 1000.0); + fflush(stderr); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/uv/test/run-benchmarks.c b/deps/uv/test/run-benchmarks.c index 8d4f549799e8b3..6e42623d54cdec 100644 --- a/deps/uv/test/run-benchmarks.c +++ b/deps/uv/test/run-benchmarks.c @@ -41,7 +41,8 @@ int main(int argc, char **argv) { case 2: return maybe_run_test(argc, argv); case 3: return run_test_part(argv[1], argv[2]); default: - LOGF("Too many arguments.\n"); + fprintf(stderr, "Too many arguments.\n"); + fflush(stderr); return EXIT_FAILURE; } diff --git a/deps/uv/test/run-tests.c b/deps/uv/test/run-tests.c index e92c93008e72ef..1f458745327398 100644 --- a/deps/uv/test/run-tests.c +++ b/deps/uv/test/run-tests.c @@ -56,7 +56,8 @@ int main(int argc, char **argv) { case 2: return maybe_run_test(argc, argv); case 3: return run_test_part(argv[1], argv[2]); default: - LOGF("Too many arguments.\n"); + fprintf(stderr, "Too many arguments.\n"); + fflush(stderr); return EXIT_FAILURE; } diff --git a/deps/uv/test/runner.c b/deps/uv/test/runner.c index e896d43b7627df..e094defc7e7de5 100644 --- a/deps/uv/test/runner.c +++ b/deps/uv/test/runner.c @@ -43,13 +43,14 @@ static void log_progress(int total, total = 1; progress = 100 * (passed + failed + skipped + todos) / total; - LOGF("[%% %3d|+ %3d|- %3d|T %3d|S %3d]: %s", - progress, - passed, - failed, - todos, - skipped, - name); + fprintf(stderr, "[%% %3d|+ %3d|- %3d|T %3d|S %3d]: %s", + progress, + passed, + failed, + todos, + skipped, + name); + fflush(stderr); } @@ -109,7 +110,8 @@ int run_tests(int benchmark_output) { } if (tap_output) { - LOGF("1..%d\n", total); + fprintf(stderr, "1..%d\n", total); + fflush(stderr); } /* Run all tests. */ @@ -184,7 +186,8 @@ void log_tap_result(int test_count, reason[0] = '\0'; } - LOGF("%s %d - %s%s%s\n", result, test_count, test, directive, reason); + fprintf(stderr, "%s %d - %s%s%s\n", result, test_count, test, directive, reason); + fflush(stderr); } @@ -320,49 +323,55 @@ int run_test(const char* test, /* Show error and output from processes if the test failed. */ if (status != 0 || task->show_output) { if (tap_output) { - LOGF("#"); + fprintf(stderr, "#"); } else if (status == TEST_TODO) { - LOGF("\n`%s` todo\n", test); + fprintf(stderr, "\n`%s` todo\n", test); } else if (status == TEST_SKIP) { - LOGF("\n`%s` skipped\n", test); + fprintf(stderr, "\n`%s` skipped\n", test); } else if (status != 0) { - LOGF("\n`%s` failed: %s\n", test, errmsg); + fprintf(stderr, "\n`%s` failed: %s\n", test, errmsg); } else { - LOGF("\n"); + fprintf(stderr, "\n"); } + fflush(stderr); for (i = 0; i < process_count; i++) { switch (process_output_size(&processes[i])) { case -1: - LOGF("Output from process `%s`: (unavailable)\n", - process_get_name(&processes[i])); + fprintf(stderr, "Output from process `%s`: (unavailable)\n", + process_get_name(&processes[i])); + fflush(stderr); break; case 0: - LOGF("Output from process `%s`: (no output)\n", - process_get_name(&processes[i])); + fprintf(stderr, "Output from process `%s`: (no output)\n", + process_get_name(&processes[i])); + fflush(stderr); break; default: - LOGF("Output from process `%s`:\n", process_get_name(&processes[i])); + fprintf(stderr, "Output from process `%s`:\n", process_get_name(&processes[i])); + fflush(stderr); process_copy_output(&processes[i], fileno(stderr)); break; } } if (!tap_output) { - LOG("=============================================================\n"); + fprintf(stderr, "=============================================================\n"); } /* In benchmark mode show concise output from the main process. */ } else if (benchmark_output) { switch (process_output_size(main_proc)) { case -1: - LOGF("%s: (unavailable)\n", test); + fprintf(stderr, "%s: (unavailable)\n", test); + fflush(stderr); break; case 0: - LOGF("%s: (no output)\n", test); + fprintf(stderr, "%s: (no output)\n", test); + fflush(stderr); break; default: @@ -397,7 +406,8 @@ int run_test_part(const char* test, const char* part) { } } - LOGF("No test part with that name: %s:%s\n", test, part); + fprintf(stderr, "No test part with that name: %s:%s\n", test, part); + fflush(stderr); return 255; } diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index 07584c52996f8c..ea0503e8feefe4 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -76,19 +76,6 @@ typedef enum { PIPE } stream_type; -/* Log to stderr. */ -#define LOG(...) \ - do { \ - fprintf(stderr, "%s", __VA_ARGS__); \ - fflush(stderr); \ - } while (0) - -#define LOGF(...) \ - do { \ - fprintf(stderr, __VA_ARGS__); \ - fflush(stderr); \ - } while (0) - /* Die with fatal error. */ #define FATAL(msg) \ do { \ @@ -158,13 +145,15 @@ enum test_status { #define RETURN_TODO(explanation) \ do { \ - LOGF("%s\n", explanation); \ + fprintf(stderr, "%s\n", explanation); \ + fflush(stderr); \ return TEST_TODO; \ } while (0) #define RETURN_SKIP(explanation) \ do { \ - LOGF("%s\n", explanation); \ + fprintf(stderr, "%s\n", explanation); \ + fflush(stderr); \ return TEST_SKIP; \ } while (0) @@ -190,10 +179,15 @@ enum test_status { #include +/* Define inline for MSVC */ +# ifdef _MSC_VER +# define inline __inline +# endif + /* Emulate snprintf() on Windows, _snprintf() doesn't zero-terminate the buffer * on overflow... */ -static int snprintf(char* buf, size_t len, const char* fmt, ...) { +inline int snprintf(char* buf, size_t len, const char* fmt, ...) { va_list ap; int n; diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index cc5dc744501ec4..a0600b30797dd9 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -1094,7 +1094,8 @@ TEST_IMPL(fs_fstat) { #elif defined(__sun) || \ defined(_BSD_SOURCE) || \ defined(_SVID_SOURCE) || \ - defined(_XOPEN_SOURCE) + defined(_XOPEN_SOURCE) || \ + defined(_DEFAULT_SOURCE) ASSERT(s->st_atim.tv_sec == t.st_atim.tv_sec); ASSERT(s->st_atim.tv_nsec == t.st_atim.tv_nsec); ASSERT(s->st_mtim.tv_sec == t.st_mtim.tv_sec); @@ -1155,6 +1156,7 @@ TEST_IMPL(fs_access) { /* Setup. */ unlink("test_file"); + rmdir("test_dir"); loop = uv_default_loop(); @@ -1198,6 +1200,16 @@ TEST_IMPL(fs_access) { ASSERT(req.result == 0); uv_fs_req_cleanup(&req); + /* Directory access */ + r = uv_fs_mkdir(loop, &req, "test_dir", 0777, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&req); + + r = uv_fs_access(loop, &req, "test_dir", W_OK, 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. @@ -1206,6 +1218,7 @@ TEST_IMPL(fs_access) { /* Cleanup. */ unlink("test_file"); + rmdir("test_dir"); MAKE_VALGRIND_HAPPY(); return 0; @@ -1310,6 +1323,65 @@ TEST_IMPL(fs_chmod) { } +TEST_IMPL(fs_unlink_readonly) { + int r; + uv_fs_t req; + uv_file file; + + /* Setup. */ + unlink("test_file"); + + loop = uv_default_loop(); + + 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); + + iov = uv_buf_init(test_buf, sizeof(test_buf)); + r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL); + ASSERT(r == sizeof(test_buf)); + ASSERT(req.result == sizeof(test_buf)); + uv_fs_req_cleanup(&req); + + close(file); + + /* Make the file read-only */ + r = uv_fs_chmod(loop, &req, "test_file", 0400, NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + uv_fs_req_cleanup(&req); + + check_permission("test_file", 0400); + + /* Try to unlink the file */ + r = uv_fs_unlink(loop, &req, "test_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. */ + uv_fs_chmod(loop, &req, "test_file", 0600, NULL); + uv_fs_req_cleanup(&req); + unlink("test_file"); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(fs_chown) { int r; uv_fs_t req; diff --git a/deps/uv/test/test-handle-fileno.c b/deps/uv/test/test-handle-fileno.c index df5e984ab74338..3fe933adebdd87 100644 --- a/deps/uv/test/test-handle-fileno.c +++ b/deps/uv/test/test-handle-fileno.c @@ -102,7 +102,8 @@ TEST_IMPL(handle_fileno) { tty_fd = get_tty_fd(); if (tty_fd < 0) { - LOGF("Cannot open a TTY fd"); + fprintf(stderr, "Cannot open a TTY fd"); + fflush(stderr); } else { r = uv_tty_init(loop, &tty, tty_fd, 0); ASSERT(r == 0); diff --git a/deps/uv/test/test-idle.c b/deps/uv/test/test-idle.c index 0e991c368cfd81..f49d1964827278 100644 --- a/deps/uv/test/test-idle.c +++ b/deps/uv/test/test-idle.c @@ -46,7 +46,8 @@ static void timer_cb(uv_timer_t* handle) { uv_close((uv_handle_t*) &timer_handle, close_cb); timer_cb_called++; - LOGF("timer_cb %d\n", timer_cb_called); + fprintf(stderr, "timer_cb %d\n", timer_cb_called); + fflush(stderr); } @@ -54,7 +55,8 @@ static void idle_cb(uv_idle_t* handle) { ASSERT(handle == &idle_handle); idle_cb_called++; - LOGF("idle_cb %d\n", idle_cb_called); + fprintf(stderr, "idle_cb %d\n", idle_cb_called); + fflush(stderr); } @@ -62,7 +64,8 @@ static void check_cb(uv_check_t* handle) { ASSERT(handle == &check_handle); check_cb_called++; - LOGF("check_cb %d\n", check_cb_called); + fprintf(stderr, "check_cb %d\n", check_cb_called); + fflush(stderr); } diff --git a/deps/uv/test/test-ip6-addr.c b/deps/uv/test/test-ip6-addr.c index cf8491fb1b4d15..869b099e0fccaf 100644 --- a/deps/uv/test/test-ip6-addr.c +++ b/deps/uv/test/test-ip6-addr.c @@ -77,14 +77,16 @@ TEST_IMPL(ip6_addr_link_local) { device_name); #endif - LOGF("Testing link-local address %s " - "(iface_index: 0x%02x, device_name: %s)\n", - scoped_addr, - iface_index, - device_name); + fprintf(stderr, "Testing link-local address %s " + "(iface_index: 0x%02x, device_name: %s)\n", + scoped_addr, + iface_index, + device_name); + fflush(stderr); ASSERT(0 == uv_ip6_addr(scoped_addr, TEST_PORT, &addr)); - LOGF("Got scope_id 0x%02x\n", addr.sin6_scope_id); + fprintf(stderr, "Got scope_id 0x%02x\n", addr.sin6_scope_id); + fflush(stderr); ASSERT(iface_index == addr.sin6_scope_id); } diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index aac15e0d9df0b7..1e3c13d5e9267d 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -43,6 +43,7 @@ TEST_DECLARE (semaphore_1) TEST_DECLARE (semaphore_2) TEST_DECLARE (semaphore_3) TEST_DECLARE (tty) +TEST_DECLARE (tty_file) TEST_DECLARE (stdio_over_pipes) TEST_DECLARE (ip6_pton) TEST_DECLARE (ipc_listen_before_write) @@ -61,6 +62,7 @@ TEST_DECLARE (multiple_listen) TEST_DECLARE (tcp_write_after_connect) #endif TEST_DECLARE (tcp_writealot) +TEST_DECLARE (tcp_write_fail) TEST_DECLARE (tcp_try_write) TEST_DECLARE (tcp_write_queue_order) TEST_DECLARE (tcp_open) @@ -195,6 +197,9 @@ TEST_DECLARE (fail_always) TEST_DECLARE (pass_always) TEST_DECLARE (socket_buffer_size) TEST_DECLARE (spawn_fails) +#ifndef _WIN32 +TEST_DECLARE (spawn_fails_check_for_waitpid_cleanup) +#endif TEST_DECLARE (spawn_exit_code) TEST_DECLARE (spawn_stdout) TEST_DECLARE (spawn_stdin) @@ -209,6 +214,8 @@ TEST_DECLARE (spawn_setuid_fails) TEST_DECLARE (spawn_setgid_fails) TEST_DECLARE (spawn_stdout_to_file) TEST_DECLARE (spawn_stdout_and_stderr_to_file) +TEST_DECLARE (spawn_stdout_and_stderr_to_file2) +TEST_DECLARE (spawn_stdout_and_stderr_to_file_swap) TEST_DECLARE (spawn_auto_unref) TEST_DECLARE (spawn_closed_process_io) TEST_DECLARE (spawn_reads_child_path) @@ -227,6 +234,7 @@ TEST_DECLARE (fs_mkdtemp) TEST_DECLARE (fs_fstat) TEST_DECLARE (fs_access) TEST_DECLARE (fs_chmod) +TEST_DECLARE (fs_unlink_readonly) TEST_DECLARE (fs_chown) TEST_DECLARE (fs_link) TEST_DECLARE (fs_readlink) @@ -343,6 +351,7 @@ TASK_LIST_START #endif TEST_ENTRY (pipe_set_non_blocking) TEST_ENTRY (tty) + TEST_ENTRY (tty_file) TEST_ENTRY (stdio_over_pipes) TEST_ENTRY (ip6_pton) TEST_ENTRY (ipc_listen_before_write) @@ -372,6 +381,9 @@ TASK_LIST_START TEST_ENTRY (tcp_writealot) TEST_HELPER (tcp_writealot, tcp4_echo_server) + TEST_ENTRY (tcp_write_fail) + TEST_HELPER (tcp_write_fail, tcp4_echo_server) + TEST_ENTRY (tcp_try_write) TEST_ENTRY (tcp_write_queue_order) @@ -551,6 +563,9 @@ TASK_LIST_START TEST_ENTRY (socket_buffer_size) TEST_ENTRY (spawn_fails) +#ifndef _WIN32 + TEST_ENTRY (spawn_fails_check_for_waitpid_cleanup) +#endif TEST_ENTRY (spawn_exit_code) TEST_ENTRY (spawn_stdout) TEST_ENTRY (spawn_stdin) @@ -565,6 +580,8 @@ TASK_LIST_START TEST_ENTRY (spawn_setgid_fails) TEST_ENTRY (spawn_stdout_to_file) TEST_ENTRY (spawn_stdout_and_stderr_to_file) + TEST_ENTRY (spawn_stdout_and_stderr_to_file2) + TEST_ENTRY (spawn_stdout_and_stderr_to_file_swap) TEST_ENTRY (spawn_auto_unref) TEST_ENTRY (spawn_closed_process_io) TEST_ENTRY (spawn_reads_child_path) @@ -611,6 +628,7 @@ TASK_LIST_START TEST_ENTRY (fs_fstat) TEST_ENTRY (fs_access) TEST_ENTRY (fs_chmod) + TEST_ENTRY (fs_unlink_readonly) TEST_ENTRY (fs_chown) TEST_ENTRY (fs_utime) TEST_ENTRY (fs_futime) diff --git a/deps/uv/test/test-loop-handles.c b/deps/uv/test/test-loop-handles.c index 0986de52981e1b..c3e8498ae90a6b 100644 --- a/deps/uv/test/test-loop-handles.c +++ b/deps/uv/test/test-loop-handles.c @@ -113,7 +113,8 @@ static void timer_cb(uv_timer_t* handle) { static void idle_2_close_cb(uv_handle_t* handle) { - LOG("IDLE_2_CLOSE_CB\n"); + fprintf(stderr, "%s", "IDLE_2_CLOSE_CB\n"); + fflush(stderr); ASSERT(handle == (uv_handle_t*)&idle_2_handle); @@ -125,7 +126,8 @@ static void idle_2_close_cb(uv_handle_t* handle) { static void idle_2_cb(uv_idle_t* handle) { - LOG("IDLE_2_CB\n"); + fprintf(stderr, "%s", "IDLE_2_CB\n"); + fflush(stderr); ASSERT(handle == &idle_2_handle); @@ -138,7 +140,8 @@ static void idle_2_cb(uv_idle_t* handle) { static void idle_1_cb(uv_idle_t* handle) { int r; - LOG("IDLE_1_CB\n"); + fprintf(stderr, "%s", "IDLE_1_CB\n"); + fflush(stderr); ASSERT(handle != NULL); ASSERT(idles_1_active > 0); @@ -164,7 +167,8 @@ static void idle_1_cb(uv_idle_t* handle) { static void idle_1_close_cb(uv_handle_t* handle) { - LOG("IDLE_1_CLOSE_CB\n"); + fprintf(stderr, "%s", "IDLE_1_CLOSE_CB\n"); + fflush(stderr); ASSERT(handle != NULL); @@ -173,7 +177,8 @@ static void idle_1_close_cb(uv_handle_t* handle) { static void prepare_1_close_cb(uv_handle_t* handle) { - LOG("PREPARE_1_CLOSE_CB"); + fprintf(stderr, "%s", "PREPARE_1_CLOSE_CB"); + fflush(stderr); ASSERT(handle == (uv_handle_t*)&prepare_1_handle); prepare_1_close_cb_called++; @@ -181,7 +186,8 @@ static void prepare_1_close_cb(uv_handle_t* handle) { static void check_close_cb(uv_handle_t* handle) { - LOG("CHECK_CLOSE_CB\n"); + fprintf(stderr, "%s", "CHECK_CLOSE_CB\n"); + fflush(stderr); ASSERT(handle == (uv_handle_t*)&check_handle); check_close_cb_called++; @@ -189,7 +195,8 @@ static void check_close_cb(uv_handle_t* handle) { static void prepare_2_close_cb(uv_handle_t* handle) { - LOG("PREPARE_2_CLOSE_CB\n"); + fprintf(stderr, "%s", "PREPARE_2_CLOSE_CB\n"); + fflush(stderr); ASSERT(handle == (uv_handle_t*)&prepare_2_handle); prepare_2_close_cb_called++; @@ -199,8 +206,8 @@ static void prepare_2_close_cb(uv_handle_t* handle) { static void check_cb(uv_check_t* handle) { int i, r; - LOG("CHECK_CB\n"); - + fprintf(stderr, "%s", "CHECK_CB\n"); + fflush(stderr); ASSERT(handle == &check_handle); if (loop_iteration < ITERATIONS) { @@ -235,8 +242,8 @@ static void check_cb(uv_check_t* handle) { static void prepare_2_cb(uv_prepare_t* handle) { int r; - LOG("PREPARE_2_CB\n"); - + fprintf(stderr, "%s", "PREPARE_2_CB\n"); + fflush(stderr); ASSERT(handle == &prepare_2_handle); /* prepare_2 gets started by prepare_1 when (loop_iteration % 2 == 0), */ @@ -255,8 +262,8 @@ static void prepare_2_cb(uv_prepare_t* handle) { static void prepare_1_cb(uv_prepare_t* handle) { int r; - LOG("PREPARE_1_CB\n"); - + fprintf(stderr, "%s", "PREPARE_1_CB\n"); + fflush(stderr); ASSERT(handle == &prepare_1_handle); if (loop_iteration % 2 == 0) { diff --git a/deps/uv/test/test-osx-select.c b/deps/uv/test/test-osx-select.c index 6ccf603483488a..a0afda9181ebd9 100644 --- a/deps/uv/test/test-osx-select.c +++ b/deps/uv/test/test-osx-select.c @@ -39,6 +39,7 @@ static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { fprintf(stdout, "got data %d\n", ++read_count); + fflush(stdout); if (read_count == 3) uv_close((uv_handle_t*) stream, NULL); @@ -55,7 +56,8 @@ TEST_IMPL(osx_select) { fd = open("/dev/tty", O_RDONLY); if (fd < 0) { - LOGF("Cannot open /dev/tty as read-only: %s\n", strerror(errno)); + fprintf(stderr, "Cannot open /dev/tty as read-only: %s\n", strerror(errno)); + fflush(stderr); return TEST_SKIP; } @@ -107,7 +109,8 @@ TEST_IMPL(osx_select_many_fds) { fd = open("/dev/tty", O_RDONLY); if (fd < 0) { - LOGF("Cannot open /dev/tty as read-only: %s\n", strerror(errno)); + fprintf(stderr, "Cannot open /dev/tty as read-only: %s\n", strerror(errno)); + fflush(stderr); return TEST_SKIP; } diff --git a/deps/uv/test/test-pipe-set-non-blocking.c b/deps/uv/test/test-pipe-set-non-blocking.c index 5cf2c19e7fbd29..fcc9fc0da85e99 100644 --- a/deps/uv/test/test-pipe-set-non-blocking.c +++ b/deps/uv/test/test-pipe-set-non-blocking.c @@ -88,8 +88,8 @@ TEST_IMPL(pipe_set_non_blocking) { uv_close((uv_handle_t*) &pipe_handle, NULL); ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - ASSERT(0 == close(fd[1])); /* fd[0] is closed by uv_close(). */ ASSERT(0 == uv_thread_join(&thread)); + ASSERT(0 == close(fd[1])); /* fd[0] is closed by uv_close(). */ uv_barrier_destroy(&ctx.barrier); MAKE_VALGRIND_HAPPY(); diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index 9b0030029c187c..d01862abe1d97a 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -21,6 +21,7 @@ #include "uv.h" #include "task.h" +#include #include #include #include @@ -34,6 +35,7 @@ # include #else # include +# include #endif @@ -180,6 +182,37 @@ TEST_IMPL(spawn_fails) { } +#ifndef _WIN32 +TEST_IMPL(spawn_fails_check_for_waitpid_cleanup) { + int r; + int status; + int err; + + init_process_options("", fail_cb); + options.file = options.args[0] = "program-that-had-better-not-exist"; + + r = uv_spawn(uv_default_loop(), &process, &options); + ASSERT(r == UV_ENOENT || r == UV_EACCES); + ASSERT(0 == uv_is_active((uv_handle_t*) &process)); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + /* verify the child is successfully cleaned up within libuv */ + do + err = waitpid(process.pid, &status, 0); + while (err == -1 && errno == EINTR); + + ASSERT(err == -1); + ASSERT(errno == ECHILD); + + uv_close((uv_handle_t*) &process, NULL); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif + + TEST_IMPL(spawn_exit_code) { int r; @@ -342,6 +375,163 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file) { } +TEST_IMPL(spawn_stdout_and_stderr_to_file2) { +#ifndef _WIN32 + int r; + uv_file file; + uv_fs_t fs_req; + uv_stdio_container_t stdio[3]; + uv_buf_t buf; + + /* Setup. */ + unlink("stdout_file"); + + init_process_options("spawn_helper6", exit_cb); + + /* Replace stderr with our file */ + r = uv_fs_open(uv_default_loop(), + &fs_req, + "stdout_file", + O_CREAT | O_RDWR, + S_IRUSR | S_IWUSR, + NULL); + ASSERT(r != -1); + uv_fs_req_cleanup(&fs_req); + file = dup2(r, STDERR_FILENO); + ASSERT(file != -1); + + options.stdio = stdio; + options.stdio[0].flags = UV_IGNORE; + options.stdio[1].flags = UV_INHERIT_FD; + options.stdio[1].data.fd = file; + options.stdio[2].flags = UV_INHERIT_FD; + options.stdio[2].data.fd = file; + options.stdio_count = 3; + + r = uv_spawn(uv_default_loop(), &process, &options); + ASSERT(r == 0); + + r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); + ASSERT(r == 0); + + ASSERT(exit_cb_called == 1); + ASSERT(close_cb_called == 1); + + buf = uv_buf_init(output, sizeof(output)); + r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL); + ASSERT(r == 27); + uv_fs_req_cleanup(&fs_req); + + r = uv_fs_close(uv_default_loop(), &fs_req, file, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&fs_req); + + printf("output is: %s", output); + ASSERT(strcmp("hello world\nhello errworld\n", output) == 0); + + /* Cleanup. */ + unlink("stdout_file"); + + MAKE_VALGRIND_HAPPY(); + return 0; +#else + RETURN_SKIP("Unix only test"); +#endif +} + + +TEST_IMPL(spawn_stdout_and_stderr_to_file_swap) { +#ifndef _WIN32 + int r; + uv_file stdout_file; + uv_file stderr_file; + uv_fs_t fs_req; + uv_stdio_container_t stdio[3]; + uv_buf_t buf; + + /* Setup. */ + unlink("stdout_file"); + unlink("stderr_file"); + + init_process_options("spawn_helper6", exit_cb); + + /* open 'stdout_file' and replace STDOUT_FILENO with it */ + r = uv_fs_open(uv_default_loop(), + &fs_req, + "stdout_file", + O_CREAT | O_RDWR, + S_IRUSR | S_IWUSR, + NULL); + ASSERT(r != -1); + uv_fs_req_cleanup(&fs_req); + stdout_file = dup2(r, STDOUT_FILENO); + ASSERT(stdout_file != -1); + + /* open 'stderr_file' and replace STDERR_FILENO with it */ + r = uv_fs_open(uv_default_loop(), &fs_req, "stderr_file", O_CREAT | O_RDWR, + S_IRUSR | S_IWUSR, NULL); + ASSERT(r != -1); + uv_fs_req_cleanup(&fs_req); + stderr_file = dup2(r, STDERR_FILENO); + ASSERT(stderr_file != -1); + + /* now we're going to swap them: the child process' stdout will be our + * stderr_file and vice versa */ + options.stdio = stdio; + options.stdio[0].flags = UV_IGNORE; + options.stdio[1].flags = UV_INHERIT_FD; + options.stdio[1].data.fd = stderr_file; + options.stdio[2].flags = UV_INHERIT_FD; + options.stdio[2].data.fd = stdout_file; + options.stdio_count = 3; + + r = uv_spawn(uv_default_loop(), &process, &options); + ASSERT(r == 0); + + r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); + ASSERT(r == 0); + + ASSERT(exit_cb_called == 1); + ASSERT(close_cb_called == 1); + + buf = uv_buf_init(output, sizeof(output)); + + /* check the content of stdout_file */ + r = uv_fs_read(uv_default_loop(), &fs_req, stdout_file, &buf, 1, 0, NULL); + ASSERT(r >= 15); + uv_fs_req_cleanup(&fs_req); + + r = uv_fs_close(uv_default_loop(), &fs_req, stdout_file, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&fs_req); + + printf("output is: %s", output); + ASSERT(strncmp("hello errworld\n", output, 15) == 0); + + /* check the content of stderr_file */ + r = uv_fs_read(uv_default_loop(), &fs_req, stderr_file, &buf, 1, 0, NULL); + ASSERT(r >= 12); + uv_fs_req_cleanup(&fs_req); + + r = uv_fs_close(uv_default_loop(), &fs_req, stderr_file, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&fs_req); + + printf("output is: %s", output); + ASSERT(strncmp("hello world\n", output, 12) == 0); + + /* Cleanup. */ + unlink("stdout_file"); + unlink("stderr_file"); + + MAKE_VALGRIND_HAPPY(); + return 0; +#else + RETURN_SKIP("Unix only test"); +#endif +} + + TEST_IMPL(spawn_stdin) { int r; uv_pipe_t out; @@ -1007,7 +1197,7 @@ TEST_IMPL(environment_creation) { return 0; } -// Regression test for issue #909 +/* Regression test for issue #909 */ TEST_IMPL(spawn_with_an_odd_path) { int r; diff --git a/deps/uv/test/test-tcp-write-fail.c b/deps/uv/test/test-tcp-write-fail.c new file mode 100644 index 00000000000000..2840d8161032be --- /dev/null +++ b/deps/uv/test/test-tcp-write-fail.c @@ -0,0 +1,115 @@ +/* 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" +#include +#include +#ifndef _WIN32 +# include +#endif + + +static int connect_cb_called = 0; +static int write_cb_called = 0; +static int close_cb_called = 0; + +static uv_connect_t connect_req; +static uv_write_t write_req; + + +static void close_socket(uv_tcp_t* sock) { + uv_os_fd_t fd; + int r; + + r = uv_fileno((uv_handle_t*)sock, &fd); + ASSERT(r == 0); +#ifdef _WIN32 + r = closesocket(fd); +#else + r = close(fd); +#endif + ASSERT(r == 0); +} + + +static void close_cb(uv_handle_t* handle) { + ASSERT(handle != NULL); + close_cb_called++; +} + + +static void write_cb(uv_write_t* req, int status) { + ASSERT(req != NULL); + + ASSERT(status != 0); + fprintf(stderr, "uv_write error: %s\n", uv_strerror(status)); + write_cb_called++; + + uv_close((uv_handle_t*)(req->handle), close_cb); +} + + +static void connect_cb(uv_connect_t* req, int status) { + uv_buf_t buf; + uv_stream_t* stream; + int r; + + ASSERT(req == &connect_req); + ASSERT(status == 0); + + stream = req->handle; + connect_cb_called++; + + /* close the socket, the hard way */ + close_socket((uv_tcp_t*)stream); + + buf = uv_buf_init("hello\n", 6); + r = uv_write(&write_req, stream, &buf, 1, write_cb); + ASSERT(r == 0); +} + + +TEST_IMPL(tcp_write_fail) { + struct sockaddr_in addr; + uv_tcp_t client; + int r; + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + + r = uv_tcp_init(uv_default_loop(), &client); + ASSERT(r == 0); + + r = uv_tcp_connect(&connect_req, + &client, + (const struct sockaddr*) &addr, + connect_cb); + ASSERT(r == 0); + + uv_run(uv_default_loop(), UV_RUN_DEFAULT); + + ASSERT(connect_cb_called == 1); + ASSERT(write_cb_called == 1); + ASSERT(close_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test-timer-again.c b/deps/uv/test/test-timer-again.c index 095cd9e707baa8..f93c509be5dc0a 100644 --- a/deps/uv/test/test-timer-again.c +++ b/deps/uv/test/test-timer-again.c @@ -47,8 +47,9 @@ static void repeat_1_cb(uv_timer_t* handle) { ASSERT(handle == &repeat_1); ASSERT(uv_timer_get_repeat((uv_timer_t*)handle) == 50); - LOGF("repeat_1_cb called after %ld ms\n", - (long int)(uv_now(uv_default_loop()) - start_time)); + fprintf(stderr, "repeat_1_cb called after %ld ms\n", + (long int)(uv_now(uv_default_loop()) - start_time)); + fflush(stderr); repeat_1_cb_called++; @@ -69,8 +70,9 @@ static void repeat_2_cb(uv_timer_t* handle) { ASSERT(handle == &repeat_2); ASSERT(repeat_2_cb_allowed); - LOGF("repeat_2_cb called after %ld ms\n", - (long int)(uv_now(uv_default_loop()) - start_time)); + fprintf(stderr, "repeat_2_cb called after %ld ms\n", + (long int)(uv_now(uv_default_loop()) - start_time)); + fflush(stderr); repeat_2_cb_called++; @@ -80,8 +82,9 @@ static void repeat_2_cb(uv_timer_t* handle) { return; } - LOGF("uv_timer_get_repeat %ld ms\n", - (long int)uv_timer_get_repeat(&repeat_2)); + fprintf(stderr, "uv_timer_get_repeat %ld ms\n", + (long int)uv_timer_get_repeat(&repeat_2)); + fflush(stderr); ASSERT(uv_timer_get_repeat(&repeat_2) == 100); /* This shouldn't take effect immediately. */ @@ -129,8 +132,9 @@ TEST_IMPL(timer_again) { ASSERT(repeat_2_cb_called == 2); ASSERT(close_cb_called == 2); - LOGF("Test took %ld ms (expected ~700 ms)\n", - (long int)(uv_now(uv_default_loop()) - start_time)); + fprintf(stderr, "Test took %ld ms (expected ~700 ms)\n", + (long int)(uv_now(uv_default_loop()) - start_time)); + fflush(stderr); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/uv/test/test-tty.c b/deps/uv/test/test-tty.c index 7e1ce2668899f8..81e612c1d6ae1c 100644 --- a/deps/uv/test/test-tty.c +++ b/deps/uv/test/test-tty.c @@ -66,13 +66,15 @@ TEST_IMPL(tty) { #else /* unix */ ttyin_fd = open("/dev/tty", O_RDONLY, 0); if (ttyin_fd < 0) { - LOGF("Cannot open /dev/tty as read-only: %s\n", strerror(errno)); + fprintf(stderr, "Cannot open /dev/tty as read-only: %s\n", strerror(errno)); + fflush(stderr); return TEST_SKIP; } ttyout_fd = open("/dev/tty", O_WRONLY, 0); if (ttyout_fd < 0) { - LOGF("Cannot open /dev/tty as write-only: %s\n", strerror(errno)); + fprintf(stderr, "Cannot open /dev/tty as write-only: %s\n", strerror(errno)); + fflush(stderr); return TEST_SKIP; } #endif @@ -111,13 +113,20 @@ TEST_IMPL(tty) { ASSERT(height > 10); /* Turn on raw mode. */ - r = uv_tty_set_mode(&tty_in, 1); + r = uv_tty_set_mode(&tty_in, UV_TTY_MODE_RAW); ASSERT(r == 0); /* Turn off raw mode. */ - r = uv_tty_set_mode(&tty_in, 0); + r = uv_tty_set_mode(&tty_in, UV_TTY_MODE_NORMAL); ASSERT(r == 0); + /* Calling uv_tty_reset_mode() repeatedly should not clobber errno. */ + errno = 0; + ASSERT(0 == uv_tty_reset_mode()); + ASSERT(0 == uv_tty_reset_mode()); + ASSERT(0 == uv_tty_reset_mode()); + ASSERT(0 == errno); + /* TODO check the actual mode! */ uv_close((uv_handle_t*) &tty_in, NULL); @@ -128,3 +137,45 @@ TEST_IMPL(tty) { MAKE_VALGRIND_HAPPY(); return 0; } + + +TEST_IMPL(tty_file) { +#ifndef _WIN32 + uv_loop_t loop; + uv_tty_t tty; + int fd; + + ASSERT(0 == uv_loop_init(&loop)); + + fd = open("test/fixtures/empty_file", O_RDONLY); + if (fd != -1) { + ASSERT(UV_EINVAL == uv_tty_init(&loop, &tty, fd, 1)); + ASSERT(0 == close(fd)); + } + + fd = open("/dev/random", O_RDONLY); + if (fd != -1) { + ASSERT(UV_EINVAL == uv_tty_init(&loop, &tty, fd, 1)); + ASSERT(0 == close(fd)); + } + + fd = open("/dev/zero", O_RDONLY); + if (fd != -1) { + ASSERT(UV_EINVAL == uv_tty_init(&loop, &tty, fd, 1)); + ASSERT(0 == close(fd)); + } + + fd = open("/dev/tty", O_RDONLY); + if (fd != -1) { + ASSERT(0 == uv_tty_init(&loop, &tty, fd, 1)); + ASSERT(0 == close(fd)); + uv_close((uv_handle_t*) &tty, NULL); + } + + ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT)); + ASSERT(0 == uv_loop_close(&loop)); + + MAKE_VALGRIND_HAPPY(); +#endif + return 0; +} diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 1ef8c05adc6496..acaed862d7c66e 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -39,7 +39,7 @@ '_FILE_OFFSET_BITS=64', ], }], - ['OS == "mac"', { + ['OS in "mac ios"', { 'defines': [ '_DARWIN_USE_64_BIT_INODE=1' ], }], ['OS == "linux"', { @@ -167,18 +167,17 @@ 'cflags': [ '-fPIC' ], }], ['uv_library=="shared_library" and OS!="mac"', { - 'link_settings': { - # Must correspond with UV_VERSION_MAJOR and UV_VERSION_MINOR - # in include/uv-version.h - 'libraries': [ '-Wl,-soname,libuv.so.1.0' ], - }, + # This will cause gyp to set soname + # Must correspond with UV_VERSION_MAJOR + # in include/uv-version.h + 'product_extension': 'so.1', }], ], }], - [ 'OS in "linux mac android"', { + [ 'OS in "linux mac ios android"', { 'sources': [ 'src/unix/proctitle.c' ], }], - [ 'OS=="mac"', { + [ 'OS in "mac ios"', { 'sources': [ 'src/unix/darwin.c', 'src/unix/fsevents.c', @@ -261,7 +260,7 @@ 'libraries': [ '-lkvm' ], }, }], - [ 'OS in "mac freebsd dragonflybsd openbsd netbsd".split()', { + [ 'OS in "ios mac freebsd dragonflybsd openbsd netbsd".split()', { 'sources': [ 'src/unix/kqueue.c' ], }], ['uv_library=="shared_library"', { @@ -364,6 +363,7 @@ 'test/test-tcp-write-to-half-open-connection.c', 'test/test-tcp-write-after-connect.c', 'test/test-tcp-writealot.c', + 'test/test-tcp-write-fail.c', 'test/test-tcp-try-write.c', 'test/test-tcp-unexpected-read.c', 'test/test-tcp-oob.c', diff --git a/deps/uv/vcbuild.bat b/deps/uv/vcbuild.bat index d3b7aa154eec6a..084ab9578fe10d 100644 --- a/deps/uv/vcbuild.bat +++ b/deps/uv/vcbuild.bat @@ -90,8 +90,8 @@ if defined noprojgen goto msbuild @rem Generate the VS project. if exist build\gyp goto have_gyp -echo git clone https://git.chromium.org/external/gyp.git build/gyp -git clone https://git.chromium.org/external/gyp.git build/gyp +echo git clone https://chromium.googlesource.com/external/gyp build/gyp +git clone https://chromium.googlesource.com/external/gyp build/gyp if errorlevel 1 goto gyp_install_failed goto have_gyp