From f61d9405bfcf0fa113a13d57d41fef7d74a69538 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Fri, 13 Dec 2013 22:35:09 +0400 Subject: uv: Upgrade to v0.11.16 --- deps/uv/.gitignore | 1 + deps/uv/.mailmap | 2 + deps/uv/AUTHORS | 9 ++ deps/uv/CONTRIBUTING.md | 177 ++++++++++++++++++++++++++++++++++++++ deps/uv/ChangeLog | 42 ++++++++- deps/uv/Makefile.am | 15 +++- deps/uv/README.md | 15 +++- deps/uv/configure.ac | 7 +- deps/uv/gyp_uv.py | 2 +- deps/uv/include/uv-errno.h | 2 + deps/uv/include/uv.h | 13 +++ deps/uv/libuv.pc.in | 11 +++ deps/uv/src/unix/core.c | 3 + deps/uv/src/unix/darwin.c | 2 +- deps/uv/src/unix/fs.c | 2 +- deps/uv/src/unix/fsevents.c | 26 +++--- deps/uv/src/unix/internal.h | 1 - deps/uv/src/unix/signal.c | 1 + deps/uv/src/unix/stream.c | 76 ++++++++++++---- deps/uv/src/uv-common.c | 18 ++-- deps/uv/src/version.c | 4 +- deps/uv/src/win/core.c | 3 + deps/uv/src/win/fs-event.c | 3 +- deps/uv/src/win/process.c | 150 +++++++++++++++----------------- deps/uv/src/win/stream.c | 6 ++ deps/uv/src/win/util.c | 25 +++--- deps/uv/test/test-emfile.c | 111 ++++++++++++++++++++++++ deps/uv/test/test-ip4-addr.c | 46 ++++++++++ deps/uv/test/test-list.h | 9 ++ deps/uv/test/test-loop-time.c | 34 ++++++++ deps/uv/test/test-tcp-try-write.c | 143 ++++++++++++++++++++++++++++++ deps/uv/uv.gyp | 4 + 32 files changed, 824 insertions(+), 139 deletions(-) create mode 100644 deps/uv/CONTRIBUTING.md create mode 100644 deps/uv/libuv.pc.in create mode 100644 deps/uv/test/test-emfile.c create mode 100644 deps/uv/test/test-ip4-addr.c create mode 100644 deps/uv/test/test-loop-time.c create mode 100644 deps/uv/test/test-tcp-try-write.c (limited to 'deps/uv') diff --git a/deps/uv/.gitignore b/deps/uv/.gitignore index 506f04ab07..c8d93d8d08 100644 --- a/deps/uv/.gitignore +++ b/deps/uv/.gitignore @@ -3,6 +3,7 @@ *.l[oa] *.opensdf *.orig +*.pyc *.sdf *.suo core diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index a2cf836e41..a1e5f71abf 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.mailmap @@ -8,6 +8,8 @@ Frank Denis Isaac Z. Schlueter Keno Fischer Keno Fischer +Maciej Małecki +Marc Schlaich Robert Mustacchi Ryan Dahl Ryan Emery diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index a9c63bf605..a7c48c4f38 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -99,3 +99,12 @@ Maks Naumov Sean Farrell Chris Bank Geert Jansen +Alex Gaynor +huxingyi +ci-innoq +Steven Kabbes +Tenor Biel +Andrej Manduch +Joshua Neuheisel +Alexis Campailla +Yorkie diff --git a/deps/uv/CONTRIBUTING.md b/deps/uv/CONTRIBUTING.md new file mode 100644 index 0000000000..960a9450ae --- /dev/null +++ b/deps/uv/CONTRIBUTING.md @@ -0,0 +1,177 @@ +# CONTRIBUTING + +The libuv project welcomes new contributors. This document will guide you +through the process. + + +### FORK + +Fork the project [on GitHub](https://github.com/joyent/libuv) and check out +your copy. + +``` +$ git clone https://github.com/username/libuv.git +$ cd libuv +$ git remote add upstream https://github.com/joyent/libuv.git +``` + +Now decide if you want your feature or bug fix to go into the master branch +or the stable branch. As a rule of thumb, bug fixes go into the stable branch +while new features go into the master branch. + +The stable branch is effectively frozen; patches that change the libuv +API/ABI or affect the run-time behavior of applications get rejected. + +In case of doubt, open an issue in the [issue tracker][], post your question +to the [libuv mailing list], or contact one of project maintainers +(@bnoordhuis, @piscisaureus, @indutny or @saghul) on [IRC][]. + +Especially do so if you plan to work on something big. Nothing is more +frustrating than seeing your hard work go to waste because your vision +does not align with that of a project maintainers. + + +### BRANCH + +Okay, so you have decided on the proper branch. Create a feature branch +and start hacking: + +``` +$ git checkout -b my-feature-branch -t origin/v0.10 +``` + +(Where v0.10 is the latest stable branch as of this writing.) + +### CODE + +Please adhere to libuv's code style. In general it follows the conventions from +the [Google C/C++ style guide]. Some of the key points, as well as some +additional guidelines, are enumerated below. + +* Code that is specific to unix-y platforms should be placed in `src/unix`, and + declarations go into `src/uv-unix.h`. + +* Source code that is Windows-specific goes into `src/win`, and related + publicly exported types, functions and macro declarations should generally + be declared in `include/uv-win.h`. + +* Names should be descriptive and concise. + +* All the symbols and types that libuv makes available publicly should be + prefixed with `uv_` (or `UV_` in case of macros). + +* Internal, non-static functions should be prefixed with `uv__`. + +* Use two spaces and no tabs. + +* Lines should be wrapped at 80 characters. + +* Ensure that lines have no trailing whitespace, and use unix-style (LF) line + endings. + +* Use C89-compliant syntax. In other words, variables can only be declared at + the top of a scope (function, if/for/while-block). + +* When writing comments, use properly constructed sentences, including + punctuation. + +* When documenting APIs and/or source code, don't make assumptions or make + implications about race, gender, religion, political orientation or anything + else that isn't relevant to the project. + +* Remember that source code usually gets written once and read often: ensure + the reader doesn't have to make guesses. Make sure that the purpose and inner + logic are either obvious to a reasonably skilled professional, or add a + comment that explains it. + + +### COMMIT + +Make sure git knows your name and email address: + +``` +$ git config --global user.name "J. Random User" +$ git config --global user.email "j.random.user@example.com" +``` + +Writing good commit logs is important. A commit log should describe what +changed and why. Follow these guidelines when writing one: + +1. The first line should be 50 characters or less and contain a short + description of the change prefixed with the name of the changed + subsystem (e.g. "net: add localAddress and localPort to Socket"). +2. Keep the second line blank. +3. Wrap all other lines at 72 columns. + +A good commit log looks like this: + +``` +subsystem: explaining the commit in one line + +Body of commit message is a few lines of text, explaining things +in more detail, possibly giving some background about the issue +being fixed, etc etc. + +The body of the commit message can be several paragraphs, and +please do proper word-wrap and keep columns shorter than about +72 characters or so. That way `git log` will show things +nicely even when it is indented. +``` + +The header line should be meaningful; it is what other people see when they +run `git shortlog` or `git log --oneline`. + +Check the output of `git log --oneline files_that_you_changed` to find out +what subsystem (or subsystems) your changes touch. + + +### REBASE + +Use `git rebase` (not `git merge`) to sync your work from time to time. + +``` +$ git fetch upstream +$ git rebase upstream/v0.10 # or upstream/master +``` + + +### TEST + +Bug fixes and features should come with tests. Add your tests in the +`test/` directory. Tests also need to be registered in `test/test-list.h`. +Look at other tests to see how they should be structured (license boilerplate, +the way entry points are declared, etc.). + +``` +$ make test +``` + +Make sure that there are no test regressions. + +### PUSH + +``` +$ git push origin my-feature-branch +``` + +Go to https://github.com/username/libuv and select your feature branch. Click +the 'Pull Request' button and fill out the form. + +Pull requests are usually reviewed within a few days. If there are comments +to address, apply your changes in a separate commit and push that to your +feature branch. Post a comment in the pull request afterwards; GitHub does +not send out notifications when you add commits. + + +### CONTRIBUTOR LICENSE AGREEMENT + +The current state of affairs is that, in order to get a patch accepted, you need +to sign Node.js's [contributor license agreement][]. You only need to do that +once. + + +[issue tracker]: https://github.com/joyent/libuv/issues +[libuv mailing list]: http://groups.google.com/group/libuv +[IRC]: http://webchat.freelibuv.net/?channels=libuv +[Google C/C++ style guide]: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml +[contributor license agreement]: http://nodejs.org/cla.html diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 0e5638f887..5ee5338236 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,4 +1,44 @@ -2013.11.21, Version 0.11.15 (Unstable) +2013.12.14, Version 0.11.16 (Unstable), ae0ed8c49d0d313c935c22077511148b6e8408a4 + +Changes since version 0.11.15: + +* fsevents: remove kFSEventStreamCreateFlagNoDefer polyfill (ci-innoq) + +* libuv: add more getaddrinfo errors (Steven Kabbes) + +* unix: fix accept() EMFILE error handling (Ben Noordhuis) + +* linux: fix up SO_REUSEPORT back-port (Ben Noordhuis) + +* fsevents: fix subfolder check (Fedor Indutny) + +* fsevents: fix invalid memory access (huxingyi) + +* windows/timer: fix uv_hrtime discontinuity (Bert Belder) + +* unix: fix various memory leaks and undef behavior (Fedor Indutny) + +* unix, windows: always update loop time (Saúl Ibarra Corretgé) + +* windows: translate system errors in uv_spawn (Alexis Campailla) + +* windows: uv_spawn code refactor (Alexis Campailla) + +* unix, windows: detect errors in uv_ip4/6_addr (Yorkie) + +* stream: introduce uv_try_write(...) (Fedor Indutny) + + +2013.12.13, Version 0.10.20 (Stable), 04141464dd0fba90ace9aa6f7003ce139b888a40 + +Changes since version 0.10.19: + +* linux: fix up SO_REUSEPORT back-port (Ben Noordhuis) + +* fs-event: fix invalid memory access (huxingyi) + + +2013.11.21, Version 0.11.15 (Unstable), bfe645ed7e99ca5670d9279ad472b604c129d2e5 Changes since version 0.11.14: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 8f656f36f4..2229e86f3d 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -126,6 +126,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-delayed-accept.c \ test/test-dlerror.c \ test/test-embed.c \ + test/test-emfile.c \ test/test-error.c \ test/test-fail-always.c \ test/test-fs-event.c \ @@ -138,12 +139,14 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-getsockname.c \ test/test-hrtime.c \ test/test-idle.c \ + test/test-ip4-addr.c \ test/test-ip6-addr.c \ test/test-ipc-send-recv.c \ test/test-ipc.c \ test/test-list.h \ test/test-loop-handles.c \ test/test-loop-stop.c \ + test/test-loop-time.c \ test/test-multiple-listen.c \ test/test-mutexes.c \ test/test-osx-select.c \ @@ -181,6 +184,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-tcp-unexpected-read.c \ test/test-tcp-write-to-half-open-connection.c \ test/test-tcp-writealot.c \ + test/test-tcp-try-write.c \ test/test-thread.c \ test/test-threadpool-cancel.c \ test/test-threadpool.c \ @@ -266,10 +270,18 @@ libuv_la_LIBADD = uv-dtrace.lo CLEANFILES += src/unix/uv-dtrace.o src/unix/uv-dtrace.lo endif -SUFFIXES = .d +if HAVE_PKG_CONFIG +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = @PACKAGE_NAME@.pc +endif +if HAVE_DTRACE include/uv-dtrace.h: src/unix/uv-dtrace.d $(AM_V_GEN)$(DTRACE) $(DTRACEFLAGS) -h -xnolibs -s $< -o $(top_srcdir)/$@ +endif + +if DTRACE_NEEDS_OBJECTS +SUFFIXES = .d src/unix/uv-dtrace.o: src/unix/uv-dtrace.d ${libuv_la_OBJECTS} @@ -285,3 +297,4 @@ src/unix/uv-dtrace.o: src/unix/uv-dtrace.d ${libuv_la_OBJECTS} "pic_object='uv-dtrace.o'" \ "non_pic_object='uv-dtrace.o'" \ > ${top_builddir}/uv-dtrace.lo +endif diff --git a/deps/uv/README.md b/deps/uv/README.md index ce43f6d99e..0b0f17f649 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -1,7 +1,7 @@ # libuv libuv is a multi-platform support library with a focus on asynchronous I/O. It -was primarily developed for use by [Node.js](http://node.js.org), but it's also +was primarily developed for use by [Node.js](http://nodejs.org), but it's also used by Mozilla's [Rust language](http://www.rust-lang.org/), [Luvit](http://luvit.io/), [Julia](http://julialang.org/), [pyuv](https://crate.io/packages/pyuv/), and others. @@ -103,6 +103,14 @@ 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. +### Running tests + +Run: + + $ ./gyp_uv.py -f make + $ make -C out + $ ./out/Debug/run-tests + ## Supported Platforms Microsoft Windows operating systems since Windows XP SP2. It can be built @@ -116,6 +124,11 @@ OS X using the GCC or XCode toolchain. Solaris 121 and later using GCC toolchain. +## patches + +See the [guidelines for contributing][]. + [node.js]: http://nodejs.org/ [GYP]: http://code.google.com/p/gyp/ [Visual Studio Express 2010]: http://www.microsoft.com/visualstudio/eng/products/visual-studio-2010-express +[guidelines for contributing]: https://github.com/joyent/libuv/blob/master/CONTRIBUTING.md diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index fda951ee14..c8b32573d4 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], [0.11.15], [https://github.com/joyent/libuv/issues]) +AC_INIT([libuv], [0.11.17], [https://github.com/joyent/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects] UV_EXTRA_AUTOMAKE_FLAGS) @@ -46,5 +46,10 @@ AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os], [openbsd*], [true], [false])]) AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os], [solaris*], [true], [false])]) AM_CONDITIONAL([WINNT], [AS_CASE([$host_os], [mingw*], [true], [false])]) PANDORA_ENABLE_DTRACE +AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes) +AM_CONDITIONAL([HAVE_PKG_CONFIG], [test "x$PKG_CONFIG" = "xyes"]) +AS_IF([test "x$PKG_CONFIG" = "xyes"], [ + AC_CONFIG_FILES([libuv.pc]) +]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/deps/uv/gyp_uv.py b/deps/uv/gyp_uv.py index 651bd095f1..4ba69167d9 100755 --- a/deps/uv/gyp_uv.py +++ b/deps/uv/gyp_uv.py @@ -75,7 +75,7 @@ if __name__ == '__main__': if sys.platform != 'win32': if '-f' not in args: args.extend('-f make'.split()) - if 'ninja' not in args: + if 'eclipse' not in args and 'ninja' not in args: args.extend(['-Goutput_dir=' + output_dir]) args.extend(['--generator-output', output_dir]) (major, minor), is_clang = compiler_version() diff --git a/deps/uv/include/uv-errno.h b/deps/uv/include/uv-errno.h index ce895b7264..797bcab93b 100644 --- a/deps/uv/include/uv-errno.h +++ b/deps/uv/include/uv-errno.h @@ -40,6 +40,8 @@ #define UV__EAI_SERVICE (-3010) #define UV__EAI_SOCKTYPE (-3011) #define UV__EAI_SYSTEM (-3012) /* TODO(bnoordhuis) Return system error. */ +#define UV__EAI_BADHINTS (-3013) +#define UV__EAI_PROTOCOL (-3014) /* Only map to the system errno on non-Windows platforms. It's apparently * a fairly common practice for Windows programmers to redefine errno codes. diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index c3ba250237..d6485e52b0 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -71,12 +71,15 @@ extern "C" { XX(EAI_ADDRFAMILY, "address family not supported") \ XX(EAI_AGAIN, "temporary failure") \ XX(EAI_BADFLAGS, "bad ai_flags value") \ + XX(EAI_BADHINTS, "invalid value for hints") \ XX(EAI_CANCELED, "request canceled") \ XX(EAI_FAIL, "permanent failure") \ XX(EAI_FAMILY, "ai_family not supported") \ XX(EAI_MEMORY, "out of memory") \ XX(EAI_NODATA, "no address") \ XX(EAI_NONAME, "unknown node or service") \ + XX(EAI_OVERFLOW, "argument buffer overflow") \ + XX(EAI_PROTOCOL, "resolved protocol is unknown") \ XX(EAI_SERVICE, "service not available for socket type") \ XX(EAI_SOCKTYPE, "socket type not supported") \ XX(EAI_SYSTEM, "system error") \ @@ -670,6 +673,16 @@ UV_EXTERN int uv_write2(uv_write_t* req, uv_stream_t* send_handle, uv_write_cb cb); +/* + * Same as `uv_write()`, but won't queue write request if it can't be completed + * immediately. + * Will return either: + * - positive number of bytes written + * - zero - if queued write is needed + * - negative error code + */ +UV_EXTERN int uv_try_write(uv_stream_t* handle, const char* buf, size_t length); + /* uv_write_t is a subclass of uv_req_t */ struct uv_write_s { UV_REQ_FIELDS diff --git a/deps/uv/libuv.pc.in b/deps/uv/libuv.pc.in new file mode 100644 index 0000000000..86c1a126cd --- /dev/null +++ b/deps/uv/libuv.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: @PACKAGE_NAME@ +Version: @PACKAGE_VERSION@ +Description: multi-platform support library with a focus on asynchronous I/O. + +Libs: -L${libdir} -luv +Cflags: -I${includedir} diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 79813a05df..6bb2057351 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -260,6 +260,9 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) { int r; r = uv__loop_alive(loop); + if (!r) + uv__update_time(loop); + while (r != 0 && loop->stop_flag == 0) { UV_TICK_START(loop, mode); diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c index c1655994e7..bc282e7912 100644 --- a/deps/uv/src/unix/darwin.c +++ b/deps/uv/src/unix/darwin.c @@ -75,7 +75,7 @@ int uv_exepath(char* buffer, size_t* size) { result = _NSGetExecutablePath(buffer, &usize); if (result) return result; - path = (char*)malloc(2 * PATH_MAX); + path = malloc(2 * PATH_MAX); fullpath = realpath(buffer, path); if (fullpath == NULL) { SAVE_ERRNO(free(path)); diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 64517c4652..4e572b7d96 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -313,7 +313,7 @@ static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) { * * 1. Read errors are reported only if nsent==0, otherwise we return nsent. * The user needs to know that some data has already been sent, to stop - * him from sending it twice. + * them from sending it twice. * * 2. Write errors are always reported. Write errors are bad because they * mean data loss: we've read data but now we can't write it out. diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c index 3618f46996..7faa1562a6 100644 --- a/deps/uv/src/unix/fsevents.c +++ b/deps/uv/src/unix/fsevents.c @@ -251,13 +251,15 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, if (strncmp(path, handle->realpath, handle->realpath_len) != 0) continue; - path += handle->realpath_len; - len -= handle->realpath_len; - - /* Skip back slash */ - if (*path != 0) { - path++; - len--; + if (handle->realpath_len > 1 || *handle->realpath != '/') { + path += handle->realpath_len; + len -= handle->realpath_len; + + /* Skip forward slash */ + if (*path != '\0') { + path++; + len--; + } } #ifdef MAC_OS_X_VERSION_10_7 @@ -267,9 +269,9 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, #endif /* MAC_OS_X_VERSION_10_7 */ /* Do not emit events from subdirectories (without option set) */ - if ((handle->cf_flags & UV_FS_EVENT_RECURSIVE) == 0) { - pos = strchr(path, '/'); - if (pos != NULL && pos != path + 1) + if ((handle->cf_flags & UV_FS_EVENT_RECURSIVE) == 0 && *path != 0) { + pos = strchr(path + 1, '/'); + if (pos != NULL) continue; } @@ -588,7 +590,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) { err = uv_mutex_init(&loop->cf_mutex); if (err) - return err; + goto fail_mutex_init; err = uv_sem_init(&loop->cf_sem, 0); if (err) @@ -658,6 +660,8 @@ fail_fsevent_sem_init: fail_sem_init: uv_mutex_destroy(&loop->cf_mutex); + +fail_mutex_init: free(state); return err; } diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 79e41faae8..0ea82b51a0 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -243,7 +243,6 @@ void uv__fsevents_loop_delete(uv_loop_t* loop); /* OSX < 10.7 has no file events, polyfill them */ #ifndef MAC_OS_X_VERSION_10_7 -static const int kFSEventStreamCreateFlagNoDefer = 0x00000002; static const int kFSEventStreamCreateFlagFileEvents = 0x00000010; static const int kFSEventStreamEventFlagItemCreated = 0x00000100; static const int kFSEventStreamEventFlagItemRemoved = 0x00000200; diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c index 8c0d62f32d..0b7a405c15 100644 --- a/deps/uv/src/unix/signal.c +++ b/deps/uv/src/unix/signal.c @@ -348,6 +348,7 @@ static void uv__signal_event(uv_loop_t* loop, int r; bytes = 0; + end = 0; do { r = read(loop->signal_pipefd[0], buf + bytes, sizeof(buf) - bytes); diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index abef01ee3f..afd2a051aa 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -462,27 +462,22 @@ void uv__stream_destroy(uv_stream_t* stream) { * calling close() and accept(). */ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) { - int fd; + int err; if (loop->emfile_fd == -1) return -EMFILE; uv__close(loop->emfile_fd); + loop->emfile_fd = -1; - for (;;) { - fd = uv__accept(accept_fd); - - if (fd != -1) { - uv__close(fd); - continue; - } - - if (errno == EINTR) - continue; + do { + err = uv__accept(accept_fd); + if (err >= 0) + uv__close(err); + } while (err >= 0 || err == -EINTR); - SAVE_ERRNO(loop->emfile_fd = uv__open_cloexec("/", O_RDONLY)); - return -errno; - } + SAVE_ERRNO(loop->emfile_fd = uv__open_cloexec("/", O_RDONLY)); + return err; } @@ -673,8 +668,8 @@ static void uv__write_req_finish(uv_write_t* req) { /* Only free when there was no error. On error, we touch up write_queue_size * right before making the callback. The reason we don't do that right away * is that a write_queue_size > 0 is our only way to signal to the user that - * he should stop writing - which he should if we got an error. Something to - * revisit in future revisions of the libuv API. + * they should stop writing - which they should if we got an error. Something + * to revisit in future revisions of the libuv API. */ if (req->error == 0) { if (req->bufs != req->bufsml) @@ -1304,6 +1299,55 @@ int uv_write(uv_write_t* req, } +void uv_try_write_cb(uv_write_t* req, int status) { + /* Should not be called */ + abort(); +} + + +int uv_try_write(uv_stream_t* stream, const char* buf, size_t size) { + int r; + int has_pollout; + size_t written; + size_t req_size; + uv_write_t req; + uv_buf_t bufstruct; + + /* Connecting or already writing some data */ + if (stream->connect_req != NULL || stream->write_queue_size != 0) + return 0; + + has_pollout = uv__io_active(&stream->io_watcher, UV__POLLOUT); + + bufstruct = uv_buf_init((char*) buf, size); + r = uv_write(&req, stream, &bufstruct, 1, uv_try_write_cb); + if (r != 0) + return r; + + /* Remove not written bytes from write queue size */ + written = size; + if (req.bufs != NULL) + req_size = uv__write_req_size(&req); + else + req_size = 0; + written -= req_size; + stream->write_queue_size -= req_size; + + /* Unqueue request, regardless of immediateness */ + QUEUE_REMOVE(&req.queue); + uv__req_unregister(stream->loop, &req); + if (req.bufs != req.bufsml) + free(req.bufs); + req.bufs = NULL; + + /* Do not poll for writable, if we wasn't before calling this */ + if (!has_pollout) + uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); + + return (int) written; +} + + static int uv__read_start_common(uv_stream_t* stream, uv_alloc_cb alloc_cb, uv_read_cb read_cb, diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 4129a36686..c4cf3c7f85 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -102,9 +102,7 @@ int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) { memset(addr, 0, sizeof(*addr)); addr->sin_family = AF_INET; addr->sin_port = htons(port); - /* TODO(bnoordhuis) Don't use inet_addr(), no good way to detect errors. */ - addr->sin_addr.s_addr = inet_addr(ip); - return 0; + return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr)); } @@ -140,10 +138,7 @@ int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) { } #endif - /* TODO(bnoordhuis) Return an error when the address is bad. */ - uv_inet_pton(AF_INET6, ip, &addr->sin6_addr); - - return 0; + return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr); } @@ -404,6 +399,9 @@ int uv__getaddrinfo_translate_error(int sys_err) { #if defined(EAI_BADFLAGS) case EAI_BADFLAGS: return UV_EAI_BADFLAGS; #endif +#if defined(EAI_BADHINTS) + case EAI_BADHINTS: return UV_EAI_BADHINTS; +#endif #if defined(EAI_CANCELED) case EAI_CANCELED: return UV_EAI_CANCELED; #endif @@ -424,6 +422,12 @@ int uv__getaddrinfo_translate_error(int sys_err) { case EAI_NONAME: return UV_EAI_NONAME; # endif #endif +#if defined(EAI_OVERFLOW) + case EAI_OVERFLOW: return UV_EAI_OVERFLOW; +#endif +#if defined(EAI_PROTOCOL) + case EAI_PROTOCOL: return UV_EAI_PROTOCOL; +#endif #if defined(EAI_SERVICE) case EAI_SERVICE: return UV_EAI_SERVICE; #endif diff --git a/deps/uv/src/version.c b/deps/uv/src/version.c index 2170dee369..c9e4200a74 100644 --- a/deps/uv/src/version.c +++ b/deps/uv/src/version.c @@ -31,8 +31,8 @@ #define UV_VERSION_MAJOR 0 #define UV_VERSION_MINOR 11 -#define UV_VERSION_PATCH 15 -#define UV_VERSION_IS_RELEASE 1 +#define UV_VERSION_PATCH 17 +#define UV_VERSION_IS_RELEASE 0 #define UV_VERSION ((UV_VERSION_MAJOR << 16) | \ diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index 4a9eca26bf..2eab49f2dc 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -273,6 +273,9 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { poll = &uv_poll; r = uv__loop_alive(loop); + if (!r) + uv_update_time(loop); + while (r != 0 && loop->stop_flag == 0) { uv_update_time(loop); uv_process_timers(loop); diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c index 2a09bf48ed..6132b79c82 100644 --- a/deps/uv/src/win/fs-event.c +++ b/deps/uv/src/win/fs-event.c @@ -382,7 +382,8 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } - _snwprintf(filenamew, size, L"%s\\%s", handle->dirw, + _snwprintf(filenamew, size, L"%s\\%.*s", handle->dirw, + file_info->FileNameLength / sizeof(WCHAR), file_info->FileName); filenamew[size - 1] = L'\0'; diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c index a5bb743770..813e522f75 100644 --- a/deps/uv/src/win/process.c +++ b/deps/uv/src/win/process.c @@ -832,26 +832,26 @@ int uv_spawn(uv_loop_t* loop, err = uv_utf8_to_utf16_alloc(options->file, &application); if (err) - goto immediate_failure; + goto done; err = make_program_args( options->args, options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS, &arguments); if (err) - goto immediate_failure; + goto done; if (options->env) { err = make_program_env(options->env, &env); if (err) - goto immediate_failure; + goto done; } if (options->cwd) { /* Explicit cwd */ err = uv_utf8_to_utf16_alloc(options->cwd, &cwd); if (err) - goto immediate_failure; + goto done; } else { /* Inherit cwd */ @@ -860,19 +860,19 @@ int uv_spawn(uv_loop_t* loop, cwd_len = GetCurrentDirectoryW(0, NULL); if (!cwd_len) { err = GetLastError(); - goto immediate_failure; + goto done; } cwd = (WCHAR*) malloc(cwd_len * sizeof(WCHAR)); if (cwd == NULL) { err = ERROR_OUTOFMEMORY; - goto immediate_failure; + goto done; } r = GetCurrentDirectoryW(cwd_len, cwd); if (r == 0 || r >= cwd_len) { err = GetLastError(); - goto immediate_failure; + goto done; } } @@ -883,27 +883,25 @@ int uv_spawn(uv_loop_t* loop, path_len = GetEnvironmentVariableW(L"PATH", NULL, 0); if (path_len == 0) { err = GetLastError(); - goto immediate_failure; + goto done; } path = (WCHAR*) malloc(path_len * sizeof(WCHAR)); if (path == NULL) { err = ERROR_OUTOFMEMORY; - goto immediate_failure; + goto done; } r = GetEnvironmentVariableW(L"PATH", path, path_len); if (r == 0 || r >= path_len) { err = GetLastError(); - goto immediate_failure; + goto done; } } err = uv__stdio_create(loop, options, &process->child_stdio_buffer); if (err) - goto immediate_failure; - - /* Beyond this point, failure is reported asynchronously. */ + goto done; application_path = search_path(application, cwd, @@ -911,7 +909,7 @@ int uv_spawn(uv_loop_t* loop, if (application_path == NULL) { /* Not found. */ err = ERROR_FILE_NOT_FOUND; - goto success_or_async_failure; + goto done; } startup.cb = sizeof(startup); @@ -950,7 +948,7 @@ int uv_spawn(uv_loop_t* loop, process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP; } - if (CreateProcessW(application_path, + if (!CreateProcessW(application_path, arguments, NULL, NULL, @@ -960,60 +958,67 @@ int uv_spawn(uv_loop_t* loop, cwd, &startup, &info)) { - /* Spawn succeeded */ - process->process_handle = info.hProcess; - process->pid = info.dwProcessId; - - /* If the process isn't spawned as detached, assign to the global job */ - /* object so windows will kill it when the parent process dies. */ - if (!(options->flags & UV_PROCESS_DETACHED)) { - uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle); - - if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) { - /* AssignProcessToJobObject might fail if this process is under job - * control and the job doesn't have the - * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version - * that doesn't support nested jobs. - * - * When that happens we just swallow the error and continue without - * establishing a kill-child-on-parent-exit relationship, otherwise - * there would be no way for libuv applications run under job control - * to spawn processes at all. - */ - DWORD err = GetLastError(); - if (err != ERROR_ACCESS_DENIED) - uv_fatal_error(err, "AssignProcessToJobObject"); - } - } + /* CreateProcessW failed. */ + err = GetLastError(); + goto done; + } - /* Set IPC pid to all IPC pipes. */ - for (i = 0; i < options->stdio_count; i++) { - const uv_stdio_container_t* fdopt = &options->stdio[i]; - 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; - } + /* Spawn succeeded */ + /* Beyond this point, failure is reported asynchronously. */ + + process->process_handle = info.hProcess; + process->pid = info.dwProcessId; + + /* If the process isn't spawned as detached, assign to the global job */ + /* object so windows will kill it when the parent process dies. */ + if (!(options->flags & UV_PROCESS_DETACHED)) { + uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle); + + if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) { + /* AssignProcessToJobObject might fail if this process is under job + * control and the job doesn't have the + * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version + * that doesn't support nested jobs. + * + * When that happens we just swallow the error and continue without + * establishing a kill-child-on-parent-exit relationship, otherwise + * there would be no way for libuv applications run under job control + * to spawn processes at all. + */ + DWORD err = GetLastError(); + if (err != ERROR_ACCESS_DENIED) + uv_fatal_error(err, "AssignProcessToJobObject"); } + } - /* Setup notifications for when the child process exits. */ - result = RegisterWaitForSingleObject(&process->wait_handle, - process->process_handle, exit_wait_callback, (void*)process, INFINITE, - WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); - if (!result) { - uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); + /* Set IPC pid to all IPC pipes. */ + for (i = 0; i < options->stdio_count; i++) { + const uv_stdio_container_t* fdopt = &options->stdio[i]; + 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; } + } - CloseHandle(info.hThread); - - } else { - /* CreateProcessW failed. */ - err = GetLastError(); + /* Setup notifications for when the child process exits. */ + result = RegisterWaitForSingleObject(&process->wait_handle, + process->process_handle, exit_wait_callback, (void*)process, INFINITE, + WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); + if (!result) { + uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); } - /* We get here if we successfully created a process, or when we */ - /* encountered failure that we want to report asynchronously. */ - success_or_async_failure: + CloseHandle(info.hThread); + + assert(!err); + + /* Make the handle active. It will remain active until the exit callback */ + /* iis made or the handle is closed, whichever happens first. */ + uv__handle_start(process); + + /* Cleanup, whether we succeeded or failed. */ + done: free(application); free(application_path); free(arguments); @@ -1027,27 +1032,6 @@ int uv_spawn(uv_loop_t* loop, process->child_stdio_buffer = NULL; } - /* Make the handle active, but only if an error didn't happen. It will */ - /* remain active until the exit callback is made or the handle is closed, */ - /* whichever happens first. */ - if (err == 0) { - uv__handle_start(process); - } - - return err; - - /* This code path is taken when we run into an error that we want to */ - /* report immediately. */ - immediate_failure: - free(application); - free(application_path); - free(arguments); - free(cwd); - free(env); - free(path); - - assert(process->child_stdio_buffer == NULL); - return uv_translate_sys_error(err); } diff --git a/deps/uv/src/win/stream.c b/deps/uv/src/win/stream.c index 5c792f2557..da62883d23 100644 --- a/deps/uv/src/win/stream.c +++ b/deps/uv/src/win/stream.c @@ -202,6 +202,12 @@ int uv_write2(uv_write_t* req, } +int uv_try_write(uv_stream_t* handle, const char* buf, size_t length) { + /* NOTE: Won't work with overlapped writes */ + return UV_ENOSYS; +} + + int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { uv_loop_t* loop = handle->loop; diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index a8183438fa..266b881640 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -59,20 +59,24 @@ static char *process_title; static CRITICAL_SECTION process_title_lock; -/* The tick frequency of the high-resolution clock. */ -static uint64_t hrtime_frequency_ = 0; +/* Frequency (ticks per nanosecond) of the high-resolution clock. */ +static double hrtime_frequency_ = 0; /* * One-time intialization code for functionality defined in util.c. */ void uv__util_init() { + LARGE_INTEGER perf_frequency; + /* Initialize process title access mutex. */ InitializeCriticalSection(&process_title_lock); /* Retrieve high-resolution timer frequency. */ - if (!QueryPerformanceFrequency((LARGE_INTEGER*) &hrtime_frequency_)) - hrtime_frequency_ = 0; + if (QueryPerformanceFrequency(&perf_frequency)) + hrtime_frequency_ = (double) perf_frequency.QuadPart / (double) NANOSEC; + else + hrtime_frequency_= 0; } @@ -447,7 +451,7 @@ uint64_t uv_hrtime(void) { uv__once_init(); /* If the performance frequency is zero, there's no support. */ - if (!hrtime_frequency_) { + if (hrtime_frequency_ == 0) { /* uv__set_sys_error(loop, ERROR_NOT_SUPPORTED); */ return 0; } @@ -457,12 +461,11 @@ uint64_t uv_hrtime(void) { return 0; } - /* Because we have no guarantee about the order of magnitude of the */ - /* performance counter frequency, and there may not be much headroom to */ - /* multiply by NANOSEC without overflowing, we use 128-bit math instead. */ - return ((uint64_t) counter.LowPart * NANOSEC / hrtime_frequency_) + - (((uint64_t) counter.HighPart * NANOSEC / hrtime_frequency_) - << 32); + /* Because we have no guarantee about the order of magnitude of the + * performance counter frequency, integer math could cause this computation + * to overflow. Therefore we resort to floating point math. + */ + return (uint64_t) ((double) counter.QuadPart / hrtime_frequency_); } diff --git a/deps/uv/test/test-emfile.c b/deps/uv/test/test-emfile.c new file mode 100644 index 0000000000..98b7da5b4d --- /dev/null +++ b/deps/uv/test/test-emfile.c @@ -0,0 +1,111 @@ +/* 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. + */ + +#if !defined(_WIN32) + +#include "uv.h" +#include "task.h" + +#include +#include +#include +#include + +static void connection_cb(uv_stream_t* server_handle, int status); +static void connect_cb(uv_connect_t* req, int status); + +static const int maxfd = 31; +static unsigned connect_cb_called; +static uv_tcp_t server_handle; +static uv_tcp_t client_handle; + + +TEST_IMPL(emfile) { + struct sockaddr_in addr; + struct rlimit limits; + uv_connect_t connect_req; + uv_loop_t* loop; + int first_fd; + + loop = uv_default_loop(); + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + ASSERT(0 == uv_tcp_init(loop, &server_handle)); + ASSERT(0 == uv_tcp_init(loop, &client_handle)); + ASSERT(0 == uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr)); + ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 8, connection_cb)); + + /* Lower the file descriptor limit and use up all fds save one. */ + limits.rlim_cur = limits.rlim_max = maxfd + 1; + if (setrlimit(RLIMIT_NOFILE, &limits)) { + perror("setrlimit(RLIMIT_NOFILE)"); + ASSERT(0); + } + + /* Remember the first one so we can clean up afterwards. */ + do + first_fd = dup(0); + while (first_fd == -1 && errno == EINTR); + ASSERT(first_fd > 0); + + while (dup(0) != -1 || errno == EINTR); + ASSERT(errno == EMFILE); + close(maxfd); + + /* Now connect and use up the last available file descriptor. The EMFILE + * handling logic in src/unix/stream.c should ensure that connect_cb() runs + * whereas connection_cb() should *not* run. + */ + ASSERT(0 == uv_tcp_connect(&connect_req, + &client_handle, + (const struct sockaddr*) &addr, + connect_cb)); + ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); + ASSERT(1 == connect_cb_called); + + /* Close the dups again. Ignore errors in the unlikely event that the + * file descriptors were not contiguous. + */ + while (first_fd < maxfd) { + close(first_fd); + first_fd += 1; + } + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +static void connection_cb(uv_stream_t* server_handle, int status) { + ASSERT(0 && "connection_cb should not be called."); +} + + +static void connect_cb(uv_connect_t* req, int status) { + /* |status| should equal 0 because the connection should have been accepted, + * it's just that the server immediately closes it again. + */ + ASSERT(0 == status); + connect_cb_called += 1; + uv_close((uv_handle_t*) &server_handle, NULL); + uv_close((uv_handle_t*) &client_handle, NULL); +} + +#endif /* !defined(_WIN32) */ diff --git a/deps/uv/test/test-ip4-addr.c b/deps/uv/test/test-ip4-addr.c new file mode 100644 index 0000000000..fc61f508bd --- /dev/null +++ b/deps/uv/test/test-ip4-addr.c @@ -0,0 +1,46 @@ +/* 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 + + +TEST_IMPL(ip4_addr) { + + struct sockaddr_in addr; + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + ASSERT(0 == uv_ip4_addr("255.255.255.255", TEST_PORT, &addr)); + ASSERT(UV_EINVAL == uv_ip4_addr("255.255.255*000", TEST_PORT, &addr)); + ASSERT(UV_EINVAL == uv_ip4_addr("255.255.255.256", TEST_PORT, &addr)); + ASSERT(UV_EINVAL == uv_ip4_addr("2555.0.0.0", TEST_PORT, &addr)); + ASSERT(UV_EINVAL == uv_ip4_addr("255", TEST_PORT, &addr)); + + // for broken address family + ASSERT(UV_EAFNOSUPPORT == uv_inet_pton(42, "127.0.0.1", + &addr.sin_addr.s_addr)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index b3f2e0afac..f744a20564 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -25,6 +25,7 @@ TEST_DECLARE (close_order) TEST_DECLARE (run_once) TEST_DECLARE (run_nowait) TEST_DECLARE (loop_stop) +TEST_DECLARE (loop_update_time) TEST_DECLARE (barrier_1) TEST_DECLARE (barrier_2) TEST_DECLARE (barrier_3) @@ -51,6 +52,7 @@ TEST_DECLARE (pipe_ping_pong) TEST_DECLARE (delayed_accept) TEST_DECLARE (multiple_listen) TEST_DECLARE (tcp_writealot) +TEST_DECLARE (tcp_try_write) TEST_DECLARE (tcp_open) TEST_DECLARE (tcp_connect_error_after_write) TEST_DECLARE (tcp_shutdown_after_write) @@ -216,6 +218,7 @@ TEST_DECLARE (dlerror) TEST_DECLARE (poll_duplex) TEST_DECLARE (poll_unidirectional) TEST_DECLARE (poll_close) +TEST_DECLARE (ip4_addr) TEST_DECLARE (ip6_addr_link_local) #ifdef _WIN32 TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) @@ -225,6 +228,7 @@ TEST_DECLARE (listen_with_simultaneous_accepts) TEST_DECLARE (listen_no_simultaneous_accepts) TEST_DECLARE (fs_stat_root) #else +TEST_DECLARE (emfile) TEST_DECLARE (close_fd) TEST_DECLARE (spawn_setuid_setgid) TEST_DECLARE (we_get_signal) @@ -250,6 +254,7 @@ TASK_LIST_START TEST_ENTRY (run_once) TEST_ENTRY (run_nowait) TEST_ENTRY (loop_stop) + TEST_ENTRY (loop_update_time) TEST_ENTRY (barrier_1) TEST_ENTRY (barrier_2) TEST_ENTRY (barrier_3) @@ -290,6 +295,8 @@ TASK_LIST_START TEST_ENTRY (tcp_writealot) TEST_HELPER (tcp_writealot, tcp4_echo_server) + TEST_ENTRY (tcp_try_write) + TEST_ENTRY (tcp_open) TEST_HELPER (tcp_open, tcp4_echo_server) @@ -457,6 +464,7 @@ TASK_LIST_START TEST_ENTRY (listen_no_simultaneous_accepts) TEST_ENTRY (fs_stat_root) #else + TEST_ENTRY (emfile) TEST_ENTRY (close_fd) TEST_ENTRY (spawn_setuid_setgid) TEST_ENTRY (we_get_signal) @@ -513,6 +521,7 @@ TASK_LIST_START TEST_ENTRY (thread_rwlock) TEST_ENTRY (thread_create) TEST_ENTRY (dlerror) + TEST_ENTRY (ip4_addr) TEST_ENTRY (ip6_addr_link_local) #if 0 /* These are for testing the test runner. */ diff --git a/deps/uv/test/test-loop-time.c b/deps/uv/test/test-loop-time.c new file mode 100644 index 0000000000..49dc79b2c3 --- /dev/null +++ b/deps/uv/test/test-loop-time.c @@ -0,0 +1,34 @@ +/* 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" + + +TEST_IMPL(loop_update_time) { + uint64_t start; + + start = uv_now(uv_default_loop()); + while (uv_now(uv_default_loop()) - start < 1000) + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_NOWAIT)); + + return 0; +} diff --git a/deps/uv/test/test-tcp-try-write.c b/deps/uv/test/test-tcp-try-write.c new file mode 100644 index 0000000000..3fd616607b --- /dev/null +++ b/deps/uv/test/test-tcp-try-write.c @@ -0,0 +1,143 @@ +/* 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 +#include + +#define MAX_BYTES 1024 * 1024 + +#ifdef _WIN32 + +TEST_IMPL(tcp_try_write) { + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#else /* !_WIN32 */ + +static uv_tcp_t server; +static uv_tcp_t client; +static uv_tcp_t incoming; +static int connect_cb_called; +static int close_cb_called; +static int connection_cb_called; +static int bytes_read; +static int bytes_written; + + +static void close_cb(uv_handle_t* handle) { + close_cb_called++; +} + + +static void connect_cb(uv_connect_t* req, int status) { + static char zeroes[1024]; + int r; + uv_buf_t buf; + ASSERT(status == 0); + connect_cb_called++; + + do { + r = uv_try_write((uv_stream_t*) &client, zeroes, sizeof(zeroes)); + ASSERT(r >= 0); + bytes_written += r; + + /* Partial write */ + if (r != (int) sizeof(zeroes)) + break; + } while (1); + uv_close((uv_handle_t*) &client, close_cb); +} + + +static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { + static char base[1024]; + + buf->base = base; + buf->len = sizeof(base); +} + + +static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { + if (nread < 0) { + uv_close((uv_handle_t*) tcp, close_cb); + uv_close((uv_handle_t*) &server, close_cb); + return; + } + + bytes_read += nread; +} + + +static void connection_cb(uv_stream_t* tcp, int status) { + ASSERT(status == 0); + + ASSERT(0 == uv_tcp_init(tcp->loop, &incoming)); + ASSERT(0 == uv_accept(tcp, (uv_stream_t*) &incoming)); + + connection_cb_called++; + ASSERT(0 == uv_read_start((uv_stream_t*) &incoming, alloc_cb, read_cb)); +} + + +static void start_server(void) { + struct sockaddr_in addr; + + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + + ASSERT(0 == uv_tcp_init(uv_default_loop(), &server)); + ASSERT(0 == uv_tcp_bind(&server, (struct sockaddr*) &addr)); + ASSERT(0 == uv_listen((uv_stream_t*) &server, 128, connection_cb)); +} + + +TEST_IMPL(tcp_try_write) { + uv_connect_t connect_req; + struct sockaddr_in addr; + + start_server(); + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + + ASSERT(0 == uv_tcp_init(uv_default_loop(), &client)); + ASSERT(0 == uv_tcp_connect(&connect_req, + &client, + (struct sockaddr*) &addr, + connect_cb)); + + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + ASSERT(connect_cb_called == 1); + ASSERT(close_cb_called == 3); + ASSERT(connection_cb_called == 1); + ASSERT(bytes_read == bytes_written); + ASSERT(bytes_written > 0); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#endif /* !_WIN32 */ diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 25190b6c82..962efacf30 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -309,6 +309,7 @@ 'test/test-delayed-accept.c', 'test/test-error.c', 'test/test-embed.c', + 'test/test-emfile.c', 'test/test-fail-always.c', 'test/test-fs.c', 'test/test-fs-event.c', @@ -323,6 +324,7 @@ 'test/test-list.h', 'test/test-loop-handles.c', 'test/test-loop-stop.c', + 'test/test-loop-time.c', 'test/test-walk-handles.c', 'test/test-watcher-cross-stop.c', 'test/test-multiple-listen.c', @@ -360,6 +362,7 @@ 'test/test-tcp-open.c', 'test/test-tcp-write-to-half-open-connection.c', 'test/test-tcp-writealot.c', + 'test/test-tcp-try-write.c', 'test/test-tcp-unexpected-read.c', 'test/test-tcp-read-stop.c', 'test/test-threadpool.c', @@ -380,6 +383,7 @@ 'test/test-udp-multicast-join.c', 'test/test-dlerror.c', 'test/test-udp-multicast-ttl.c', + 'test/test-ip4-addr.c', 'test/test-ip6-addr.c', ], 'conditions': [ -- cgit v1.2.3