diff -Nru libuv1-1.8.0/android-configure libuv1-1.9.1/android-configure --- libuv1-1.8.0/android-configure 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/android-configure 2016-05-16 21:22:19.000000000 +0000 @@ -3,7 +3,7 @@ export TOOLCHAIN=$PWD/android-toolchain mkdir -p $TOOLCHAIN $1/build/tools/make-standalone-toolchain.sh \ - --toolchain=arm-linux-androideabi-4.8 \ + --toolchain=arm-linux-androideabi-4.9 \ --arch=arm \ --install-dir=$TOOLCHAIN \ --platform=android-21 @@ -14,7 +14,7 @@ export LINK=arm-linux-androideabi-g++ export PLATFORM=android -if [ $2 -a $2 == 'gyp' ] +if [[ $2 == 'gyp' ]] then ./gyp_uv.py -Dtarget_arch=arm -DOS=android -f make-android fi diff -Nru libuv1-1.8.0/appveyor.yml libuv1-1.9.1/appveyor.yml --- libuv1-1.8.0/appveyor.yml 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/appveyor.yml 2016-05-16 21:22:19.000000000 +0000 @@ -1,4 +1,4 @@ -version: v1.8.0.build{build} +version: v1.9.1.build{build} install: - cinst -y nsis diff -Nru libuv1-1.8.0/AUTHORS libuv1-1.9.1/AUTHORS --- libuv1-1.8.0/AUTHORS 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/AUTHORS 2016-05-16 21:22:19.000000000 +0000 @@ -240,3 +240,20 @@ Joran Dirk Greef Andrey Mazo sztomi +Martin Bark +Dave +Alexis Murzeau +Didiet +Nan Xiang <514580344@qq.com> +Samuel Lorétan +Nándor István Krácser +Katsutoshi Horie +Lukasz Jagiello +Robert Chiras +Kári Tristan Helgason +Krishnaraj Bhat +Enno Boland +Michael Fero +Robert Jefe Lindstaedt +Myles Borins +Tony Theodore diff -Nru libuv1-1.8.0/autogen.sh libuv1-1.9.1/autogen.sh --- libuv1-1.8.0/autogen.sh 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/autogen.sh 2016-05-16 21:22:19.000000000 +0000 @@ -40,7 +40,7 @@ > m4/libuv-extra-automake-flags.m4 set -ex -"$LIBTOOLIZE" +"$LIBTOOLIZE" --copy "$ACLOCAL" -I m4 "$AUTOCONF" "$AUTOMAKE" --add-missing --copy diff -Nru libuv1-1.8.0/ChangeLog libuv1-1.9.1/ChangeLog --- libuv1-1.8.0/ChangeLog 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/ChangeLog 2016-05-16 21:22:19.000000000 +0000 @@ -1,4 +1,232 @@ -2015.12.15, Version 1.8.0 (Stable) +2016.05.17, Version 1.9.1 (Stable) + +Changes since version 1.9.0: + +* test: handle root home directories (cjihrig) + +* unix: implement uv__fs_futime for AIX 7.1 (Imran Iqbal) + +* test: skip early bind tests if no IPv6 is supported (Saúl Ibarra Corretgé) + +* win: fix var declaration to be C89 compliant (Michael Fero) + +* unix: use POLL{IN,OUT,etc} constants directly (Ben Noordhuis) + +* doc: add ability to live reload and regenerate HTML (Saúl Ibarra Corretgé) + +* Revert "win,build: remove unused build defines" (cjihrig) + +* linux: fix fd leaks in uv_cpu_info() error paths (Ben Noordhuis) + +* linux: don't abort on malformed /proc/stat (Ben Noordhuis) + +* linux: fix long lines in linux-core.c (Ben Noordhuis) + +* test: fix fs_event_watch_file_current_dir for AIX (Imran Iqbal) + +* unix,fs: code cleanup of uv_fs_event_start for AIX (Imran Iqbal) + +* unix: delay signal handling until after normal i/o (Ben Noordhuis) + +* android: pthread_sigmask() does not set errno (Oguz Bastemur) + +* win: work around sharepoint scandir bug (Ben Noordhuis) + +* unix: guard against clobbering errno in uv__free() (Ben Noordhuis) + +* unix: remove unneeded SAVE_ERRNO wrappers (Ben Noordhuis) + +* test: skip fs_event_close_in_callback on AIX (Imran Iqbal) + +* win: add maxrss, pagefaults to uv_getrusage() (Robert Jefe Lindstaedt) + +* test: set a big send buffer size for tcp_write_queue_order (Andrius Bentkus) + +* unix: error on realpath if PATH_MAX is undefined (Myles Borins) + +* unix: fix bug in barrier fallback implementation (Kári Tristan Helgason) + +* build: bump android ndk version (Kári Tristan Helgason) + +* build: always compile with -fvisibility=hidden (Ben Noordhuis) + +* test: fix -Wformat warnings in platform test (Ben Noordhuis) + +* win: clarify fsevents handling code (Saúl Ibarra Corretgé) + +* test: fix POLLHDRUP related failures for AIX (Imran Iqbal) + +* build, mingw: set LIBS in configure.ac (Tony Theodore) + +* win: improve uv__convert_utf16_to_utf8 (Saúl Ibarra Corretgé) + +* win: simplified UTF16 -> UTF8 conversions (Saúl Ibarra Corretgé) + +* win: remove unneeded condition (Saúl Ibarra Corretgé) + +* darwin: work around condition variable kernel bug (Ben Noordhuis) + +* darwin: make thread stack multiple of page size (Ben Noordhuis) + +* build,win: rename platform to msbuild_platform (João Reis) + +* gitignore: ignore VS temporary database files (João Reis) + +* test: skip emfile on AIX (Imran Iqbal) + +* unix: use system allocator for scandir() (cjihrig) + +* common: release uv_fs_scandir() array (cjihrig) + +* win: call uv__fs_scandir_cleanup() (cjihrig) + +* win,tty: fix read stop in line mode (João Reis) + +* win,tty: don't duplicate handle for line reads (João Reis) + +* win,tty: restore cursor after canceling line read (Alexis Campailla) + + +2016.04.08, Version 1.9.0 (Stable), 229b3a4cc150aebd6561e6bd43076eafa7a03756 + +Changes since version 1.8.0: + +* win: wait for full timeout duration (João Reis) + +* unix: fix support for uClibc-ng (Martin Bark) + +* doc: indicate where new test files need to be added (Dave) + +* test,unix: fix logic error in test runner (Ben Noordhuis) + +* fs: don't nullify req->bufs on EINTR (Dave) + +* osx: set the default thread stack size to RLIMIT_STACK (Saúl Ibarra Corretgé) + +* build: invoke libtoolize with --copy (Ben Noordhuis) + +* test: fixup eintr_handling (Saúl Ibarra Corretgé) + +* osx: avoid compilation warning with Clang (Saúl Ibarra Corretgé) + +* test,win: fix compilation with shared lib (Alexis Murzeau) + +* test: fix race condition in pipe-close-stdout (Imran Iqbal) + +* unix,win: add uv_os_tmpdir() (cjihrig) + +* ios: fix undefined PTHREAD_STACK_MIN (Didiet) + +* test: fix threadpool_multiple_event_loops for AIX (Imran Iqbal) + +* unix: report errors for unpollable fds (Ben Noordhuis) + +* win: fix watching root files (Nicholas Vavilov) + +* build,win: print the Visual Studio version in use (Saúl Ibarra Corretgé) + +* build,win: remove unneeded condition from GYP file (Saúl Ibarra Corretgé) + +* test,win: fix compilation warning (Saúl Ibarra Corretgé) + +* test: use uv_loop_close and assert its result (Nan Xiang) + +* build: map 'AMD64' host arch to 'x64' (Ben Noordhuis) + +* osx: protected use of potentially undefined macro (Samuel Lorétan) + +* linux: fix compilation with musl (Saúl Ibarra Corretgé) + +* doc: describe how to make release builds on Unix (Saúl Ibarra Corretgé) + +* doc: add missing link in README (Saúl Ibarra Corretgé) + +* build: python 2.x/3.x consistent print usage (Rasmus Christian Pedersen) + +* test: assume no IPv6 if interfaces cannot be listed (Nan Xiang) + +* darwin: replace F_FULLFSYNC with fdatasync syscall (Saúl Ibarra Corretgé) + +* doc: add missing write callback to example (Nándor István Krácser) + +* build: compile with -D_THREAD_SAFE on AIX (Imran Iqbal) + +* test: fix threadpool_multiple_event_loops on PPC (Imran Iqbal) + +* test: reduce timeout in tcp_close_while_connecting (Imran Iqbal) + +* unix, win: consistently null-terminate buffers (Saúl Ibarra Corretgé) + +* unix, win: count null byte on UV_ENOBUFS (Saúl Ibarra Corretgé) + +* test: fix deadlocks in uv_cond_wait (Katsutoshi Horie) + +* linux: fix cpu count (Lukasz Jagiello) + +* unix: fix uv__handle_type for AIX (Imran Iqbal) + +* linux: call fclose(), fix fdopen() memory leak (Ben Noordhuis) + +* win: remove unneeded condition (Saúl Ibarra Corretgé) + +* unix: fix compile error in Android using bionic (Robert Chiras) + +* linux: add braces to multi-statement if (Kári Tristan Helgason) + +* doc: add @cjihrig as a maintainer (Saúl Ibarra Corretgé) + +* unix: add fork-safe open file function (Kári Tristan Helgason) + +* linux: replace calls to fopen with uv__open_file (Kári Tristan Helgason) + +* linux: remove redundant call to rewind() (Krishnaraj Bhat) + +* win: remove duplicated code when processing fsevents (Saúl Ibarra Corretgé) + +* test: fix poll_bad_fdtype for AIX (Imran Iqbal) + +* linux: fix error checking in uv__open_file (Saúl Ibarra Corretgé) + +* poll: add UV_DISCONNECT event (Santiago Gimeno) + +* fs: realpath: fix string size before converting (Yuval Brik) + +* win: use native APIs for UTF conversions (cjihrig) + +* doc: clarify uv_loop_close() (Ben Noordhuis) + +* unix: retry ioctl(TIOCGWINSZ) on EINTR (Ben Noordhuis) + +* win,build: remove unused build defines (Saúl Ibarra Corretgé) + +* win: fix buffer overflow in fs events (Joran Dirk Greef) + +* win: fix uv_relative_path and remove dead branch (Joran Dirk Greef) + +* unix: use open(2) with O_CLOEXEC on OS X (Kári Tristan Helgason) + +* test: add missing copyright header (cjihrig) + +* aix: fix 'POLLRDHUP undeclared' build error (Ben Noordhuis) + +* unix,win: add uv_get_passwd() (cjihrig) + +* process: fix uv_spawn edge-case (Santiago Gimeno) + +* test: use %ld for printing uid/gid (Ben Noordhuis) + +* aix: fix ahafs implementation (Imran Iqbal) + +* aix: do not store absolute path to ahafs (Imran Iqbal) + +* process: close process pipes safely (Santiago Gimeno) + +* unix: open ttyname instead of /dev/tty (Enno Boland) + +* unix: remove outdated comment (Kári Tristan Helgason) + + +2015.12.15, Version 1.8.0 (Stable), 5467299450ecf61635657557b6e01aaaf6c3fdf4 Changes since version 1.7.5: diff -Nru libuv1-1.8.0/checksparse.sh libuv1-1.9.1/checksparse.sh --- libuv1-1.8.0/checksparse.sh 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/checksparse.sh 2016-05-16 21:22:19.000000000 +0000 @@ -101,6 +101,7 @@ test/test-get-currentexe.c test/test-get-loadavg.c test/test-get-memory.c +test/test-get-passwd.c test/test-getaddrinfo.c test/test-getsockname.c test/test-homedir.c @@ -155,6 +156,7 @@ test/test-threadpool.c test/test-timer-again.c test/test-timer.c +test/test-tmpdir.c test/test-tty.c test/test-udp-dgram-too-big.c test/test-udp-ipv6.c diff -Nru libuv1-1.8.0/common.gypi libuv1-1.9.1/common.gypi --- libuv1-1.8.0/common.gypi 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/common.gypi 2016-05-16 21:22:19.000000000 +0000 @@ -1,6 +1,5 @@ { 'variables': { - 'visibility%': 'hidden', # V8's visibility setting 'target_arch%': 'ia32', # set v8's target architecture 'host_arch%': 'ia32', # set v8's host architecture 'uv_library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds @@ -156,9 +155,6 @@ 'cflags': [ '-pthread' ], 'ldflags': [ '-pthread' ], }], - [ 'visibility=="hidden"', { - 'cflags': [ '-fvisibility=hidden' ], - }], ], }], ['OS=="mac"', { @@ -170,9 +166,6 @@ 'GCC_ENABLE_CPP_EXCEPTIONS': 'NO', # -fno-exceptions 'GCC_ENABLE_CPP_RTTI': 'NO', # -fno-rtti 'GCC_ENABLE_PASCAL_STRINGS': 'NO', # No -mpascal-strings - # GCC_INLINES_ARE_PRIVATE_EXTERN maps to -fvisibility-inlines-hidden - 'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES', - 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden 'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics 'PREBINDING': 'NO', # No -Wl,-prebind 'USE_HEADERMAP': 'NO', diff -Nru libuv1-1.8.0/configure.ac libuv1-1.9.1/configure.ac --- libuv1-1.8.0/configure.ac 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/configure.ac 2016-05-16 21:22:19.000000000 +0000 @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.8.0], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.9.1], [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]) @@ -58,6 +58,9 @@ 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])]) +AS_CASE([$host_os],[mingw*], [ + LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv -luser32" +]) AC_CHECK_HEADERS([sys/ahafs_evProds.h]) AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes) AM_CONDITIONAL([HAVE_PKG_CONFIG], [test "x$PKG_CONFIG" != "x"]) diff -Nru libuv1-1.8.0/CONTRIBUTING.md libuv1-1.9.1/CONTRIBUTING.md --- libuv1-1.8.0/CONTRIBUTING.md 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/CONTRIBUTING.md 2016-05-16 21:22:19.000000000 +0000 @@ -23,8 +23,7 @@ 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][]. +to the [libuv mailing list], or contact one of [project maintainers][] 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 @@ -138,7 +137,10 @@ ### 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`. +`test/` directory. Each new test needs to be registered in `test/test-list.h`. If you add a new test file, it needs to be registered in two places: +- `Makefile.am`: add the file's name to the `test_run_tests_SOURCES` list. +- `uv.gyp`: add the file's name to the `sources` list in the `run-tests` target. + Look at other tests to see how they should be structured (license boilerplate, the way entry points are declared, etc.). @@ -164,3 +166,4 @@ [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 +[project maintainers]: https://github.com/libuv/libuv/blob/master/MAINTAINERS.md diff -Nru libuv1-1.8.0/debian/changelog libuv1-1.9.1/debian/changelog --- libuv1-1.8.0/debian/changelog 2015-12-14 22:45:30.000000000 +0000 +++ libuv1-1.9.1/debian/changelog 2018-05-29 14:51:08.000000000 +0000 @@ -1,3 +1,53 @@ +libuv1 (1.9.1-3ppa1~ubuntu16.04) unstable; urgency=medium + + * Backport for Ubuntu Xenial. + + -- Joachim Bauch Tue, 29 May 2018 16:51:03 +0200 + +libuv1 (1.9.1-3ppa1~ubuntu14.04) unstable; urgency=medium + + * Backport for Ubuntu Trusty + + -- Joachim Bauch Mon, 20 Nov 2017 15:25:55 +0100 + +libuv1 (1.9.1-3) unstable; urgency=medium + + * Team upload. + * Make libuv1-dev libkvm-dev on kfreebsd-any. (Closes: #834563) + * Bump Standards-Version to 3.9.8, no changes needed. + * Add patch from upstream to don't fail the build if /dev/pty is not present. + + -- Mattia Rizzolo Sun, 23 Oct 2016 13:36:45 +0000 + +libuv1 (1.9.1-2) unstable; urgency=medium + + * Team upload. + + [ Mattia Rizzolo ] + * Fix Vcs-Git + + [ Dominique Dumont ] + * fix patch to avoid bogus signal blockers on arm64 (Closes: #841354) + Many thanks to Tobias Leich (FROGGS) and Perl6/Moar team for + the help fixing this bug + + -- Dominique Dumont Fri, 21 Oct 2016 13:06:07 +0200 + +libuv1 (1.9.1-1) unstable; urgency=medium + + * New upstream release + + -- Luca Bruno Sun, 29 May 2016 19:29:08 +0200 + +libuv1 (1.9.0-1) unstable; urgency=medium + + * New upstream release + + New symbols introduced + * Bump Standards-Version + * Move Vcs-* headers to HTTPS endpoints + + -- Luca Bruno Thu, 07 Apr 2016 23:55:20 +0200 + libuv1 (1.8.0-1) unstable; urgency=medium * New upstream release diff -Nru libuv1-1.8.0/debian/control libuv1-1.9.1/debian/control --- libuv1-1.8.0/debian/control 2015-12-14 22:25:41.000000000 +0000 +++ libuv1-1.9.1/debian/control 2017-11-20 14:24:41.000000000 +0000 @@ -3,20 +3,22 @@ Maintainer: Debian Javascript Maintainers Uploaders: Luca Bruno Build-Depends: debhelper (>= 9), - dh-exec (>=0.3), dh-autoreconf, + dh-exec (>=0.3), libkvm-dev [kfreebsd-any], pkg-config -Standards-Version: 3.9.6 +Standards-Version: 3.9.8 Section: libs Homepage: https://github.com/libuv/libuv -Vcs-Browser: http://anonscm.debian.org/cgit/pkg-javascript/libuv1.git -Vcs-Git: git://anonscm.debian.org/pkg-javascript/libuv1.git +Vcs-Browser: https://anonscm.debian.org/git/pkg-javascript/libuv1.git +Vcs-Git: https://anonscm.debian.org/git/pkg-javascript/libuv1.git Package: libuv1-dev Section: libdevel Architecture: any -Depends: libuv1 (= ${binary:Version}), ${misc:Depends} +Depends: libkvm-dev [kfreebsd-any], + libuv1 (= ${binary:Version}), + ${misc:Depends} Multi-Arch: same Replaces: libuv-dev Conflicts: libuv-dev, libuv0.10-dev @@ -39,7 +41,7 @@ Package: libuv1 Architecture: any Pre-Depends: ${misc:Pre-Depends} -Depends: ${shlibs:Depends}, ${misc:Depends} +Depends: ${misc:Depends}, ${shlibs:Depends} Multi-Arch: same Description: asynchronous event notification library - runtime library Libuv is the asynchronous library behind Node.js. Very similar to libevent or diff -Nru libuv1-1.8.0/debian/copyright libuv1-1.9.1/debian/copyright --- libuv1-1.8.0/debian/copyright 2015-12-14 22:25:41.000000000 +0000 +++ libuv1-1.9.1/debian/copyright 2017-11-20 14:24:41.000000000 +0000 @@ -137,7 +137,7 @@ Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. - . + . THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR diff -Nru libuv1-1.8.0/debian/gbp.conf libuv1-1.9.1/debian/gbp.conf --- libuv1-1.8.0/debian/gbp.conf 2015-12-14 22:25:41.000000000 +0000 +++ libuv1-1.9.1/debian/gbp.conf 2018-05-29 14:46:36.000000000 +0000 @@ -1,6 +1,7 @@ [DEFAULT] pristine-tar = True -debian-branch = debian/sid +debian-branch = ubuntu/xenial +debian-tag = ubuntu/xenial/%(version)s [git-buildpackage] -upstream-tag = v%(version)s +upstream-tag = upstream/%(version)s diff -Nru libuv1-1.8.0/debian/libuv1.symbols libuv1-1.9.1/debian/libuv1.symbols --- libuv1-1.8.0/debian/libuv1.symbols 2015-12-14 22:35:57.000000000 +0000 +++ libuv1-1.9.1/debian/libuv1.symbols 2017-11-20 14:24:41.000000000 +0000 @@ -117,7 +117,10 @@ uv_mutex_unlock@Base 1.4.2 uv_now@Base 1.4.2 uv_once@Base 1.4.2 + uv_os_free_passwd@Base 1.9.0~ + uv_os_get_passwd@Base 1.9.0~ uv_os_homedir@Base 1.6.1 + uv_os_tmpdir@Base 1.9.0~ uv_pipe_bind@Base 1.4.2 uv_pipe_connect@Base 1.4.2 uv_pipe_getpeername@Base 1.4.2 diff -Nru libuv1-1.8.0/debian/patches/kfreebsd.patch libuv1-1.9.1/debian/patches/kfreebsd.patch --- libuv1-1.8.0/debian/patches/kfreebsd.patch 2015-12-14 22:26:30.000000000 +0000 +++ libuv1-1.9.1/debian/patches/kfreebsd.patch 2017-11-20 14:24:41.000000000 +0000 @@ -2,8 +2,10 @@ Author: Jérémy Lal Last-Update: 2015-09-19 Forwarded: not yet ---- a/configure.ac -+++ b/configure.ac +Index: libuv1/configure.ac +=================================================================== +--- libuv1.orig/configure.ac 2016-05-29 19:26:19.060785992 +0200 ++++ libuv1/configure.ac 2016-05-29 19:26:19.056785952 +0200 @@ -53,6 +53,7 @@ AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])]) AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])]) @@ -12,10 +14,12 @@ AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])]) AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])]) AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])]) ---- a/src/unix/core.c -+++ b/src/unix/core.c -@@ -55,7 +55,7 @@ - # include +Index: libuv1/src/unix/core.c +=================================================================== +--- libuv1.orig/src/unix/core.c 2016-05-29 19:26:19.060785992 +0200 ++++ libuv1/src/unix/core.c 2016-05-29 19:26:19.056785952 +0200 +@@ -58,7 +58,7 @@ + # endif #endif -#if defined(__FreeBSD__) || defined(__DragonFly__) @@ -23,7 +27,7 @@ # include # include # include -@@ -500,7 +500,7 @@ +@@ -524,7 +524,7 @@ #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ @@ -32,7 +36,7 @@ int uv__nonblock(int fd, int set) { int r; -@@ -530,7 +530,7 @@ +@@ -554,7 +554,7 @@ } #else /* !(defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ @@ -41,7 +45,7 @@ int uv__nonblock(int fd, int set) { int flags; -@@ -594,7 +594,7 @@ +@@ -618,7 +618,7 @@ } #endif /* defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ @@ -50,18 +54,11 @@ /* This function is not execve-safe, there is a race window -@@ -931,7 +931,7 @@ - int fd; - - #if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 9) || \ -- defined(__DragonFly__) -+ defined(__DragonFly__) || defined(__FreeBSD_kernel__) - static int no_cloexec; - - if (!no_cloexec) { ---- a/include/uv-unix.h -+++ b/include/uv-unix.h -@@ -54,7 +54,7 @@ +Index: libuv1/include/uv-unix.h +=================================================================== +--- libuv1.orig/include/uv-unix.h 2016-05-29 19:26:19.060785992 +0200 ++++ libuv1/include/uv-unix.h 2016-05-29 19:26:19.056785952 +0200 +@@ -51,7 +51,7 @@ #elif defined(__APPLE__) # include "uv-darwin.h" #elif defined(__DragonFly__) || \ @@ -70,9 +67,11 @@ defined(__OpenBSD__) || \ defined(__NetBSD__) # include "uv-bsd.h" ---- a/src/unix/fs.c -+++ b/src/unix/fs.c -@@ -192,6 +192,7 @@ +Index: libuv1/src/unix/fs.c +=================================================================== +--- libuv1.orig/src/unix/fs.c 2016-05-29 19:26:19.060785992 +0200 ++++ libuv1/src/unix/fs.c 2016-05-29 19:26:19.056785952 +0200 +@@ -193,6 +193,7 @@ #elif defined(__APPLE__) \ || defined(__DragonFly__) \ || defined(__FreeBSD__) \ @@ -80,8 +79,10 @@ || defined(__NetBSD__) \ || defined(__OpenBSD__) \ || defined(__sun) ---- a/test/test-fs-event.c -+++ b/test/test-fs-event.c +Index: libuv1/test/test-fs-event.c +=================================================================== +--- libuv1.orig/test/test-fs-event.c 2016-05-29 19:26:19.060785992 +0200 ++++ libuv1/test/test-fs-event.c 2016-05-29 19:26:19.056785952 +0200 @@ -29,6 +29,7 @@ # if defined(__APPLE__) || \ defined(__DragonFly__) || \ diff -Nru libuv1-1.8.0/debian/patches/mips-epoll_pwait.diff libuv1-1.9.1/debian/patches/mips-epoll_pwait.diff --- libuv1-1.8.0/debian/patches/mips-epoll_pwait.diff 2015-12-14 22:25:41.000000000 +0000 +++ libuv1-1.9.1/debian/patches/mips-epoll_pwait.diff 2017-11-20 14:24:41.000000000 +0000 @@ -1,9 +1,9 @@ -From de298f5ae62b1338cf830d5833bae2486931afaa Mon Sep 17 00:00:00 2001 +Subject: [PATCH] unix: use libc-provided epoll_pwait wrapper +Bug-Debian: https://bugs.debian.org/841354 From: Luca Bruno Date: Tue, 12 May 2015 22:04:35 +0200 -Subject: [PATCH] unix: use libc-provided epoll_pwait wrapper -Further fix for sigmask size calculation on top of 751ac48. +Signed-off-by: Luca Bruno We now use epoll_pwait() wrapper from libc, which takes care of passing proper sigset_t size to kernel. @@ -13,16 +13,20 @@ This fixes #335. -Signed-off-by: Luca Bruno +Many thanks to Tobias Leich who amended this +patch to fix #841354 + --- src/unix/linux-core.c | 15 ++++++++------- src/unix/linux-syscalls.c | 21 +++++++-------------- src/unix/linux-syscalls.h | 2 +- 3 files changed, 16 insertions(+), 22 deletions(-) ---- a/src/unix/linux-core.c -+++ b/src/unix/linux-core.c -@@ -33,6 +33,7 @@ +Index: libuv1/src/unix/linux-core.c +=================================================================== +--- libuv1.orig/src/unix/linux-core.c 2016-05-29 19:25:29.000284791 +0200 ++++ libuv1/src/unix/linux-core.c 2016-05-29 19:26:01.036605254 +0200 +@@ -38,6 +38,7 @@ #include #include #include @@ -30,31 +34,32 @@ #include #include -@@ -159,8 +160,8 @@ +@@ -186,8 +187,8 @@ QUEUE* q; uv__io_t* w; sigset_t sigset; - uint64_t sigmask; uint64_t base; + int is_sigmasked; + int have_signals; int nevents; int count; - int nfds; -@@ -208,11 +209,11 @@ +@@ -236,11 +237,11 @@ w->events = w->pevents; } - sigmask = 0; + is_sigmasked = 0; ++ sigemptyset(&sigset); if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { - sigemptyset(&sigset); +- sigemptyset(&sigset); sigaddset(&sigset, SIGPROF); - sigmask |= 1 << (SIGPROF - 1); + is_sigmasked = 1; } assert(timeout >= -1); -@@ -227,16 +228,16 @@ +@@ -255,16 +256,16 @@ if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) timeout = max_safe_timeout; @@ -74,7 +79,7 @@ if (nfds == -1 && errno == ENOSYS) no_epoll_pwait = 1; } else { -@@ -248,7 +249,7 @@ +@@ -276,7 +277,7 @@ no_epoll_wait = 1; } @@ -83,8 +88,10 @@ if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL)) abort(); ---- a/src/unix/linux-syscalls.c -+++ b/src/unix/linux-syscalls.c +Index: libuv1/src/unix/linux-syscalls.c +=================================================================== +--- libuv1.orig/src/unix/linux-syscalls.c 2016-05-29 19:25:29.000284791 +0200 ++++ libuv1/src/unix/linux-syscalls.c 2016-05-29 19:25:29.000284791 +0200 @@ -22,6 +22,7 @@ #include "linux-syscalls.h" #include @@ -121,9 +128,11 @@ #else return errno = ENOSYS, -1; #endif ---- a/src/unix/linux-syscalls.h -+++ b/src/unix/linux-syscalls.h -@@ -131,7 +131,7 @@ +Index: libuv1/src/unix/linux-syscalls.h +=================================================================== +--- libuv1.orig/src/unix/linux-syscalls.h 2016-05-29 19:25:29.000284791 +0200 ++++ libuv1/src/unix/linux-syscalls.h 2016-05-29 19:25:29.000284791 +0200 +@@ -124,7 +124,7 @@ struct uv__epoll_event* events, int nevents, int timeout, diff -Nru libuv1-1.8.0/debian/patches/series libuv1-1.9.1/debian/patches/series --- libuv1-1.8.0/debian/patches/series 2015-12-14 22:26:13.000000000 +0000 +++ libuv1-1.9.1/debian/patches/series 2017-11-20 14:24:41.000000000 +0000 @@ -2,3 +2,4 @@ sparc-skip-tcp_oob.diff #iovec_rw_fix.patch kfreebsd.patch +skip_test_if_no_pty.patch diff -Nru libuv1-1.8.0/debian/patches/skip_test_if_no_pty.patch libuv1-1.9.1/debian/patches/skip_test_if_no_pty.patch --- libuv1-1.8.0/debian/patches/skip_test_if_no_pty.patch 1970-01-01 00:00:00.000000000 +0000 +++ libuv1-1.9.1/debian/patches/skip_test_if_no_pty.patch 2017-11-20 14:24:41.000000000 +0000 @@ -0,0 +1,33 @@ +Description: test: skip tty_pty test if pty is not available + Do not let `tty_pty` test fail if no terminals are available + to `openpty()`. +Author: Luca Bruno +Reviewed-By: Colin Ihrig +Reviewed-By: Saúl Ibarra Corretgé +Forwarded: yes, accepted already: https://github.com/libuv/libuv/pull/919 +Last-Update: Sun, 19 Jun 2016 18:20:53 +0200 + +diff --git a/test/test-tty.c b/test/test-tty.c +index 55cc016..5787d1d 100644 +--- a/test/test-tty.c ++++ b/test/test-tty.c +@@ -262,14 +262,17 @@ TEST_IMPL(tty_file) { + TEST_IMPL(tty_pty) { + # if defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ + defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) +- int master_fd, slave_fd; ++ int master_fd, slave_fd, r; + struct winsize w; + uv_loop_t loop; + uv_tty_t master_tty, slave_tty; + + ASSERT(0 == uv_loop_init(&loop)); + +- ASSERT(0 == openpty(&master_fd, &slave_fd, NULL, NULL, &w)); ++ r = openpty(&master_fd, &slave_fd, NULL, NULL, &w); ++ if (r != 0) ++ RETURN_SKIP("No pty available, skipping."); ++ + ASSERT(0 == uv_tty_init(&loop, &slave_tty, slave_fd, 0)); + ASSERT(0 == uv_tty_init(&loop, &master_tty, master_fd, 0)); + /* Check if the file descriptor was reopened. If it is, diff -Nru libuv1-1.8.0/docs/Makefile libuv1-1.9.1/docs/Makefile --- libuv1-1.8.0/docs/Makefile 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/docs/Makefile 2016-05-16 21:22:19.000000000 +0000 @@ -2,11 +2,12 @@ # # You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = build -SRCDIR = src +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXAUTOBUILD = sphinx-autobuild +PAPER = +BUILDDIR = build +SRCDIR = src # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) @@ -20,11 +21,12 @@ # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRCDIR) -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext +.PHONY: help clean html livehtml dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" + @echo " livehtml to make standalone HTML files and live reload them" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @@ -55,6 +57,9 @@ @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." +livehtml: + $(SPHINXAUTOBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo diff -Nru libuv1-1.8.0/docs/src/loop.rst libuv1-1.9.1/docs/src/loop.rst --- libuv1-1.8.0/docs/src/loop.rst 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/docs/src/loop.rst 2016-05-16 21:22:19.000000000 +0000 @@ -71,9 +71,10 @@ .. c:function:: int uv_loop_close(uv_loop_t* loop) - Closes all internal loop resources. This function must only be called once - the loop has finished its execution or it will return UV_EBUSY. After this - function returns the user shall free the memory allocated for the loop. + Releases all internal loop resources. Call this function only when the loop + has finished executing and all open handles and requests have been closed, + or it will return UV_EBUSY. After this function returns, the user can free + the memory allocated for the loop. .. c:function:: uv_loop_t* uv_default_loop(void) diff -Nru libuv1-1.8.0/docs/src/misc.rst libuv1-1.9.1/docs/src/misc.rst --- libuv1-1.8.0/docs/src/misc.rst 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/docs/src/misc.rst 2016-05-16 21:22:19.000000000 +0000 @@ -122,6 +122,20 @@ } netmask; } uv_interface_address_t; +.. c:type:: uv_passwd_t + + Data type for password file information. + + :: + + typedef struct uv_passwd_s { + char* username; + long uid; + long gid; + char* shell; + char* homedir; + } uv_passwd_t; + API --- @@ -265,14 +279,50 @@ `uv_os_homedir()` first checks the `HOME` environment variable using :man:`getenv(3)`. If `HOME` is not set, :man:`getpwuid_r(3)` is called. The user's home directory is stored in `buffer`. When `uv_os_homedir()` is - called, `size` indicates the maximum size of `buffer`. On success or - `UV_ENOBUFS` failure, `size` is set to the string length of `buffer`. + called, `size` indicates the maximum size of `buffer`. On success `size` is set + to the string length of `buffer`. On `UV_ENOBUFS` failure `size` is set to the + required length for `buffer`, including the null byte. .. warning:: `uv_os_homedir()` is not thread safe. .. versionadded:: 1.6.0 +.. c:function:: int uv_os_tmpdir(char* buffer, size_t* size) + + Gets the temp directory. On Windows, `uv_os_tmpdir()` uses `GetTempPathW()`. + On all other operating systems, `uv_os_tmpdir()` uses the first environment + variable found in the ordered list `TMPDIR`, `TMP`, `TEMP`, and `TEMPDIR`. + If none of these are found, the path `"/tmp"` is used, or, on Android, + `"/data/local/tmp"` is used. The temp directory is stored in `buffer`. When + `uv_os_tmpdir()` is called, `size` indicates the maximum size of `buffer`. + On success `size` is set to the string length of `buffer` (which does not + include the terminating null). On `UV_ENOBUFS` failure `size` is set to the + required length for `buffer`, including the null byte. + + .. warning:: + `uv_os_tmpdir()` is not thread safe. + + .. versionadded:: 1.9.0 + +.. c:function:: int uv_os_get_passwd(uv_passwd_t* pwd) + + Gets a subset of the password file entry for the current effective uid (not + the real uid). The populated data includes the username, euid, gid, shell, + and home directory. On non-Windows systems, all data comes from + :man:`getpwuid_r(3)`. On Windows, uid and gid are set to -1 and have no + meaning, and shell is `NULL`. After successfully calling this function, the + memory allocated to `pwd` needs to be freed with + :c:func:`uv_os_free_passwd`. + + .. versionadded:: 1.9.0 + +.. c:function:: void uv_os_free_passwd(uv_passwd_t* pwd) + + Frees the `pwd` memory previously allocated with :c:func:`uv_os_get_passwd`. + + .. versionadded:: 1.9.0 + .. uint64_t uv_get_free_memory(void) .. c:function:: uint64_t uv_get_total_memory(void) diff -Nru libuv1-1.8.0/docs/src/poll.rst libuv1-1.9.1/docs/src/poll.rst --- libuv1-1.8.0/docs/src/poll.rst 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/docs/src/poll.rst 2016-05-16 21:22:19.000000000 +0000 @@ -4,8 +4,8 @@ :c:type:`uv_poll_t` --- Poll handle =================================== -Poll handles are used to watch file descriptors for readability and -writability, similar to the purpose of :man:`poll(2)`. +Poll handles are used to watch file descriptors for readability, +writability and disconnection 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 @@ -31,6 +31,8 @@ On windows only sockets can be polled with poll handles. On Unix any file descriptor that would be accepted by :man:`poll(2)` can be used. +.. note:: + On AIX, watching for disconnection is not supported. Data types ---------- @@ -51,7 +53,8 @@ enum uv_poll_event { UV_READABLE = 1, - UV_WRITABLE = 2 + UV_WRITABLE = 2, + UV_DISCONNECT = 4 }; @@ -82,10 +85,14 @@ .. c:function:: int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) Starts polling the file descriptor. `events` is a bitmask consisting made up - of UV_READABLE and UV_WRITABLE. As soon as an event is detected the callback - will be called with `status` set to 0, and the detected events set on the + of UV_READABLE, UV_WRITABLE and UV_DISCONNECT. As soon as an event is detected + the callback will be called with `status` set to 0, and the detected events set on the `events` field. + The UV_DISCONNECT event is optional in the sense that it may not be + reported and the user is free to ignore it, but it can help optimize the shutdown + path because an extra read or write call might be avoided. + If an error happens while polling, `status` will be < 0 and corresponds with one of the UV_E* error codes (see :ref:`errors`). The user should not close the socket while the handle is active. If the user does that @@ -96,6 +103,12 @@ Calling :c:func:`uv_poll_start` on a handle that is already active is fine. Doing so will update the events mask that is being watched for. + .. note:: + Though UV_DISCONNECT can be set, it is unsupported on AIX and as such will not be set + on the `events` field in the callback. + + .. versionchanged:: 1.9.0 Added the UV_DISCONNECT event. + .. c:function:: int uv_poll_stop(uv_poll_t* poll) Stop polling the file descriptor, the callback will no longer be called. diff -Nru libuv1-1.8.0/docs/src/stream.rst libuv1-1.9.1/docs/src/stream.rst --- libuv1-1.8.0/docs/src/stream.rst 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/docs/src/stream.rst 2016-05-16 21:22:19.000000000 +0000 @@ -148,6 +148,10 @@ :: + void cb(uv_write_t* req, int status) { + /* Logic which handles the write result */ + } + uv_buf_t a[] = { { .base = "1", .len = 1 }, { .base = "2", .len = 1 } @@ -162,8 +166,8 @@ uv_write_t req2; /* writes "1234" */ - uv_write(&req1, stream, a, 2); - uv_write(&req2, stream, b, 2); + uv_write(&req1, stream, a, 2, cb); + uv_write(&req2, stream, b, 2, cb); .. c:function:: int uv_write2(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle, uv_write_cb cb) diff -Nru libuv1-1.8.0/docs/src/tty.rst libuv1-1.9.1/docs/src/tty.rst --- libuv1-1.8.0/docs/src/tty.rst 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/docs/src/tty.rst 2016-05-16 21:22:19.000000000 +0000 @@ -58,14 +58,22 @@ `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 determine the path of the fd of the terminal + using :man:`ttyname_r(3)`, open it, 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. + + This function is not thread safe on systems that don't support + ioctl TIOCGPTN or TIOCPTYGNAME, for instance OpenBSD and Solaris. .. note:: - If opening ``/dev/tty`` fails, libuv falls back to blocking writes for + If reopening the TTY fails, libuv falls back to blocking writes for non-readable TTY streams. + .. versionchanged:: 1.9.0: the path of the TTY is determined by + :man:`ttyname_r(3)`. In earlier versions libuv opened + `/dev/tty` instead. + .. versionchanged:: 1.5.0: trying to initialize a TTY stream with a file descriptor that refers to a file returns `UV_EINVAL` on UNIX. diff -Nru libuv1-1.8.0/.gitignore libuv1-1.9.1/.gitignore --- libuv1-1.8.0/.gitignore 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/.gitignore 2016-05-16 21:22:19.000000000 +0000 @@ -6,6 +6,9 @@ *.pyc *.sdf *.suo +.vs/ +*.VC.db +*.VC.opendb core vgcore.* .buildstamp diff -Nru libuv1-1.8.0/gyp_uv.py libuv1-1.9.1/gyp_uv.py --- libuv1-1.8.0/gyp_uv.py 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/gyp_uv.py 2016-05-16 21:22:19.000000000 +0000 @@ -27,6 +27,7 @@ def host_arch(): machine = platform.machine() if machine == 'i386': return 'ia32' + if machine == 'AMD64': return 'x64' if machine == 'x86_64': return 'x64' if machine.startswith('arm'): return 'arm' if machine.startswith('mips'): return 'mips' @@ -36,7 +37,7 @@ def run_gyp(args): rc = gyp.main(args) if rc != 0: - print 'Error running GYP' + print('Error running GYP') sys.exit(rc) @@ -89,5 +90,5 @@ args.append('--no-parallel') gyp_args = list(args) - print gyp_args + print(gyp_args) run_gyp(gyp_args) diff -Nru libuv1-1.8.0/include/pthread-barrier.h libuv1-1.9.1/include/pthread-barrier.h --- libuv1-1.8.0/include/pthread-barrier.h 1970-01-01 00:00:00.000000000 +0000 +++ libuv1-1.9.1/include/pthread-barrier.h 2016-05-16 21:22:19.000000000 +0000 @@ -0,0 +1,64 @@ +/* +Copyright (c) 2016, Kari Tristan Helgason + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef _UV_PTHREAD_BARRIER_ +#define _UV_PTHREAD_BARRIER_ +#include +#include +#include /* sem_t */ + +#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345 + +/* + * To maintain ABI compatibility with + * libuv v1.x struct is padded according + * to target platform + */ +#if defined(__ANDROID__) +# define UV_BARRIER_STRUCT_PADDING \ + sizeof(pthread_mutex_t) + \ + sizeof(pthread_cond_t) + \ + sizeof(unsigned int) - \ + sizeof(void *) +#elif defined(__APPLE__) +# define UV_BARRIER_STRUCT_PADDING \ + sizeof(pthread_mutex_t) + \ + 2 * sizeof(sem_t) + \ + 2 * sizeof(unsigned int) - \ + sizeof(void *) +#endif + +typedef struct { + pthread_mutex_t mutex; + pthread_cond_t cond; + unsigned threshold; + unsigned in; + unsigned out; +} _uv_barrier; + +typedef struct { + _uv_barrier* b; + char _pad[UV_BARRIER_STRUCT_PADDING]; +} pthread_barrier_t; + +int pthread_barrier_init(pthread_barrier_t* barrier, + const void* barrier_attr, + unsigned count); + +int pthread_barrier_wait(pthread_barrier_t* barrier); +int pthread_barrier_destroy(pthread_barrier_t *barrier); + +#endif /* _UV_PTHREAD_BARRIER_ */ diff -Nru libuv1-1.8.0/include/pthread-fixes.h libuv1-1.9.1/include/pthread-fixes.h --- libuv1-1.8.0/include/pthread-fixes.h 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/include/pthread-fixes.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -/* Copyright (c) 2013, Sony Mobile Communications AB - * Copyright (c) 2012, Google Inc. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H -#define GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H - -#include - - -/*Android doesn't provide pthread_barrier_t for now.*/ -#ifndef PTHREAD_BARRIER_SERIAL_THREAD - -/* Anything except 0 will do here.*/ -#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345 - -typedef struct { - pthread_mutex_t mutex; - pthread_cond_t cond; - unsigned count; -} pthread_barrier_t; - -int pthread_barrier_init(pthread_barrier_t* barrier, - const void* barrier_attr, - unsigned count); - -int pthread_barrier_wait(pthread_barrier_t* barrier); -int pthread_barrier_destroy(pthread_barrier_t *barrier); -#endif /* defined(PTHREAD_BARRIER_SERIAL_THREAD) */ - -int pthread_yield(void); - -/* Workaround pthread_sigmask() returning EINVAL on versions < 4.1 by - * replacing all calls to pthread_sigmask with sigprocmask. See: - * https://android.googlesource.com/platform/bionic/+/9bf330b5 - * https://code.google.com/p/android/issues/detail?id=15337 - */ -int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); - -#ifdef pthread_sigmask -#undef pthread_sigmask -#endif -#define pthread_sigmask(how, set, oldset) uv__pthread_sigmask(how, set, oldset) - -#endif /* GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H */ diff -Nru libuv1-1.8.0/include/uv.h libuv1-1.9.1/include/uv.h --- libuv1-1.8.0/include/uv.h 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/include/uv.h 2016-05-16 21:22:19.000000000 +0000 @@ -230,6 +230,7 @@ typedef struct uv_cpu_info_s uv_cpu_info_t; typedef struct uv_interface_address_s uv_interface_address_t; typedef struct uv_dirent_s uv_dirent_t; +typedef struct uv_passwd_s uv_passwd_t; typedef enum { UV_LOOP_BLOCK_SIGNAL @@ -714,7 +715,8 @@ enum uv_poll_event { UV_READABLE = 1, - UV_WRITABLE = 2 + UV_WRITABLE = 2, + UV_DISCONNECT = 4 }; UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd); @@ -1000,6 +1002,14 @@ } netmask; }; +struct uv_passwd_s { + char* username; + long uid; + long gid; + char* shell; + char* homedir; +}; + typedef enum { UV_DIRENT_UNKNOWN, UV_DIRENT_FILE, @@ -1049,6 +1059,9 @@ UV_EXTERN int uv_getrusage(uv_rusage_t* rusage); UV_EXTERN int uv_os_homedir(char* buffer, size_t* size); +UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size); +UV_EXTERN int uv_os_get_passwd(uv_passwd_t* pwd); +UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd); UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count); UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count); diff -Nru libuv1-1.8.0/include/uv-unix.h libuv1-1.9.1/include/uv-unix.h --- libuv1-1.8.0/include/uv-unix.h 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/include/uv-unix.h 2016-05-16 21:22:19.000000000 +0000 @@ -38,9 +38,6 @@ #include #include -#ifdef __ANDROID__ -#include "pthread-fixes.h" -#endif #include #include "uv-threadpool.h" @@ -60,6 +57,10 @@ # include "uv-bsd.h" #endif +#ifndef PTHREAD_BARRIER_SERIAL_THREAD +# include "pthread-barrier.h" +#endif + #ifndef NI_MAXHOST # define NI_MAXHOST 1025 #endif @@ -136,22 +137,8 @@ typedef UV_PLATFORM_SEM_T uv_sem_t; typedef pthread_cond_t uv_cond_t; typedef pthread_key_t uv_key_t; - -#if defined(__APPLE__) && defined(__MACH__) - -typedef struct { - unsigned int n; - unsigned int count; - uv_mutex_t mutex; - uv_sem_t turnstile1; - uv_sem_t turnstile2; -} uv_barrier_t; - -#else /* defined(__APPLE__) && defined(__MACH__) */ - typedef pthread_barrier_t uv_barrier_t; -#endif /* defined(__APPLE__) && defined(__MACH__) */ /* Platform-specific definitions for uv_spawn support. */ typedef gid_t uv_gid_t; diff -Nru libuv1-1.8.0/include/uv-version.h libuv1-1.9.1/include/uv-version.h --- libuv1-1.8.0/include/uv-version.h 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/include/uv-version.h 2016-05-16 21:22:19.000000000 +0000 @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 8 -#define UV_VERSION_PATCH 0 +#define UV_VERSION_MINOR 9 +#define UV_VERSION_PATCH 1 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff -Nru libuv1-1.8.0/include/uv-win.h libuv1-1.9.1/include/uv-win.h --- libuv1-1.8.0/include/uv-win.h 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/include/uv-win.h 2016-05-16 21:22:19.000000000 +0000 @@ -483,7 +483,8 @@ union { \ struct { \ /* Used for readable TTY handles */ \ - HANDLE read_line_handle; \ + /* TODO: remove me in v2.x. */ \ + HANDLE unused_; \ uv_buf_t read_line_buffer; \ HANDLE read_raw_wait; \ /* Fields used for translating win keystrokes into vt100 characters */ \ @@ -634,11 +635,6 @@ struct uv_req_s signal_req; \ unsigned long pending_signum; -int uv_utf16_to_utf8(const WCHAR* utf16Buffer, size_t utf16Size, - char* utf8Buffer, size_t utf8Size); -int uv_utf8_to_utf16(const char* utf8Buffer, WCHAR* utf16Buffer, - size_t utf16Size); - #ifndef F_OK #define F_OK 0 #endif diff -Nru libuv1-1.8.0/.mailmap libuv1-1.9.1/.mailmap --- libuv1-1.8.0/.mailmap 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/.mailmap 2016-05-16 21:22:19.000000000 +0000 @@ -11,6 +11,7 @@ Devchandra Meetei Leishangthem Fedor Indutny Frank Denis +Imran Iqbal Isaac Z. Schlueter Jason Williams Justin Venus diff -Nru libuv1-1.8.0/MAINTAINERS.md libuv1-1.9.1/MAINTAINERS.md --- libuv1-1.8.0/MAINTAINERS.md 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/MAINTAINERS.md 2016-05-16 21:22:19.000000000 +0000 @@ -6,6 +6,7 @@ * **Ben Noordhuis** ([@bnoordhuis](https://github.com/bnoordhuis)) - GPG key: D77B 1E34 243F BAF0 5F8E 9CC3 4F55 C8C8 46AB 89B9 (pubkey-bnoordhuis) * **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus)) +* **Colin Ihrig** ([@cjihrig](https://github.com/cjihrig)) * **Fedor Indutny** ([@indutny](https://github.com/indutny)) - GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny) * **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul)) diff -Nru libuv1-1.8.0/Makefile.am libuv1-1.9.1/Makefile.am --- libuv1-1.8.0/Makefile.am 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/Makefile.am 2016-05-16 21:22:19.000000000 +0000 @@ -45,7 +45,6 @@ AM_CPPFLAGS += -I$(top_srcdir)/src/win \ -DWIN32_LEAN_AND_MEAN \ -D_WIN32_WINNT=0x0600 -LIBS += -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv libuv_la_SOURCES += src/win/async.c \ src/win/atomicops-inl.h \ src/win/core.c \ @@ -130,6 +129,7 @@ TESTS = test/run-tests check_PROGRAMS = test/run-tests test_run_tests_CFLAGS = +test_run_tests_LDFLAGS = test_run_tests_SOURCES = test/blackhole-server.c \ test/dns-server.c \ test/echo-server.c \ @@ -151,6 +151,7 @@ test/test-default-loop-close.c \ test/test-delayed-accept.c \ test/test-dlerror.c \ + test/test-eintr-handling.c \ test/test-embed.c \ test/test-emfile.c \ test/test-error.c \ @@ -161,6 +162,7 @@ test/test-get-currentexe.c \ test/test-get-loadavg.c \ test/test-get-memory.c \ + test/test-get-passwd.c \ test/test-getaddrinfo.c \ test/test-getnameinfo.c \ test/test-getsockname.c \ @@ -242,6 +244,7 @@ test/test-timer-again.c \ test/test-timer-from-check.c \ test/test-timer.c \ + test/test-tmpdir.c \ test/test-tty.c \ test/test-udp-bind.c \ test/test-udp-create-socket-early.c \ @@ -280,36 +283,42 @@ if AIX -libuv_la_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT +libuv_la_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT -D_THREAD_SAFE include_HEADERS += include/uv-aix.h libuv_la_SOURCES += src/unix/aix.c endif if ANDROID include_HEADERS += include/android-ifaddrs.h \ - include/pthread-fixes.h + include/pthread-barrier.h libuv_la_SOURCES += src/unix/android-ifaddrs.c \ - src/unix/pthread-fixes.c + src/unix/pthread-fixes.c \ + src/unix/pthread-barrier.c endif if DARWIN -include_HEADERS += include/uv-darwin.h +include_HEADERS += include/uv-darwin.h \ + include/pthread-barrier.h libuv_la_CFLAGS += -D_DARWIN_USE_64_BIT_INODE=1 libuv_la_CFLAGS += -D_DARWIN_UNLIMITED_SELECT=1 libuv_la_SOURCES += src/unix/darwin.c \ src/unix/darwin-proctitle.c \ src/unix/fsevents.c \ src/unix/kqueue.c \ - src/unix/proctitle.c + src/unix/proctitle.c \ + src/unix/pthread-barrier.c +test_run_tests_LDFLAGS += -lutil endif if DRAGONFLY include_HEADERS += include/uv-bsd.h +test_run_tests_LDFLAGS += -lutil endif if FREEBSD include_HEADERS += include/uv-bsd.h libuv_la_SOURCES += src/unix/freebsd.c src/unix/kqueue.c +test_run_tests_LDFLAGS += -lutil endif if LINUX @@ -320,16 +329,19 @@ src/unix/linux-syscalls.c \ src/unix/linux-syscalls.h \ src/unix/proctitle.c +test_run_tests_LDFLAGS += -lutil endif if NETBSD include_HEADERS += include/uv-bsd.h libuv_la_SOURCES += src/unix/kqueue.c src/unix/netbsd.c +test_run_tests_LDFLAGS += -lutil endif if OPENBSD include_HEADERS += include/uv-bsd.h libuv_la_SOURCES += src/unix/kqueue.c src/unix/openbsd.c +test_run_tests_LDFLAGS += -lutil endif if SUNOS diff -Nru libuv1-1.8.0/README.md libuv1-1.9.1/README.md --- libuv1-1.8.0/README.md 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/README.md 2016-05-16 21:22:19.000000000 +0000 @@ -60,6 +60,11 @@ $ make html +Build documentation as HTML and live reload it when it changes (this requires +sphinx-autobuild to be installed and is only supported on Unix): + + $ make livehtml + Build documentation as man pages: $ make man @@ -156,11 +161,16 @@ ### Unix -Run: +For Debug builds (recommended) run: $ ./gyp_uv.py -f make $ make -C out +For Release builds run: + + $ ./gyp_uv.py -f make + $ BUILDTYPE=Release make -C out + Run `./gyp_uv.py -f make -Dtarget_arch=x32` to build [x32][] binaries. ### OS X @@ -243,3 +253,4 @@ [Visual Studio Express 2010]: http://www.microsoft.com/visualstudio/eng/products/visual-studio-2010-express [guidelines for contributing]: https://github.com/libuv/libuv/blob/master/CONTRIBUTING.md [libuv_banner]: https://raw.githubusercontent.com/libuv/libuv/master/img/banner.png +[x32]: https://en.wikipedia.org/wiki/X32_ABI diff -Nru libuv1-1.8.0/src/fs-poll.c libuv1-1.9.1/src/fs-poll.c --- libuv1-1.8.0/src/fs-poll.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/fs-poll.c 2016-05-16 21:22:19.000000000 +0000 @@ -138,13 +138,14 @@ assert(ctx != NULL); required_len = strlen(ctx->path); - if (required_len > *size) { - *size = required_len; + if (required_len >= *size) { + *size = required_len + 1; return UV_ENOBUFS; } memcpy(buffer, ctx->path, required_len); *size = required_len; + buffer[required_len] = '\0'; return 0; } diff -Nru libuv1-1.8.0/src/unix/aix.c libuv1-1.9.1/src/unix/aix.c --- libuv1-1.8.0/src/unix/aix.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/aix.c 2016-05-16 21:22:19.000000000 +0000 @@ -91,6 +91,24 @@ } +int uv__io_check_fd(uv_loop_t* loop, int fd) { + struct poll_ctl pc; + + pc.events = POLLIN; + pc.cmd = PS_MOD; /* Equivalent to PS_ADD if the fd is not in the pollset. */ + pc.fd = fd; + + if (pollset_ctl(loop->backend_fd, &pc, 1)) + return -errno; + + pc.cmd = PS_DELETE; + if (pollset_ctl(loop->backend_fd, &pc, 1)) + abort(); + + return 0; +} + + void uv__io_poll(uv_loop_t* loop, int timeout) { struct pollfd events[1024]; struct pollfd pqry; @@ -100,6 +118,7 @@ uv__io_t* w; uint64_t base; uint64_t diff; + int have_signals; int nevents; int count; int nfds; @@ -207,6 +226,7 @@ goto update_timeout; } + have_signals = 0; nevents = 0; assert(loop->watchers != NULL); @@ -237,13 +257,26 @@ continue; } - w->cb(loop, w, pe->revents); + /* Run signal watchers last. This also affects child process watchers + * because those are implemented in terms of signal watchers. + */ + if (w == &loop->signal_io_watcher) + have_signals = 1; + else + w->cb(loop, w, pe->revents); + nevents++; } + if (have_signals != 0) + loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); + loop->watchers[loop->nwatchers] = NULL; loop->watchers[loop->nwatchers + 1] = NULL; + if (have_signals != 0) + return; /* Event loop should cycle now so don't poll again. */ + if (nevents != 0) { if (nfds == ARRAY_SIZE(events) && --count != 0) { /* Poll for more events but don't block this time. */ @@ -506,7 +539,7 @@ if (*p == '/') { *p = 0; err = mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - if(err != 0) + if (err != 0 && errno != EEXIST) return err; *p = '/'; } @@ -707,59 +740,44 @@ int bytes, rc = 0; uv_fs_event_t* handle; int events = 0; - int i = 0; char fname[PATH_MAX]; char *p; handle = container_of(event_watch, uv_fs_event_t, event_watcher); - /* Clean all the buffers*/ - for(i = 0; i < PATH_MAX; i++) { - fname[i] = 0; - } - i = 0; - /* At this point, we assume that polling has been done on the * file descriptor, so we can just read the AHAFS event occurrence * data and parse its results without having to block anything */ bytes = pread(event_watch->fd, result_data, RDWR_BUF_SIZE, 0); - assert((bytes <= 0) && "uv__ahafs_event - Error reading monitor file"); + assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file"); /* Parse the data */ if(bytes > 0) rc = uv__parse_data(result_data, &events, handle); + /* Unrecoverable error */ + if (rc == -1) + return; + /* For directory changes, the name of the files that triggered the change * are never absolute pathnames */ if (uv__path_is_a_directory(handle->path) == 0) { p = handle->dir_filename; - while(*p != NULL){ - fname[i]= *p; - i++; - p++; - } } else { - /* For file changes, figure out whether filename is absolute or not */ - if (handle->path[0] == '/') { - p = strrchr(handle->path, '/'); + p = strrchr(handle->path, '/'); + if (p == NULL) + p = handle->path; + else p++; - - while(*p != NULL) { - fname[i]= *p; - i++; - p++; - } - } } + strncpy(fname, p, sizeof(fname) - 1); + /* Just in case */ + fname[sizeof(fname) - 1] = '\0'; - /* Unrecoverable error */ - if (rc == -1) - return; - else /* Call the actual JavaScript callback function */ - handle->cb(handle, (const char*)&fname, events, 0); + handle->cb(handle, fname, events, 0); } #endif @@ -779,53 +797,30 @@ const char* filename, unsigned int flags) { #ifdef HAVE_SYS_AHAFS_EVPRODS_H - int fd, rc, i = 0, res = 0; + int fd, rc, str_offset = 0; char cwd[PATH_MAX]; char absolute_path[PATH_MAX]; - char fname[PATH_MAX]; - char *p; + char readlink_cwd[PATH_MAX]; - /* Clean all the buffers*/ - for(i = 0; i < PATH_MAX; i++) { - cwd[i] = 0; - absolute_path[i] = 0; - fname[i] = 0; - } - i = 0; /* Figure out whether filename is absolute or not */ if (filename[0] == '/') { - /* We have absolute pathname, create the relative pathname*/ - sprintf(absolute_path, filename); - p = strrchr(filename, '/'); - p++; + /* We have absolute pathname */ + snprintf(absolute_path, sizeof(absolute_path), "%s", filename); } else { - if (filename[0] == '.' && filename[1] == '/') { - /* We have a relative pathname, compose the absolute pathname */ - sprintf(fname, filename); - snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid()); - res = readlink(cwd, absolute_path, sizeof(absolute_path) - 1); - if (res < 0) - return res; - p = strrchr(absolute_path, '/'); - p++; - p++; - } else { - /* We have a relative pathname, compose the absolute pathname */ - sprintf(fname, filename); - snprintf(cwd, PATH_MAX-1, "/proc/%lu/cwd", (unsigned long) getpid()); - res = readlink(cwd, absolute_path, sizeof(absolute_path) - 1); - if (res < 0) - return res; - p = strrchr(absolute_path, '/'); - p++; - } - /* Copy to filename buffer */ - while(filename[i] != NULL) { - *p = filename[i]; - i++; - p++; - } + /* We have a relative pathname, compose the absolute pathname */ + snprintf(cwd, sizeof(cwd), "/proc/%lu/cwd", (unsigned long) getpid()); + rc = readlink(cwd, readlink_cwd, sizeof(readlink_cwd) - 1); + if (rc < 0) + return rc; + /* readlink does not null terminate our string */ + readlink_cwd[rc] = '\0'; + + if (filename[0] == '.' && filename[1] == '/') + str_offset = 2; + + snprintf(absolute_path, sizeof(absolute_path), "%s%s", readlink_cwd, + filename + str_offset); } if (uv__is_ahafs_mounted() < 0) /* /aha checks failed */ @@ -839,10 +834,10 @@ /* Setup/Initialize all the libuv routines */ uv__handle_start(handle); uv__io_init(&handle->event_watcher, uv__ahafs_event, fd); - handle->path = uv__strdup((const char*)&absolute_path); + handle->path = uv__strdup(filename); handle->cb = cb; - uv__io_start(handle->loop, &handle->event_watcher, UV__POLLIN); + uv__io_start(handle->loop, &handle->event_watcher, POLLIN); return 0; #else @@ -1033,14 +1028,14 @@ } if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) { - SAVE_ERRNO(uv__close(sockfd)); + uv__close(sockfd); return -errno; } ifc.ifc_req = (struct ifreq*)uv__malloc(size); ifc.ifc_len = size; if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { - SAVE_ERRNO(uv__close(sockfd)); + uv__close(sockfd); return -errno; } @@ -1059,7 +1054,7 @@ memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - SAVE_ERRNO(uv__close(sockfd)); + uv__close(sockfd); return -errno; } diff -Nru libuv1-1.8.0/src/unix/async.c libuv1-1.9.1/src/unix/async.c --- libuv1-1.8.0/src/unix/async.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/async.c 2016-05-16 21:22:19.000000000 +0000 @@ -223,7 +223,7 @@ return err; uv__io_init(&wa->io_watcher, uv__async_io, pipefd[0]); - uv__io_start(loop, &wa->io_watcher, UV__POLLIN); + uv__io_start(loop, &wa->io_watcher, POLLIN); wa->wfd = pipefd[1]; wa->cb = cb; @@ -241,7 +241,7 @@ wa->wfd = -1; } - uv__io_stop(loop, &wa->io_watcher, UV__POLLIN); + uv__io_stop(loop, &wa->io_watcher, POLLIN); uv__close(wa->io_watcher.fd); wa->io_watcher.fd = -1; } diff -Nru libuv1-1.8.0/src/unix/core.c libuv1-1.9.1/src/unix/core.c --- libuv1-1.8.0/src/unix/core.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/core.c 2016-05-16 21:22:19.000000000 +0000 @@ -53,6 +53,9 @@ # include /* _NSGetExecutablePath */ # include # include +# if defined(O_CLOEXEC) +# define UV__O_CLOEXEC O_CLOEXEC +# endif #endif #if defined(__FreeBSD__) || defined(__DragonFly__) @@ -427,6 +430,22 @@ return sockfd; } +/* get a file pointer to a file in read-only and close-on-exec mode */ +FILE* uv__open_file(const char* path) { + int fd; + FILE* fp; + + fd = uv__open_cloexec(path, O_RDONLY); + if (fd < 0) + return NULL; + + fp = fdopen(fd, "r"); + if (fp == NULL) + uv__close(fd); + + return fp; +} + int uv__accept(int sockfd) { int peerfd; @@ -435,7 +454,7 @@ assert(sockfd >= 0); while (1) { -#if defined(__linux__) || __FreeBSD__ >= 10 +#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) static int no_accept4; if (no_accept4) @@ -479,12 +498,11 @@ } -int uv__close(int fd) { +int uv__close_nocheckstdio(int fd) { int saved_errno; int rc; assert(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */ - assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */ saved_errno = errno; rc = close(fd); @@ -499,6 +517,12 @@ } +int uv__close(int fd) { + assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */ + return uv__close_nocheckstdio(fd); +} + + #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ defined(_AIX) || defined(__DragonFly__) @@ -738,7 +762,7 @@ QUEUE_REMOVE(q); QUEUE_INIT(q); w = QUEUE_DATA(q, uv__io_t, pending_queue); - w->cb(loop, w, UV__POLLOUT); + w->cb(loop, w, POLLOUT); } return 1; @@ -809,7 +833,7 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT))); + assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP))); assert(0 != events); assert(w->fd >= 0); assert(w->fd < INT_MAX); @@ -842,7 +866,7 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT))); + assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP))); assert(0 != events); if (w->fd == -1) @@ -874,7 +898,7 @@ void uv__io_close(uv_loop_t* loop, uv__io_t* w) { - uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT); + uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP); QUEUE_REMOVE(&w->pending_queue); /* Remove stale events for this file descriptor */ @@ -889,7 +913,7 @@ int uv__io_active(const uv__io_t* w, unsigned int events) { - assert(0 == (events & ~(UV__POLLIN | UV__POLLOUT))); + assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP))); assert(0 != events); return 0 != (w->pevents & events); } @@ -930,8 +954,7 @@ int err; int fd; -#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 9) || \ - defined(__DragonFly__) +#if defined(UV__O_CLOEXEC) static int no_cloexec; if (!no_cloexec) { @@ -1014,17 +1037,10 @@ int uv_os_homedir(char* buffer, size_t* size) { - struct passwd pw; - struct passwd* result; + uv_passwd_t pwd; char* buf; - uid_t uid; - size_t bufsize; size_t len; - long initsize; int r; -#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 - int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**); -#endif if (buffer == NULL || size == NULL || *size == 0) return -EINVAL; @@ -1036,7 +1052,7 @@ len = strlen(buf); if (len >= *size) { - *size = len; + *size = len + 1; return -ENOBUFS; } @@ -1046,13 +1062,102 @@ return 0; } + /* HOME is not set, so call uv__getpwuid_r() */ + r = uv__getpwuid_r(&pwd); + + if (r != 0) { + return r; + } + + len = strlen(pwd.homedir); + + if (len >= *size) { + *size = len + 1; + uv_os_free_passwd(&pwd); + return -ENOBUFS; + } + + memcpy(buffer, pwd.homedir, len + 1); + *size = len; + uv_os_free_passwd(&pwd); + + return 0; +} + + +int uv_os_tmpdir(char* buffer, size_t* size) { + const char* buf; + size_t len; + + if (buffer == NULL || size == NULL || *size == 0) + return -EINVAL; + +#define CHECK_ENV_VAR(name) \ + do { \ + buf = getenv(name); \ + if (buf != NULL) \ + goto return_buffer; \ + } \ + while (0) + + /* Check the TMPDIR, TMP, TEMP, and TEMPDIR environment variables in order */ + CHECK_ENV_VAR("TMPDIR"); + CHECK_ENV_VAR("TMP"); + CHECK_ENV_VAR("TEMP"); + CHECK_ENV_VAR("TEMPDIR"); + +#undef CHECK_ENV_VAR + + /* No temp environment variables defined */ + #if defined(__ANDROID__) + buf = "/data/local/tmp"; + #else + buf = "/tmp"; + #endif + +return_buffer: + len = strlen(buf); + + if (len >= *size) { + *size = len + 1; + return -ENOBUFS; + } + + /* The returned directory should not have a trailing slash. */ + if (len > 1 && buf[len - 1] == '/') { + len--; + } + + memcpy(buffer, buf, len + 1); + buffer[len] = '\0'; + *size = len; + + return 0; +} + + +int uv__getpwuid_r(uv_passwd_t* pwd) { + struct passwd pw; + struct passwd* result; + char* buf; + uid_t uid; + size_t bufsize; + size_t name_size; + size_t homedir_size; + size_t shell_size; + long initsize; + int r; #if defined(__ANDROID_API__) && __ANDROID_API__ < 21 + int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**); + getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r"); if (getpwuid_r == NULL) return -ENOSYS; #endif - /* HOME is not set, so call getpwuid() */ + if (pwd == NULL) + return -EINVAL; + initsize = sysconf(_SC_GETPW_R_SIZE_MAX); if (initsize <= 0) @@ -1060,7 +1165,7 @@ else bufsize = (size_t) initsize; - uid = getuid(); + uid = geteuid(); buf = NULL; for (;;) { @@ -1088,17 +1193,54 @@ return -ENOENT; } - len = strlen(pw.pw_dir); + /* Allocate memory for the username, shell, and home directory */ + name_size = strlen(pw.pw_name) + 1; + homedir_size = strlen(pw.pw_dir) + 1; + shell_size = strlen(pw.pw_shell) + 1; + pwd->username = uv__malloc(name_size + homedir_size + shell_size); - if (len >= *size) { - *size = len; + if (pwd->username == NULL) { uv__free(buf); - return -ENOBUFS; + return -ENOMEM; } - memcpy(buffer, pw.pw_dir, len + 1); - *size = len; + /* Copy the username */ + memcpy(pwd->username, pw.pw_name, name_size); + + /* Copy the home directory */ + pwd->homedir = pwd->username + name_size; + memcpy(pwd->homedir, pw.pw_dir, homedir_size); + + /* Copy the shell */ + pwd->shell = pwd->homedir + homedir_size; + memcpy(pwd->shell, pw.pw_shell, shell_size); + + /* Copy the uid and gid */ + pwd->uid = pw.pw_uid; + pwd->gid = pw.pw_gid; + uv__free(buf); return 0; } + + +void uv_os_free_passwd(uv_passwd_t* pwd) { + if (pwd == NULL) + return; + + /* + The memory for name, shell, and homedir are allocated in a single + uv__malloc() call. The base of the pointer is stored in pwd->username, so + that is the field that needs to be freed. + */ + uv__free(pwd->username); + pwd->username = NULL; + pwd->shell = NULL; + pwd->homedir = NULL; +} + + +int uv_os_get_passwd(uv_passwd_t* pwd) { + return uv__getpwuid_r(pwd); +} diff -Nru libuv1-1.8.0/src/unix/freebsd.c libuv1-1.9.1/src/unix/freebsd.c --- libuv1-1.8.0/src/unix/freebsd.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/freebsd.c 2016-05-16 21:22:19.000000000 +0000 @@ -292,7 +292,7 @@ size = sizeof(cpuspeed); if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0)) { - SAVE_ERRNO(uv__free(*cpu_infos)); + uv__free(*cpu_infos); return -errno; } @@ -301,7 +301,7 @@ */ size = sizeof(maxcpus); if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0)) { - SAVE_ERRNO(uv__free(*cpu_infos)); + uv__free(*cpu_infos); return -errno; } @@ -314,8 +314,8 @@ } if (sysctlbyname(cptimes_key, cp_times, &size, NULL, 0)) { - SAVE_ERRNO(uv__free(cp_times)); - SAVE_ERRNO(uv__free(*cpu_infos)); + uv__free(cp_times); + uv__free(*cpu_infos); return -errno; } diff -Nru libuv1-1.8.0/src/unix/fs.c libuv1-1.9.1/src/unix/fs.c --- libuv1-1.8.0/src/unix/fs.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/fs.c 2016-05-16 21:22:19.000000000 +0000 @@ -33,6 +33,7 @@ #include #include #include +#include /* PATH_MAX */ #include #include @@ -127,8 +128,8 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) { #if defined(__linux__) || defined(__sun) || defined(__NetBSD__) return fdatasync(req->file); -#elif defined(__APPLE__) && defined(F_FULLFSYNC) - return fcntl(req->file, F_FULLFSYNC); +#elif defined(__APPLE__) && defined(SYS_fdatasync) + return syscall(SYS_fdatasync, req->file); #else return fsync(req->file); #endif @@ -205,6 +206,13 @@ # else return futimes(req->file, tv); # endif +#elif defined(_AIX71) + struct timespec ts[2]; + ts[0].tv_sec = req->atime; + ts[0].tv_nsec = (unsigned long)(req->atime * 1000000) % 1000000 * 1000; + ts[1].tv_sec = req->mtime; + ts[1].tv_nsec = (unsigned long)(req->mtime * 1000000) % 1000000 * 1000; + return futimens(req->file, ts); #else errno = ENOSYS; return -1; @@ -362,9 +370,10 @@ if (dents != NULL) { int i; + /* Memory was allocated using the system allocator, so use free() here. */ for (i = 0; i < n; i++) - uv__free(dents[i]); - uv__free(dents); + free(dents[i]); + free(dents); } errno = saved_errno; @@ -383,7 +392,7 @@ #if defined(PATH_MAX) return PATH_MAX; #else - return 4096; +#error "PATH_MAX undefined in the current platform" #endif } @@ -749,13 +758,13 @@ dst->st_gen = src->st_gen; #elif defined(__ANDROID__) dst->st_atim.tv_sec = src->st_atime; - dst->st_atim.tv_nsec = src->st_atime_nsec; + dst->st_atim.tv_nsec = src->st_atimensec; dst->st_mtim.tv_sec = src->st_mtime; - dst->st_mtim.tv_nsec = src->st_mtime_nsec; + dst->st_mtim.tv_nsec = src->st_mtimensec; dst->st_ctim.tv_sec = src->st_ctime; - dst->st_ctim.tv_nsec = src->st_ctime_nsec; + dst->st_ctim.tv_nsec = src->st_ctimensec; dst->st_birthtim.tv_sec = src->st_ctime; - dst->st_birthtim.tv_nsec = src->st_ctime_nsec; + dst->st_birthtim.tv_nsec = src->st_ctimensec; dst->st_flags = 0; dst->st_gen = 0; #elif !defined(_AIX) && ( \ @@ -858,9 +867,14 @@ total += result; } + if (errno == EINTR && total == -1) + return total; + if (bufs != req->bufsml) uv__free(bufs); + req->bufs = NULL; + req->nbufs = 0; return total; } diff -Nru libuv1-1.8.0/src/unix/internal.h libuv1-1.9.1/src/unix/internal.h --- libuv1-1.8.0/src/unix/internal.h 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/internal.h 2016-05-16 21:22:19.000000000 +0000 @@ -28,6 +28,7 @@ #include /* abort */ #include /* strrchr */ #include /* O_CLOEXEC, may be */ +#include #if defined(__STRICT_ANSI__) # define inline __inline @@ -43,15 +44,25 @@ #endif /* __sun */ #if defined(_AIX) -#define reqevents events -#define rtnevents revents -#include +# define reqevents events +# define rtnevents revents +# include +#else +# include #endif /* _AIX */ #if defined(__APPLE__) && !TARGET_OS_IPHONE # include #endif +#if defined(__ANDROID__) +int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); +# ifdef pthread_sigmask +# undef pthread_sigmask +# endif +# define pthread_sigmask(how, set, oldset) uv__pthread_sigmask(how, set, oldset) +#endif + #define ACCESS_ONCE(type, var) \ (*(volatile type*) &(var)) @@ -88,34 +99,11 @@ # define UV_UNUSED(declaration) declaration #endif -#if defined(__linux__) -# define UV__POLLIN UV__EPOLLIN -# define UV__POLLOUT UV__EPOLLOUT -# define UV__POLLERR UV__EPOLLERR -# define UV__POLLHUP UV__EPOLLHUP -#endif - -#if defined(__sun) || defined(_AIX) -# define UV__POLLIN POLLIN -# define UV__POLLOUT POLLOUT -# define UV__POLLERR POLLERR -# define UV__POLLHUP POLLHUP -#endif - -#ifndef UV__POLLIN -# define UV__POLLIN 1 -#endif - -#ifndef UV__POLLOUT -# define UV__POLLOUT 2 -#endif - -#ifndef UV__POLLERR -# define UV__POLLERR 4 -#endif - -#ifndef UV__POLLHUP -# define UV__POLLHUP 8 +/* Leans on the fact that, on Linux, POLLRDHUP == EPOLLRDHUP. */ +#ifdef POLLRDHUP +# define UV__POLLRDHUP POLLRDHUP +#else +# define UV__POLLRDHUP 0x2000 #endif #if !defined(O_CLOEXEC) && defined(__FreeBSD__) @@ -167,6 +155,7 @@ /* core */ int uv__nonblock(int fd, int set); int uv__close(int fd); +int uv__close_nocheckstdio(int fd); int uv__cloexec(int fd, int set); int uv__socket(int domain, int type, int protocol); int uv__dup(int fd); @@ -180,6 +169,7 @@ void uv__io_close(uv_loop_t* loop, uv__io_t* w); void uv__io_feed(uv_loop_t* loop, uv__io_t* w); int uv__io_active(const uv__io_t* w, unsigned int events); +int uv__io_check_fd(uv_loop_t* loop, int fd); void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */ /* async */ @@ -245,6 +235,9 @@ void uv__udp_close(uv_udp_t* handle); void uv__udp_finish_close(uv_udp_t* handle); uv_handle_type uv__handle_type(int fd); +FILE* uv__open_file(const char* path); +int uv__getpwuid_r(uv_passwd_t* pwd); + #if defined(__APPLE__) int uv___stream_fd(const uv_stream_t* handle); diff -Nru libuv1-1.8.0/src/unix/kqueue.c libuv1-1.9.1/src/unix/kqueue.c --- libuv1-1.8.0/src/unix/kqueue.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/kqueue.c 2016-05-16 21:22:19.000000000 +0000 @@ -48,6 +48,24 @@ } +int uv__io_check_fd(uv_loop_t* loop, int fd) { + struct kevent ev; + int rc; + + rc = 0; + EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0); + if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL)) + rc = -errno; + + EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0); + if (rc == 0) + if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL)) + abort(); + + return rc; +} + + void uv__io_poll(uv_loop_t* loop, int timeout) { struct kevent events[1024]; struct kevent* ev; @@ -60,6 +78,7 @@ sigset_t set; uint64_t base; uint64_t diff; + int have_signals; int filter; int fflags; int count; @@ -85,7 +104,7 @@ assert(w->fd >= 0); assert(w->fd < (int) loop->nwatchers); - if ((w->events & UV__POLLIN) == 0 && (w->pevents & UV__POLLIN) != 0) { + if ((w->events & POLLIN) == 0 && (w->pevents & POLLIN) != 0) { filter = EVFILT_READ; fflags = 0; op = EV_ADD; @@ -106,7 +125,7 @@ } } - if ((w->events & UV__POLLOUT) == 0 && (w->pevents & UV__POLLOUT) != 0) { + if ((w->events & POLLOUT) == 0 && (w->pevents & POLLOUT) != 0) { EV_SET(events + nevents, w->fd, EVFILT_WRITE, EV_ADD, 0, 0, 0); if (++nevents == ARRAY_SIZE(events)) { @@ -174,6 +193,7 @@ goto update_timeout; } + have_signals = 0; nevents = 0; assert(loop->watchers != NULL); @@ -201,8 +221,8 @@ } if (ev->filter == EVFILT_VNODE) { - assert(w->events == UV__POLLIN); - assert(w->pevents == UV__POLLIN); + assert(w->events == POLLIN); + assert(w->pevents == POLLIN); w->cb(loop, w, ev->fflags); /* XXX always uv__fs_event() */ nevents++; continue; @@ -211,8 +231,8 @@ revents = 0; if (ev->filter == EVFILT_READ) { - if (w->pevents & UV__POLLIN) { - revents |= UV__POLLIN; + if (w->pevents & POLLIN) { + revents |= POLLIN; w->rcount = ev->data; } else { /* TODO batch up */ @@ -225,8 +245,8 @@ } if (ev->filter == EVFILT_WRITE) { - if (w->pevents & UV__POLLOUT) { - revents |= UV__POLLOUT; + if (w->pevents & POLLOUT) { + revents |= POLLOUT; w->wcount = ev->data; } else { /* TODO batch up */ @@ -239,17 +259,34 @@ } if (ev->flags & EV_ERROR) - revents |= UV__POLLERR; + revents |= POLLERR; + + if ((ev->flags & EV_EOF) && (w->pevents & UV__POLLRDHUP)) + revents |= UV__POLLRDHUP; if (revents == 0) continue; - w->cb(loop, w, revents); + /* Run signal watchers last. This also affects child process watchers + * because those are implemented in terms of signal watchers. + */ + if (w == &loop->signal_io_watcher) + have_signals = 1; + else + w->cb(loop, w, revents); + nevents++; } + + if (have_signals != 0) + loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); + loop->watchers[loop->nwatchers] = NULL; loop->watchers[loop->nwatchers + 1] = NULL; + if (have_signals != 0) + return; /* Event loop should cycle now so don't poll again. */ + if (nevents != 0) { if (nfds == ARRAY_SIZE(events) && --count != 0) { /* Poll for more events but don't block this time. */ @@ -388,7 +425,7 @@ fallback: #endif /* defined(__APPLE__) */ - uv__io_start(handle->loop, &handle->event_watcher, UV__POLLIN); + uv__io_start(handle->loop, &handle->event_watcher, POLLIN); return 0; } diff -Nru libuv1-1.8.0/src/unix/linux-core.c libuv1-1.9.1/src/unix/linux-core.c --- libuv1-1.8.0/src/unix/linux-core.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/linux-core.c 2016-05-16 21:22:19.000000000 +0000 @@ -18,6 +18,11 @@ * IN THE SOFTWARE. */ +/* We lean on the fact that POLL{IN,OUT,ERR,HUP} correspond with their + * EPOLL* counterparts. We use the POLL* variants in this file because that + * is what libuv uses elsewhere and it avoids a dependency on . + */ + #include "uv.h" #include "internal.h" @@ -39,7 +44,7 @@ #define HAVE_IFADDRS_H 1 #ifdef __UCLIBC__ -# if __UCLIBC_MAJOR__ < 0 || __UCLIBC_MINOR__ < 9 || __UCLIBC_SUBLEVEL__ < 32 +# if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32 # undef HAVE_IFADDRS_H # endif #endif @@ -52,7 +57,7 @@ # endif # include # include -# include +# include #endif /* HAVE_IFADDRS_H */ /* Available from 2.6.32 onwards. */ @@ -69,7 +74,9 @@ #endif static int read_models(unsigned int numcpus, uv_cpu_info_t* ci); -static int read_times(unsigned int numcpus, uv_cpu_info_t* ci); +static int read_times(FILE* statfile_fp, + unsigned int numcpus, + uv_cpu_info_t* ci); static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci); static unsigned long read_cpufreq(unsigned int cpunum); @@ -102,7 +109,7 @@ void uv__platform_loop_delete(uv_loop_t* loop) { if (loop->inotify_fd == -1) return; - uv__io_stop(loop, &loop->inotify_read_watcher, UV__POLLIN); + uv__io_stop(loop, &loop->inotify_read_watcher, POLLIN); uv__close(loop->inotify_fd); loop->inotify_fd = -1; } @@ -140,6 +147,26 @@ } +int uv__io_check_fd(uv_loop_t* loop, int fd) { + struct uv__epoll_event e; + int rc; + + e.events = POLLIN; + e.data = -1; + + rc = 0; + if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_ADD, fd, &e)) + if (errno != EEXIST) + rc = -errno; + + if (rc == 0) + if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &e)) + abort(); + + return rc; +} + + void uv__io_poll(uv_loop_t* loop, int timeout) { /* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes * effectively infinite on 32 bits architectures. To avoid blocking @@ -161,6 +188,7 @@ sigset_t sigset; uint64_t sigmask; uint64_t base; + int have_signals; int nevents; int count; int nfds; @@ -288,6 +316,7 @@ goto update_timeout; } + have_signals = 0; nevents = 0; assert(loop->watchers != NULL); @@ -321,7 +350,7 @@ * the current watcher. Also, filters out events that users has not * requested us to watch. */ - pe->events &= w->pevents | UV__POLLERR | UV__POLLHUP; + pe->events &= w->pevents | POLLERR | POLLHUP; /* Work around an epoll quirk where it sometimes reports just the * EPOLLERR or EPOLLHUP event. In order to force the event loop to @@ -338,17 +367,31 @@ * needs to remember the error/hangup event. We should get that for * free when we switch over to edge-triggered I/O. */ - if (pe->events == UV__EPOLLERR || pe->events == UV__EPOLLHUP) - pe->events |= w->pevents & (UV__EPOLLIN | UV__EPOLLOUT); + if (pe->events == POLLERR || pe->events == POLLHUP) + pe->events |= w->pevents & (POLLIN | POLLOUT); if (pe->events != 0) { - w->cb(loop, w, pe->events); + /* Run signal watchers last. This also affects child process watchers + * because those are implemented in terms of signal watchers. + */ + if (w == &loop->signal_io_watcher) + have_signals = 1; + else + w->cb(loop, w, pe->events); + nevents++; } } + + if (have_signals != 0) + loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); + loop->watchers[loop->nwatchers] = NULL; loop->watchers[loop->nwatchers + 1] = NULL; + if (have_signals != 0) + return; /* Event loop should cycle now so don't poll again. */ + if (nevents != 0) { if (nfds == ARRAY_SIZE(events) && --count != 0) { /* Poll for more events but don't block this time. */ @@ -532,29 +575,57 @@ } +static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) { + unsigned int num; + char buf[1024]; + + if (!fgets(buf, sizeof(buf), statfile_fp)) + return -EIO; + + num = 0; + while (fgets(buf, sizeof(buf), statfile_fp)) { + if (strncmp(buf, "cpu", 3)) + break; + num++; + } + + if (num == 0) + return -EIO; + + *numcpus = num; + return 0; +} + + int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { unsigned int numcpus; uv_cpu_info_t* ci; int err; + FILE* statfile_fp; *cpu_infos = NULL; *count = 0; - numcpus = sysconf(_SC_NPROCESSORS_ONLN); - assert(numcpus != (unsigned int) -1); - assert(numcpus != 0); + statfile_fp = uv__open_file("/proc/stat"); + if (statfile_fp == NULL) + return -errno; + + err = uv__cpu_num(statfile_fp, &numcpus); + if (err < 0) + goto out; + err = -ENOMEM; ci = uv__calloc(numcpus, sizeof(*ci)); if (ci == NULL) - return -ENOMEM; + goto out; err = read_models(numcpus, ci); if (err == 0) - err = read_times(numcpus, ci); + err = read_times(statfile_fp, numcpus, ci); if (err) { uv_free_cpu_info(ci, numcpus); - return err; + goto out; } /* read_models() on x86 also reads the CPU speed from /proc/cpuinfo. @@ -565,8 +636,15 @@ *cpu_infos = ci; *count = numcpus; + err = 0; - return 0; +out: + + if (fclose(statfile_fp)) + if (errno != EINTR && errno != EINPROGRESS) + abort(); + + return err; } @@ -608,7 +686,7 @@ defined(__i386__) || \ defined(__mips__) || \ defined(__x86_64__) - fp = fopen("/proc/cpuinfo", "r"); + fp = uv__open_file("/proc/cpuinfo"); if (fp == NULL) return -errno; @@ -676,7 +754,9 @@ } -static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) { +static int read_times(FILE* statfile_fp, + unsigned int numcpus, + uv_cpu_info_t* ci) { unsigned long clock_ticks; struct uv_cpu_times_s ts; unsigned long user; @@ -688,22 +768,19 @@ unsigned int num; unsigned int len; char buf[1024]; - FILE* fp; clock_ticks = sysconf(_SC_CLK_TCK); assert(clock_ticks != (unsigned long) -1); assert(clock_ticks != 0); - fp = fopen("/proc/stat", "r"); - if (fp == NULL) - return -errno; + rewind(statfile_fp); - if (!fgets(buf, sizeof(buf), fp)) + if (!fgets(buf, sizeof(buf), statfile_fp)) abort(); num = 0; - while (fgets(buf, sizeof(buf), fp)) { + while (fgets(buf, sizeof(buf), statfile_fp)) { if (num >= numcpus) break; @@ -742,7 +819,6 @@ ts.irq = clock_ticks * irq; ci[num++].cpu_times = ts; } - fclose(fp); assert(num == numcpus); return 0; @@ -759,7 +835,7 @@ "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq", cpunum); - fp = fopen(buf, "r"); + fp = uv__open_file(buf); if (fp == NULL) return 0; diff -Nru libuv1-1.8.0/src/unix/linux-inotify.c libuv1-1.9.1/src/unix/linux-inotify.c --- libuv1-1.8.0/src/unix/linux-inotify.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/linux-inotify.c 2016-05-16 21:22:19.000000000 +0000 @@ -102,7 +102,7 @@ loop->inotify_fd = err; uv__io_init(&loop->inotify_read_watcher, uv__inotify_read, loop->inotify_fd); - uv__io_start(loop, &loop->inotify_read_watcher, UV__POLLIN); + uv__io_start(loop, &loop->inotify_read_watcher, POLLIN); return 0; } diff -Nru libuv1-1.8.0/src/unix/linux-syscalls.h libuv1-1.9.1/src/unix/linux-syscalls.h --- libuv1-1.8.0/src/unix/linux-syscalls.h 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/linux-syscalls.h 2016-05-16 21:22:19.000000000 +0000 @@ -72,13 +72,6 @@ #define UV__EPOLL_CTL_DEL 2 #define UV__EPOLL_CTL_MOD 3 -#define UV__EPOLLIN 1 -#define UV__EPOLLOUT 4 -#define UV__EPOLLERR 8 -#define UV__EPOLLHUP 16 -#define UV__EPOLLONESHOT 0x40000000 -#define UV__EPOLLET 0x80000000 - /* inotify flags */ #define UV__IN_ACCESS 0x001 #define UV__IN_MODIFY 0x002 diff -Nru libuv1-1.8.0/src/unix/openbsd.c libuv1-1.9.1/src/unix/openbsd.c --- libuv1-1.8.0/src/unix/openbsd.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/openbsd.c 2016-05-16 21:22:19.000000000 +0000 @@ -247,7 +247,7 @@ which[1] = HW_CPUSPEED; size = sizeof(cpuspeed); if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) { - SAVE_ERRNO(uv__free(*cpu_infos)); + uv__free(*cpu_infos); return -errno; } @@ -258,7 +258,7 @@ which[2] = i; size = sizeof(info); if (sysctl(which, 3, &info, &size, NULL, 0)) { - SAVE_ERRNO(uv__free(*cpu_infos)); + uv__free(*cpu_infos); return -errno; } diff -Nru libuv1-1.8.0/src/unix/pipe.c libuv1-1.9.1/src/unix/pipe.c --- libuv1-1.8.0/src/unix/pipe.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/pipe.c 2016-05-16 21:22:19.000000000 +0000 @@ -102,7 +102,7 @@ handle->connection_cb = cb; handle->io_watcher.cb = uv__server_io; - uv__io_start(handle->loop, &handle->io_watcher, UV__POLLIN); + uv__io_start(handle->loop, &handle->io_watcher, POLLIN); return 0; } @@ -185,7 +185,7 @@ } if (err == 0) - uv__io_start(handle->loop, &handle->io_watcher, UV__POLLIN | UV__POLLOUT); + uv__io_start(handle->loop, &handle->io_watcher, POLLIN | POLLOUT); out: handle->delayed_error = err; @@ -200,9 +200,6 @@ if (err) uv__io_feed(handle->loop, &handle->io_watcher); - /* Mimic the Windows pipe implementation, always - * return 0 and let the callback handle errors. - */ } @@ -234,14 +231,18 @@ addrlen = strlen(sa.sun_path); - if (addrlen > *size) { - *size = addrlen; + if (addrlen >= *size) { + *size = addrlen + 1; return UV_ENOBUFS; } memcpy(buffer, sa.sun_path, addrlen); *size = addrlen; + /* only null-terminate if it's not an abstract socket */ + if (buffer[0] != '\0') + buffer[addrlen] = '\0'; + return 0; } diff -Nru libuv1-1.8.0/src/unix/poll.c libuv1-1.9.1/src/unix/poll.c --- libuv1-1.8.0/src/unix/poll.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/poll.c 2016-05-16 21:22:19.000000000 +0000 @@ -33,18 +33,20 @@ handle = container_of(w, uv_poll_t, io_watcher); - if (events & UV__POLLERR) { - uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT); + if (events & POLLERR) { + uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP); uv__handle_stop(handle); handle->poll_cb(handle, -EBADF, 0); return; } pevents = 0; - if (events & UV__POLLIN) + if (events & POLLIN) pevents |= UV_READABLE; - if (events & UV__POLLOUT) + if (events & POLLOUT) pevents |= UV_WRITABLE; + if (events & UV__POLLRDHUP) + pevents |= UV_DISCONNECT; handle->poll_cb(handle, 0, pevents); } @@ -53,6 +55,10 @@ int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { int err; + err = uv__io_check_fd(loop, fd); + if (err) + return err; + err = uv__nonblock(fd, 1); if (err) return err; @@ -71,7 +77,9 @@ static void uv__poll_stop(uv_poll_t* handle) { - uv__io_stop(handle->loop, &handle->io_watcher, UV__POLLIN | UV__POLLOUT); + uv__io_stop(handle->loop, + &handle->io_watcher, + POLLIN | POLLOUT | UV__POLLRDHUP); uv__handle_stop(handle); } @@ -86,7 +94,7 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) { int events; - assert((pevents & ~(UV_READABLE | UV_WRITABLE)) == 0); + assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0); assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); uv__poll_stop(handle); @@ -96,9 +104,11 @@ events = 0; if (pevents & UV_READABLE) - events |= UV__POLLIN; + events |= POLLIN; if (pevents & UV_WRITABLE) - events |= UV__POLLOUT; + events |= POLLOUT; + if (pevents & UV_DISCONNECT) + events |= UV__POLLRDHUP; uv__io_start(handle->loop, &handle->io_watcher, events); uv__handle_start(handle); diff -Nru libuv1-1.8.0/src/unix/process.c libuv1-1.9.1/src/unix/process.c --- libuv1-1.8.0/src/unix/process.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/process.c 2016-05-16 21:22:19.000000000 +0000 @@ -498,7 +498,7 @@ } else abort(); - uv__close(signal_pipe[0]); + uv__close_nocheckstdio(signal_pipe[0]); for (i = 0; i < options->stdio_count; i++) { err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0); @@ -530,9 +530,9 @@ if (options->stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM)) continue; if (pipes[i][0] != -1) - close(pipes[i][0]); + uv__close_nocheckstdio(pipes[i][0]); if (pipes[i][1] != -1) - close(pipes[i][1]); + uv__close_nocheckstdio(pipes[i][1]); } uv__free(pipes); } diff -Nru libuv1-1.8.0/src/unix/pthread-barrier.c libuv1-1.9.1/src/unix/pthread-barrier.c --- libuv1-1.8.0/src/unix/pthread-barrier.c 1970-01-01 00:00:00.000000000 +0000 +++ libuv1-1.9.1/src/unix/pthread-barrier.c 2016-05-16 21:22:19.000000000 +0000 @@ -0,0 +1,120 @@ +/* +Copyright (c) 2016, Kari Tristan Helgason + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +#include "uv-common.h" +#include "pthread-barrier.h" + +#include +#include + +/* TODO: support barrier_attr */ +int pthread_barrier_init(pthread_barrier_t* barrier, + const void* barrier_attr, + unsigned count) { + int rc; + _uv_barrier* b; + + if (barrier == NULL || count == 0) + return EINVAL; + + if (barrier_attr != NULL) + return ENOTSUP; + + b = uv__malloc(sizeof(*b)); + if (b == NULL) + return ENOMEM; + + b->in = 0; + b->out = 0; + b->threshold = count; + + if ((rc = pthread_mutex_init(&b->mutex, NULL)) != 0) + goto error2; + if ((rc = pthread_cond_init(&b->cond, NULL)) != 0) + goto error; + + barrier->b = b; + return 0; + +error: + pthread_mutex_destroy(&b->mutex); +error2: + uv__free(b); + return rc; +} + +int pthread_barrier_wait(pthread_barrier_t* barrier) { + int rc; + _uv_barrier* b; + + if (barrier == NULL || barrier->b == NULL) + return EINVAL; + + b = barrier->b; + /* Lock the mutex*/ + if ((rc = pthread_mutex_lock(&b->mutex)) != 0) + return rc; + + /* Increment the count. If this is the first thread to reach the threshold, + wake up waiters, unlock the mutex, then return + PTHREAD_BARRIER_SERIAL_THREAD. */ + if (++b->in == b->threshold) { + b->in = 0; + b->out = b->threshold - 1; + assert(pthread_cond_signal(&b->cond) == 0); + + pthread_mutex_unlock(&b->mutex); + return PTHREAD_BARRIER_SERIAL_THREAD; + } + /* Otherwise, wait for other threads until in is set to 0, + then return 0 to indicate this is not the first thread. */ + do { + if ((rc = pthread_cond_wait(&b->cond, &b->mutex)) != 0) + break; + } while (b->in != 0); + + /* mark thread exit */ + b->out--; + pthread_cond_signal(&b->cond); + pthread_mutex_unlock(&b->mutex); + return rc; +} + +int pthread_barrier_destroy(pthread_barrier_t* barrier) { + int rc; + _uv_barrier* b; + + if (barrier == NULL || barrier->b == NULL) + return EINVAL; + + b = barrier->b; + + if ((rc = pthread_mutex_lock(&b->mutex)) != 0) + return rc; + + if (b->in > 0 || b->out > 0) + rc = EBUSY; + + pthread_mutex_unlock(&b->mutex); + + if (rc) + return rc; + + pthread_cond_destroy(&b->cond); + pthread_mutex_destroy(&b->mutex); + uv__free(barrier->b); + barrier->b = NULL; + return 0; +} diff -Nru libuv1-1.8.0/src/unix/pthread-fixes.c libuv1-1.9.1/src/unix/pthread-fixes.c --- libuv1-1.8.0/src/unix/pthread-fixes.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/pthread-fixes.c 2016-05-16 21:22:19.000000000 +0000 @@ -29,76 +29,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Android versions < 4.1 have a broken pthread_sigmask. - * Note that this block of code must come before any inclusion of - * pthread-fixes.h so that the real pthread_sigmask can be referenced. - * */ +/* Android versions < 4.1 have a broken pthread_sigmask. */ #include #include #include int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset) { static int workaround; + int err; if (workaround) { return sigprocmask(how, set, oset); - } else if (pthread_sigmask(how, set, oset)) { - if (errno == EINVAL && sigprocmask(how, set, oset) == 0) { - workaround = 1; - return 0; - } else { - return -1; - } } else { - return 0; - } -} - -/*Android doesn't provide pthread_barrier_t for now.*/ -#ifndef PTHREAD_BARRIER_SERIAL_THREAD - -#include "pthread-fixes.h" - -int pthread_barrier_init(pthread_barrier_t* barrier, - const void* barrier_attr, - unsigned count) { - barrier->count = count; - pthread_mutex_init(&barrier->mutex, NULL); - pthread_cond_init(&barrier->cond, NULL); - return 0; -} - -int pthread_barrier_wait(pthread_barrier_t* barrier) { - /* Lock the mutex*/ - pthread_mutex_lock(&barrier->mutex); - /* Decrement the count. If this is the first thread to reach 0, wake up - waiters, unlock the mutex, then return PTHREAD_BARRIER_SERIAL_THREAD.*/ - if (--barrier->count == 0) { - /* First thread to reach the barrier */ - pthread_cond_broadcast(&barrier->cond); - pthread_mutex_unlock(&barrier->mutex); - return PTHREAD_BARRIER_SERIAL_THREAD; + err = pthread_sigmask(how, set, oset); + if (err) { + if (err == EINVAL && sigprocmask(how, set, oset) == 0) { + workaround = 1; + return 0; + } else { + return -1; + } + } } - /* Otherwise, wait for other threads until the count reaches 0, then - return 0 to indicate this is not the first thread.*/ - do { - pthread_cond_wait(&barrier->cond, &barrier->mutex); - } while (barrier->count > 0); - - pthread_mutex_unlock(&barrier->mutex); - return 0; -} - -int pthread_barrier_destroy(pthread_barrier_t *barrier) { - barrier->count = 0; - pthread_cond_destroy(&barrier->cond); - pthread_mutex_destroy(&barrier->mutex); - return 0; -} - -#endif /* defined(PTHREAD_BARRIER_SERIAL_THREAD) */ -int pthread_yield(void) { - sched_yield(); return 0; } diff -Nru libuv1-1.8.0/src/unix/signal.c libuv1-1.9.1/src/unix/signal.c --- libuv1-1.8.0/src/unix/signal.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/signal.c 2016-05-16 21:22:19.000000000 +0000 @@ -222,7 +222,7 @@ uv__io_init(&loop->signal_io_watcher, uv__signal_event, loop->signal_pipefd[0]); - uv__io_start(loop, &loop->signal_io_watcher, UV__POLLIN); + uv__io_start(loop, &loop->signal_io_watcher, POLLIN); return 0; } diff -Nru libuv1-1.8.0/src/unix/stream.c libuv1-1.9.1/src/unix/stream.c --- libuv1-1.8.0/src/unix/stream.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/stream.c 2016-05-16 21:22:19.000000000 +0000 @@ -159,9 +159,9 @@ memset(s->sread, 0, s->sread_sz); memset(s->swrite, 0, s->swrite_sz); - if (uv__io_active(&stream->io_watcher, UV__POLLIN)) + if (uv__io_active(&stream->io_watcher, POLLIN)) FD_SET(fd, s->sread); - if (uv__io_active(&stream->io_watcher, UV__POLLOUT)) + if (uv__io_active(&stream->io_watcher, POLLOUT)) FD_SET(fd, s->swrite); FD_SET(s->int_fd, s->sread); @@ -202,9 +202,9 @@ /* Handle events */ events = 0; if (FD_ISSET(fd, s->sread)) - events |= UV__POLLIN; + events |= POLLIN; if (FD_ISSET(fd, s->swrite)) - events |= UV__POLLOUT; + events |= POLLOUT; assert(events != 0 || FD_ISSET(s->int_fd, s->sread)); if (events != 0) { @@ -233,14 +233,14 @@ ACCESS_ONCE(int, s->events) = 0; assert(events != 0); - assert(events == (events & (UV__POLLIN | UV__POLLOUT))); + assert(events == (events & (POLLIN | POLLOUT))); /* Invoke callback on event-loop */ - if ((events & UV__POLLIN) && uv__io_active(&stream->io_watcher, UV__POLLIN)) - uv__stream_io(stream->loop, &stream->io_watcher, UV__POLLIN); + if ((events & POLLIN) && uv__io_active(&stream->io_watcher, POLLIN)) + uv__stream_io(stream->loop, &stream->io_watcher, POLLIN); - if ((events & UV__POLLOUT) && uv__io_active(&stream->io_watcher, UV__POLLOUT)) - uv__stream_io(stream->loop, &stream->io_watcher, UV__POLLOUT); + if ((events & POLLOUT) && uv__io_active(&stream->io_watcher, POLLOUT)) + uv__stream_io(stream->loop, &stream->io_watcher, POLLOUT); if (stream->flags & UV_CLOSING) return; @@ -437,7 +437,7 @@ void uv__stream_destroy(uv_stream_t* stream) { - assert(!uv__io_active(&stream->io_watcher, UV__POLLIN | UV__POLLOUT)); + assert(!uv__io_active(&stream->io_watcher, POLLIN | POLLOUT)); assert(stream->flags & UV_CLOSED); if (stream->connect_req) { @@ -511,11 +511,11 @@ int err; stream = container_of(w, uv_stream_t, io_watcher); - assert(events == UV__POLLIN); + assert(events == POLLIN); assert(stream->accepted_fd == -1); assert(!(stream->flags & UV_CLOSING)); - uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN); + uv__io_start(stream->loop, &stream->io_watcher, POLLIN); /* connection_cb can close the server socket while we're * in the loop so check it on each iteration. @@ -552,7 +552,7 @@ if (stream->accepted_fd != -1) { /* The user hasn't yet accepted called uv_accept() */ - uv__io_stop(loop, &stream->io_watcher, UV__POLLIN); + uv__io_stop(loop, &stream->io_watcher, POLLIN); return; } @@ -626,7 +626,7 @@ } else { server->accepted_fd = -1; if (err == 0) - uv__io_start(server->loop, &server->io_watcher, UV__POLLIN); + uv__io_start(server->loop, &server->io_watcher, POLLIN); } return err; } @@ -660,7 +660,7 @@ int err; assert(QUEUE_EMPTY(&stream->write_queue)); - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); + uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); uv__stream_osx_interrupt_select(stream); /* Shutdown? */ @@ -846,8 +846,8 @@ /* Error */ req->error = -errno; uv__write_req_finish(req); - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); - if (!uv__io_active(&stream->io_watcher, UV__POLLIN)) + uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); + if (!uv__io_active(&stream->io_watcher, POLLIN)) uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); return; @@ -910,7 +910,7 @@ assert(!(stream->flags & UV_STREAM_BLOCKING)); /* We're not done. */ - uv__io_start(stream->loop, &stream->io_watcher, UV__POLLOUT); + uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); /* Notify select() thread about state change */ uv__stream_osx_interrupt_select(stream); @@ -946,13 +946,14 @@ uv_handle_type uv__handle_type(int fd) { struct sockaddr_storage ss; + socklen_t sslen; socklen_t len; int type; memset(&ss, 0, sizeof(ss)); - len = sizeof(ss); + sslen = sizeof(ss); - if (getsockname(fd, (struct sockaddr*)&ss, &len)) + if (getsockname(fd, (struct sockaddr*)&ss, &sslen)) return UV_UNKNOWN_HANDLE; len = sizeof type; @@ -961,6 +962,14 @@ return UV_UNKNOWN_HANDLE; if (type == SOCK_STREAM) { +#if defined(_AIX) + /* on AIX the getsockname call returns an empty sa structure + * for sockets of type AF_UNIX. For all other types it will + * return a properly filled in structure. + */ + if (sslen == 0) + return UV_NAMED_PIPE; +#endif switch (ss.ss_family) { case AF_UNIX: return UV_NAMED_PIPE; @@ -980,8 +989,8 @@ static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) { stream->flags |= UV_STREAM_READ_EOF; - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN); - if (!uv__io_active(&stream->io_watcher, UV__POLLOUT)) + uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); + if (!uv__io_active(&stream->io_watcher, POLLOUT)) uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); stream->read_cb(stream, UV_EOF, buf); @@ -1082,6 +1091,11 @@ } +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-folding-constant" +#endif + static void uv__read(uv_stream_t* stream) { uv_buf_t buf; ssize_t nread; @@ -1145,7 +1159,7 @@ if (errno == EAGAIN || errno == EWOULDBLOCK) { /* Wait for the next one. */ if (stream->flags & UV_STREAM_READING) { - uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN); + uv__io_start(stream->loop, &stream->io_watcher, POLLIN); uv__stream_osx_interrupt_select(stream); } stream->read_cb(stream, 0, &buf); @@ -1154,8 +1168,8 @@ stream->read_cb(stream, -errno, &buf); if (stream->flags & UV_STREAM_READING) { stream->flags &= ~UV_STREAM_READING; - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN); - if (!uv__io_active(&stream->io_watcher, UV__POLLOUT)) + uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); + if (!uv__io_active(&stream->io_watcher, POLLOUT)) uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); } @@ -1187,6 +1201,10 @@ } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + #undef UV__CMSG_FD_COUNT #undef UV__CMSG_FD_SIZE @@ -1212,7 +1230,7 @@ stream->shutdown_req = req; stream->flags |= UV_STREAM_SHUTTING; - uv__io_start(stream->loop, &stream->io_watcher, UV__POLLOUT); + uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); uv__stream_osx_interrupt_select(stream); return 0; @@ -1237,7 +1255,7 @@ assert(uv__stream_fd(stream) >= 0); /* Ignore POLLHUP here. Even it it's set, there may still be data to read. */ - if (events & (UV__POLLIN | UV__POLLERR | UV__POLLHUP)) + if (events & (POLLIN | POLLERR | POLLHUP)) uv__read(stream); if (uv__stream_fd(stream) == -1) @@ -1249,7 +1267,7 @@ * have to do anything. If the partial read flag is not set, we can't * report the EOF yet because there is still data to read. */ - if ((events & UV__POLLHUP) && + if ((events & POLLHUP) && (stream->flags & UV_STREAM_READING) && (stream->flags & UV_STREAM_READ_PARTIAL) && !(stream->flags & UV_STREAM_READ_EOF)) { @@ -1260,7 +1278,7 @@ if (uv__stream_fd(stream) == -1) return; /* read_cb closed stream. */ - if (events & (UV__POLLOUT | UV__POLLERR | UV__POLLHUP)) { + if (events & (POLLOUT | POLLERR | POLLHUP)) { uv__write(stream); uv__write_callbacks(stream); @@ -1309,7 +1327,7 @@ uv__req_unregister(stream->loop, req); if (error < 0 || QUEUE_EMPTY(&stream->write_queue)) { - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); + uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); } if (req->cb) @@ -1404,7 +1422,7 @@ * sufficiently flushed in uv__write. */ assert(!(stream->flags & UV_STREAM_BLOCKING)); - uv__io_start(stream->loop, &stream->io_watcher, UV__POLLOUT); + uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); uv__stream_osx_interrupt_select(stream); } @@ -1443,7 +1461,7 @@ if (stream->connect_req != NULL || stream->write_queue_size != 0) return -EAGAIN; - has_pollout = uv__io_active(&stream->io_watcher, UV__POLLOUT); + has_pollout = uv__io_active(&stream->io_watcher, POLLOUT); r = uv_write(&req, stream, bufs, nbufs, uv_try_write_cb); if (r != 0) @@ -1467,7 +1485,7 @@ /* 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); + uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); uv__stream_osx_interrupt_select(stream); } @@ -1502,7 +1520,7 @@ stream->read_cb = read_cb; stream->alloc_cb = alloc_cb; - uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN); + uv__io_start(stream->loop, &stream->io_watcher, POLLIN); uv__handle_start(stream); uv__stream_osx_interrupt_select(stream); @@ -1515,8 +1533,8 @@ return 0; stream->flags &= ~UV_STREAM_READING; - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN); - if (!uv__io_active(&stream->io_watcher, UV__POLLOUT)) + uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); + if (!uv__io_active(&stream->io_watcher, POLLOUT)) uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); @@ -1603,7 +1621,7 @@ handle->queued_fds = NULL; } - assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT)); + assert(!uv__io_active(&handle->io_watcher, POLLIN | POLLOUT)); } diff -Nru libuv1-1.8.0/src/unix/sunos.c libuv1-1.9.1/src/unix/sunos.c --- libuv1-1.8.0/src/unix/sunos.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/sunos.c 2016-05-16 21:22:19.000000000 +0000 @@ -116,6 +116,17 @@ } +int uv__io_check_fd(uv_loop_t* loop, int fd) { + if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0)) + return -errno; + + if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd)) + abort(); + + return 0; +} + + void uv__io_poll(uv_loop_t* loop, int timeout) { struct port_event events[1024]; struct port_event* pe; @@ -129,6 +140,7 @@ unsigned int nfds; unsigned int i; int saved_errno; + int have_signals; int nevents; int count; int err; @@ -219,6 +231,7 @@ return; } + have_signals = 0; nevents = 0; assert(loop->watchers != NULL); @@ -241,7 +254,14 @@ if (w == NULL) continue; - w->cb(loop, w, pe->portev_events); + /* Run signal watchers last. This also affects child process watchers + * because those are implemented in terms of signal watchers. + */ + if (w == &loop->signal_io_watcher) + have_signals = 1; + else + w->cb(loop, w, pe->portev_events); + nevents++; if (w != loop->watchers[fd]) @@ -251,9 +271,16 @@ if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue)) QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); } + + if (have_signals != 0) + loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); + loop->watchers[loop->nwatchers] = NULL; loop->watchers[loop->nwatchers + 1] = NULL; + if (have_signals != 0) + return; /* Event loop should cycle now so don't poll again. */ + if (nevents != 0) { if (nfds == ARRAY_SIZE(events) && --count != 0) { /* Poll for more events but don't block this time. */ @@ -445,7 +472,7 @@ if (first_run) { uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd); - uv__io_start(handle->loop, &handle->loop->fs_event_watcher, UV__POLLIN); + uv__io_start(handle->loop, &handle->loop->fs_event_watcher, POLLIN); } return 0; diff -Nru libuv1-1.8.0/src/unix/tcp.c libuv1-1.9.1/src/unix/tcp.c --- libuv1-1.8.0/src/unix/tcp.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/tcp.c 2016-05-16 21:22:19.000000000 +0000 @@ -181,7 +181,7 @@ QUEUE_INIT(&req->queue); handle->connect_req = req; - uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT); + uv__io_start(handle->loop, &handle->io_watcher, POLLOUT); if (handle->delayed_error) uv__io_feed(handle->loop, &handle->io_watcher); @@ -273,7 +273,7 @@ /* Start listening for connections. */ tcp->io_watcher.cb = uv__server_io; - uv__io_start(tcp->loop, &tcp->io_watcher, UV__POLLIN); + uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN); return 0; } diff -Nru libuv1-1.8.0/src/unix/thread.c libuv1-1.9.1/src/unix/thread.c --- libuv1-1.8.0/src/unix/thread.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/thread.c 2016-05-16 21:22:19.000000000 +0000 @@ -27,11 +27,14 @@ #include #include +#include /* getrlimit() */ +#include /* getpagesize() */ + +#include #undef NANOSEC #define NANOSEC ((uint64_t) 1e9) - struct thread_ctx { void (*entry)(void* arg); void* arg; @@ -55,6 +58,11 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { struct thread_ctx* ctx; int err; + pthread_attr_t* attr; +#if defined(__APPLE__) + pthread_attr_t attr_storage; + struct rlimit lim; +#endif ctx = uv__malloc(sizeof(*ctx)); if (ctx == NULL) @@ -63,7 +71,33 @@ ctx->entry = entry; ctx->arg = arg; - err = pthread_create(tid, NULL, uv__thread_start, ctx); + /* On OSX threads other than the main thread are created with a reduced stack + * size by default, adjust it to RLIMIT_STACK. + */ +#if defined(__APPLE__) + if (getrlimit(RLIMIT_STACK, &lim)) + abort(); + + attr = &attr_storage; + if (pthread_attr_init(attr)) + abort(); + + if (lim.rlim_cur != RLIM_INFINITY) { + /* pthread_attr_setstacksize() expects page-aligned values. */ + lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize(); + + if (lim.rlim_cur >= PTHREAD_STACK_MIN) + if (pthread_attr_setstacksize(attr, lim.rlim_cur)) + abort(); + } +#else + attr = NULL; +#endif + + err = pthread_create(tid, attr, uv__thread_start, ctx); + + if (attr != NULL) + pthread_attr_destroy(attr); if (err) uv__free(ctx); @@ -362,6 +396,35 @@ #endif /* defined(__APPLE__) && defined(__MACH__) */ void uv_cond_destroy(uv_cond_t* cond) { +#if defined(__APPLE__) && defined(__MACH__) + /* It has been reported that destroying condition variables that have been + * signalled but not waited on can sometimes result in application crashes. + * See https://codereview.chromium.org/1323293005. + */ + pthread_mutex_t mutex; + struct timespec ts; + int err; + + if (pthread_mutex_init(&mutex, NULL)) + abort(); + + if (pthread_mutex_lock(&mutex)) + abort(); + + ts.tv_sec = 0; + ts.tv_nsec = 1; + + err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts); + if (err != 0 && err != ETIMEDOUT) + abort(); + + if (pthread_mutex_unlock(&mutex)) + abort(); + + if (pthread_mutex_destroy(&mutex)) + abort(); +#endif /* defined(__APPLE__) && defined(__MACH__) */ + if (pthread_cond_destroy(cond)) abort(); } @@ -417,72 +480,6 @@ } -#if defined(__APPLE__) && defined(__MACH__) - -int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { - int err; - - barrier->n = count; - barrier->count = 0; - - err = uv_mutex_init(&barrier->mutex); - if (err) - return -err; - - err = uv_sem_init(&barrier->turnstile1, 0); - if (err) - goto error2; - - err = uv_sem_init(&barrier->turnstile2, 1); - if (err) - goto error; - - return 0; - -error: - uv_sem_destroy(&barrier->turnstile1); -error2: - uv_mutex_destroy(&barrier->mutex); - return -err; - -} - - -void uv_barrier_destroy(uv_barrier_t* barrier) { - uv_sem_destroy(&barrier->turnstile2); - uv_sem_destroy(&barrier->turnstile1); - uv_mutex_destroy(&barrier->mutex); -} - - -int uv_barrier_wait(uv_barrier_t* barrier) { - int serial_thread; - - uv_mutex_lock(&barrier->mutex); - if (++barrier->count == barrier->n) { - uv_sem_wait(&barrier->turnstile2); - uv_sem_post(&barrier->turnstile1); - } - uv_mutex_unlock(&barrier->mutex); - - uv_sem_wait(&barrier->turnstile1); - uv_sem_post(&barrier->turnstile1); - - uv_mutex_lock(&barrier->mutex); - serial_thread = (--barrier->count == 0); - if (serial_thread) { - uv_sem_wait(&barrier->turnstile1); - uv_sem_post(&barrier->turnstile2); - } - uv_mutex_unlock(&barrier->mutex); - - uv_sem_wait(&barrier->turnstile2); - uv_sem_post(&barrier->turnstile2); - return serial_thread; -} - -#else /* !(defined(__APPLE__) && defined(__MACH__)) */ - int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { return -pthread_barrier_init(barrier, NULL, count); } @@ -501,7 +498,6 @@ return r == PTHREAD_BARRIER_SERIAL_THREAD; } -#endif /* defined(__APPLE__) && defined(__MACH__) */ int uv_key_create(uv_key_t* key) { return -pthread_key_create(key, NULL); diff -Nru libuv1-1.8.0/src/unix/tty.c libuv1-1.9.1/src/unix/tty.c --- libuv1-1.8.0/src/unix/tty.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/tty.c 2016-05-16 21:22:19.000000000 +0000 @@ -23,6 +23,7 @@ #include "internal.h" #include "spinlock.h" +#include #include #include #include @@ -33,12 +34,30 @@ static struct termios orig_termios; static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER; +static int uv__tty_is_slave(const int fd) { + int result; +#if defined(__linux__) || defined(__FreeBSD__) + int dummy; + + result = ioctl(fd, TIOCGPTN, &dummy) != 0; +#elif defined(__APPLE__) + char dummy[256]; + + result = ioctl(fd, TIOCPTYGNAME, &dummy) != 0; +#else + /* Fallback to ptsname + */ + result = ptsname(fd) == NULL; +#endif + return result; +} 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; + char path[256]; /* File descriptors that refer to files cannot be monitored with epoll. * That restriction also applies to character devices like /dev/random @@ -62,7 +81,15 @@ * other processes. */ if (type == UV_TTY) { - r = uv__open_cloexec("/dev/tty", O_RDWR); + /* Reopening a pty in master mode won't work either because the reopened + * pty will be in slave mode (*BSD) or reopening will allocate a new + * master/slave pair (Linux). Therefore check if the fd points to a + * slave device. + */ + if (uv__tty_is_slave(fd) && ttyname_r(fd, path, sizeof(path)) == 0) + r = uv__open_cloexec(path, O_RDWR); + else + r = -1; if (r < 0) { /* fallback to using blocking writes */ @@ -185,8 +212,13 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) { struct winsize ws; + int err; + + do + err = ioctl(uv__stream_fd(tty), TIOCGWINSZ, &ws); + while (err == -1 && errno == EINTR); - if (ioctl(uv__stream_fd(tty), TIOCGWINSZ, &ws)) + if (err == -1) return -errno; *width = ws.ws_col; diff -Nru libuv1-1.8.0/src/unix/udp.c libuv1-1.9.1/src/unix/udp.c --- libuv1-1.8.0/src/unix/udp.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/unix/udp.c 2016-05-16 21:22:19.000000000 +0000 @@ -61,7 +61,7 @@ uv_udp_send_t* req; QUEUE* q; - assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT)); + assert(!uv__io_active(&handle->io_watcher, POLLIN | POLLOUT)); assert(handle->io_watcher.fd == -1); while (!QUEUE_EMPTY(&handle->write_queue)) { @@ -120,8 +120,8 @@ if (QUEUE_EMPTY(&handle->write_queue)) { /* Pending queue and completion queue empty, stop watcher. */ - uv__io_stop(handle->loop, &handle->io_watcher, UV__POLLOUT); - if (!uv__io_active(&handle->io_watcher, UV__POLLIN)) + uv__io_stop(handle->loop, &handle->io_watcher, POLLOUT); + if (!uv__io_active(&handle->io_watcher, POLLIN)) uv__handle_stop(handle); } @@ -135,10 +135,10 @@ handle = container_of(w, uv_udp_t, io_watcher); assert(handle->type == UV_UDP); - if (revents & UV__POLLIN) + if (revents & POLLIN) uv__udp_recvmsg(handle); - if (revents & UV__POLLOUT) { + if (revents & POLLOUT) { uv__udp_sendmsg(handle); uv__udp_run_completed(handle); } @@ -424,7 +424,7 @@ if (empty_queue && !(handle->flags & UV_UDP_PROCESSING)) { uv__udp_sendmsg(handle); } else { - uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT); + uv__io_start(handle->loop, &handle->io_watcher, POLLOUT); } return 0; @@ -843,7 +843,7 @@ if (alloc_cb == NULL || recv_cb == NULL) return -EINVAL; - if (uv__io_active(&handle->io_watcher, UV__POLLIN)) + if (uv__io_active(&handle->io_watcher, POLLIN)) return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */ err = uv__udp_maybe_deferred_bind(handle, AF_INET, 0); @@ -853,7 +853,7 @@ handle->alloc_cb = alloc_cb; handle->recv_cb = recv_cb; - uv__io_start(handle->loop, &handle->io_watcher, UV__POLLIN); + uv__io_start(handle->loop, &handle->io_watcher, POLLIN); uv__handle_start(handle); return 0; @@ -861,9 +861,9 @@ int uv__udp_recv_stop(uv_udp_t* handle) { - uv__io_stop(handle->loop, &handle->io_watcher, UV__POLLIN); + uv__io_stop(handle->loop, &handle->io_watcher, POLLIN); - if (!uv__io_active(&handle->io_watcher, UV__POLLOUT)) + if (!uv__io_active(&handle->io_watcher, POLLOUT)) uv__handle_stop(handle); handle->alloc_cb = NULL; diff -Nru libuv1-1.8.0/src/uv-common.c libuv1-1.9.1/src/uv-common.c --- libuv1-1.8.0/src/uv-common.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/uv-common.c 2016-05-16 21:22:19.000000000 +0000 @@ -22,10 +22,11 @@ #include "uv.h" #include "uv-common.h" -#include #include +#include #include #include /* NULL */ +#include #include /* malloc */ #include /* memset */ @@ -75,7 +76,14 @@ } void uv__free(void* ptr) { + int saved_errno; + + /* Libuv expects that free() does not clobber errno. The system allocator + * honors that assumption but custom allocators may not be so careful. + */ + saved_errno = errno; uv__allocator.local_free(ptr); + errno = saved_errno; } void* uv__calloc(size_t count, size_t size) { @@ -451,13 +459,14 @@ } required_len = strlen(handle->path); - if (required_len > *size) { - *size = required_len; + if (required_len >= *size) { + *size = required_len + 1; return UV_ENOBUFS; } memcpy(buffer, handle->path, required_len); *size = required_len; + buffer[required_len] = '\0'; return 0; } @@ -474,6 +483,16 @@ #endif } +/* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows + * systems. So, the memory should be released using free(). On Windows, + * uv__malloc() is used, so use uv__free() to free memory. +*/ +#ifdef _WIN32 +# define uv__fs_scandir_free uv__free +#else +# define uv__fs_scandir_free free +#endif + void uv__fs_scandir_cleanup(uv_fs_t* req) { uv__dirent_t** dents; @@ -483,7 +502,10 @@ if (*nbufs > 0 && *nbufs != (unsigned int) req->result) (*nbufs)--; for (; *nbufs < (unsigned int) req->result; (*nbufs)++) - uv__free(dents[*nbufs]); + uv__fs_scandir_free(dents[*nbufs]); + + uv__fs_scandir_free(req->ptr); + req->ptr = NULL; } @@ -497,11 +519,11 @@ /* Free previous entity */ if (*nbufs > 0) - uv__free(dents[*nbufs - 1]); + uv__fs_scandir_free(dents[*nbufs - 1]); /* End was already reached */ if (*nbufs == (unsigned int) req->result) { - uv__free(dents); + uv__fs_scandir_free(dents); req->ptr = NULL; return UV_EOF; } diff -Nru libuv1-1.8.0/src/win/core.c libuv1-1.9.1/src/win/core.c --- libuv1-1.8.0/src/win/core.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/win/core.c 2016-05-16 21:22:19.000000000 +0000 @@ -256,30 +256,48 @@ ULONG_PTR key; OVERLAPPED* overlapped; uv_req_t* req; + int repeat; + uint64_t timeout_time; - GetQueuedCompletionStatus(loop->iocp, - &bytes, - &key, - &overlapped, - timeout); - - if (overlapped) { - /* Package was dequeued */ - req = uv_overlapped_to_req(overlapped); - uv_insert_pending_req(loop, req); - - /* Some time might have passed waiting for I/O, - * so update the loop time here. - */ - uv_update_time(loop); - } else if (GetLastError() != WAIT_TIMEOUT) { - /* Serious error */ - uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus"); - } else if (timeout > 0) { - /* GetQueuedCompletionStatus can occasionally return a little early. - * Make sure that the desired timeout is reflected in the loop time. - */ - uv__time_forward(loop, timeout); + timeout_time = loop->time + timeout; + + for (repeat = 0; ; repeat++) { + GetQueuedCompletionStatus(loop->iocp, + &bytes, + &key, + &overlapped, + timeout); + + if (overlapped) { + /* Package was dequeued */ + req = uv_overlapped_to_req(overlapped); + uv_insert_pending_req(loop, req); + + /* Some time might have passed waiting for I/O, + * so update the loop time here. + */ + uv_update_time(loop); + } else if (GetLastError() != WAIT_TIMEOUT) { + /* Serious error */ + uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus"); + } else if (timeout > 0) { + /* GetQueuedCompletionStatus can occasionally return a little early. + * Make sure that the desired timeout target time is reached. + */ + uv_update_time(loop); + if (timeout_time > loop->time) { + timeout = (DWORD)(timeout_time - loop->time); + /* The first call to GetQueuedCompletionStatus should return very + * close to the target time and the second should reach it, but + * this is not stated in the documentation. To make sure a busy + * loop cannot happen, the timeout is increased exponentially + * starting on the third round. + */ + timeout += repeat ? (1 << (repeat - 1)) : 0; + continue; + } + } + break; } } @@ -290,33 +308,51 @@ OVERLAPPED_ENTRY overlappeds[128]; ULONG count; ULONG i; + int repeat; + uint64_t timeout_time; - success = pGetQueuedCompletionStatusEx(loop->iocp, - overlappeds, - ARRAY_SIZE(overlappeds), - &count, - timeout, - FALSE); + timeout_time = loop->time + timeout; - if (success) { - for (i = 0; i < count; i++) { - /* Package was dequeued */ - req = uv_overlapped_to_req(overlappeds[i].lpOverlapped); - uv_insert_pending_req(loop, req); + for (repeat = 0; ; repeat++) { + success = pGetQueuedCompletionStatusEx(loop->iocp, + overlappeds, + ARRAY_SIZE(overlappeds), + &count, + timeout, + FALSE); + + if (success) { + for (i = 0; i < count; i++) { + /* Package was dequeued */ + req = uv_overlapped_to_req(overlappeds[i].lpOverlapped); + uv_insert_pending_req(loop, req); + } + + /* Some time might have passed waiting for I/O, + * so update the loop time here. + */ + uv_update_time(loop); + } else if (GetLastError() != WAIT_TIMEOUT) { + /* Serious error */ + uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx"); + } else if (timeout > 0) { + /* GetQueuedCompletionStatus can occasionally return a little early. + * Make sure that the desired timeout target time is reached. + */ + uv_update_time(loop); + if (timeout_time > loop->time) { + timeout = (DWORD)(timeout_time - loop->time); + /* The first call to GetQueuedCompletionStatus should return very + * close to the target time and the second should reach it, but + * this is not stated in the documentation. To make sure a busy + * loop cannot happen, the timeout is increased exponentially + * starting on the third round. + */ + timeout += repeat ? (1 << (repeat - 1)) : 0; + continue; + } } - - /* Some time might have passed waiting for I/O, - * so update the loop time here. - */ - uv_update_time(loop); - } else if (GetLastError() != WAIT_TIMEOUT) { - /* Serious error */ - uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx"); - } else if (timeout > 0) { - /* GetQueuedCompletionStatus can occasionally return a little early. - * Make sure that the desired timeout is reflected in the loop time. - */ - uv__time_forward(loop, timeout); + break; } } diff -Nru libuv1-1.8.0/src/win/dl.c libuv1-1.9.1/src/win/dl.c --- libuv1-1.8.0/src/win/dl.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/win/dl.c 2016-05-16 21:22:19.000000000 +0000 @@ -31,7 +31,12 @@ lib->handle = NULL; lib->errmsg = NULL; - if (!uv_utf8_to_utf16(filename, filename_w, ARRAY_SIZE(filename_w))) { + if (!MultiByteToWideChar(CP_UTF8, + 0, + filename, + -1, + filename_w, + ARRAY_SIZE(filename_w))) { return uv__dlerror(lib, GetLastError()); } diff -Nru libuv1-1.8.0/src/win/fs.c libuv1-1.9.1/src/win/fs.c --- libuv1-1.8.0/src/win/fs.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/win/fs.c 2016-05-16 21:22:19.000000000 +0000 @@ -901,7 +901,15 @@ /* Compute the length of the filename in WCHARs. */ wchar_len = info->FileNameLength / sizeof info->FileName[0]; - /* Skip over '.' and '..' entries. */ + /* Skip over '.' and '..' entries. It has been reported that + * the SharePoint driver includes the terminating zero byte in + * the filename length. Strip those first. + */ + while (wchar_len > 0 && info->FileName[wchar_len - 1] == L'\0') + wchar_len -= 1; + + if (wchar_len == 0) + continue; if (wchar_len == 1 && info->FileName[0] == L'.') continue; if (wchar_len == 2 && info->FileName[0] == L'.' && @@ -1717,25 +1725,26 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { int r; DWORD w_realpath_len; - WCHAR* w_realpath_ptr; - WCHAR* w_finalpath_ptr = NULL; + WCHAR* w_realpath_ptr = NULL; + WCHAR* w_realpath_buf; w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS); if (w_realpath_len == 0) { return -1; } - w_realpath_ptr = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR)); - if (w_realpath_ptr == NULL) { + w_realpath_buf = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR)); + if (w_realpath_buf == NULL) { SetLastError(ERROR_OUTOFMEMORY); return -1; } + w_realpath_ptr = w_realpath_buf; if (pGetFinalPathNameByHandleW(handle, w_realpath_ptr, w_realpath_len, VOLUME_NAME_DOS) == 0) { - uv__free(w_realpath_ptr); + uv__free(w_realpath_buf); SetLastError(ERROR_INVALID_HANDLE); return -1; } @@ -1744,20 +1753,22 @@ if (wcsncmp(w_realpath_ptr, UNC_PATH_PREFIX, UNC_PATH_PREFIX_LEN) == 0) { - w_finalpath_ptr = w_realpath_ptr + 6; - *w_finalpath_ptr = L'\\'; + w_realpath_ptr += 6; + *w_realpath_ptr = L'\\'; + w_realpath_len -= 6; } else if (wcsncmp(w_realpath_ptr, LONG_PATH_PREFIX, LONG_PATH_PREFIX_LEN) == 0) { - w_finalpath_ptr = w_realpath_ptr + 4; + w_realpath_ptr += 4; + w_realpath_len -= 4; } else { - uv__free(w_realpath_ptr); + uv__free(w_realpath_buf); SetLastError(ERROR_INVALID_HANDLE); return -1; } - r = fs__wide_to_utf8(w_finalpath_ptr, w_realpath_len, realpath_ptr, NULL); - uv__free(w_realpath_ptr); + r = fs__wide_to_utf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL); + uv__free(w_realpath_buf); return r; } @@ -1867,8 +1878,12 @@ if (req->flags & UV_FS_FREE_PATHS) uv__free(req->file.pathw); - if (req->flags & UV_FS_FREE_PTR) - uv__free(req->ptr); + if (req->flags & UV_FS_FREE_PTR) { + if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL) + uv__fs_scandir_cleanup(req); + else + uv__free(req->ptr); + } req->path = NULL; req->file.pathw = NULL; diff -Nru libuv1-1.8.0/src/win/fs-event.c libuv1-1.9.1/src/win/fs-event.c --- libuv1-1.8.0/src/win/fs-event.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/win/fs-event.c 2016-05-16 21:22:19.000000000 +0000 @@ -63,19 +63,20 @@ handle->req_pending = 1; } -static int uv_relative_path(const WCHAR* filename, - const WCHAR* dir, - WCHAR** relpath) { - int dirlen = wcslen(dir); - int filelen = wcslen(filename); - if (dir[dirlen - 1] == '\\') +static void uv_relative_path(const WCHAR* filename, + const WCHAR* dir, + WCHAR** relpath) { + size_t relpathlen; + size_t filenamelen = wcslen(filename); + size_t dirlen = wcslen(dir); + if (dirlen > 0 && dir[dirlen - 1] == '\\') dirlen--; - *relpath = uv__malloc((MAX_PATH + 1) * sizeof(WCHAR)); + relpathlen = filenamelen - dirlen - 1; + *relpath = uv__malloc((relpathlen + 1) * sizeof(WCHAR)); if (!*relpath) uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - wcsncpy(*relpath, filename + dirlen + 1, filelen - dirlen - 1); - (*relpath)[filelen - dirlen - 1] = L'\0'; - return 0; + wcsncpy(*relpath, filename + dirlen + 1, relpathlen); + (*relpath)[relpathlen] = L'\0'; } static int uv_split_path(const WCHAR* filename, WCHAR** dir, @@ -101,12 +102,12 @@ *file = wcsdup(filename); } else { if (dir) { - *dir = (WCHAR*)uv__malloc((i + 1) * sizeof(WCHAR)); + *dir = (WCHAR*)uv__malloc((i + 2) * sizeof(WCHAR)); if (!*dir) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } - wcsncpy(*dir, filename, i); - (*dir)[i] = L'\0'; + wcsncpy(*dir, filename, i + 1); + (*dir)[i + 1] = L'\0'; } *file = (WCHAR*)uv__malloc((len - i) * sizeof(WCHAR)); @@ -159,14 +160,20 @@ uv__handle_start(handle); /* Convert name to UTF16. */ - name_size = uv_utf8_to_utf16(path, NULL, 0) * sizeof(WCHAR); + + name_size = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0) * + sizeof(WCHAR); pathw = (WCHAR*)uv__malloc(name_size); if (!pathw) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } - if (!uv_utf8_to_utf16(path, pathw, - name_size / sizeof(WCHAR))) { + if (!MultiByteToWideChar(CP_UTF8, + 0, + path, + -1, + pathw, + name_size / sizeof(WCHAR))) { return uv_translate_sys_error(GetLastError()); } @@ -340,9 +347,10 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, uv_fs_event_t* handle) { FILE_NOTIFY_INFORMATION* file_info; - int err, sizew, size, result; + int err, sizew, size; char* filename = NULL; - WCHAR* filenamew, *long_filenamew = NULL; + WCHAR* filenamew = NULL; + WCHAR* long_filenamew = NULL; DWORD offset = 0; assert(req->type == UV_FS_EVENT_REQ); @@ -367,6 +375,7 @@ do { file_info = (FILE_NOTIFY_INFORMATION*)((char*)file_info + offset); assert(!filename); + assert(!filenamew); assert(!long_filenamew); /* @@ -425,25 +434,14 @@ if (long_filenamew) { /* Get the file name out of the long path. */ - result = uv_relative_path(long_filenamew, - handle->dirw, - &filenamew); + uv_relative_path(long_filenamew, + handle->dirw, + &filenamew); uv__free(long_filenamew); - - if (result == 0) { - long_filenamew = filenamew; - sizew = -1; - } else { - long_filenamew = NULL; - } - } - - /* - * We could not resolve the long form explicitly. - * We therefore use the name given by ReadDirectoryChangesW. - * This may be the long form or the 8.3 short name in some cases. - */ - if (!long_filenamew) { + long_filenamew = filenamew; + sizew = -1; + } else { + /* We couldn't get the long filename, use the one reported. */ filenamew = file_info->FileName; sizew = file_info->FileNameLength / sizeof(WCHAR); } @@ -453,10 +451,8 @@ * We therefore use the name given by ReadDirectoryChangesW. * This may be the long form or the 8.3 short name in some cases. */ - if (!long_filenamew) { - filenamew = file_info->FileName; - sizew = file_info->FileNameLength / sizeof(WCHAR); - } + filenamew = file_info->FileName; + sizew = file_info->FileNameLength / sizeof(WCHAR); } } else { /* We already have the long name of the file, so just use it. */ @@ -464,30 +460,8 @@ sizew = -1; } - if (filenamew) { - /* Convert the filename to utf8. */ - size = uv_utf16_to_utf8(filenamew, - sizew, - NULL, - 0); - if (size) { - filename = (char*)uv__malloc(size + 1); - if (!filename) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - size = uv_utf16_to_utf8(filenamew, - sizew, - filename, - size); - if (size) { - filename[size] = '\0'; - } else { - uv__free(filename); - filename = NULL; - } - } - } + /* Convert the filename to utf8. */ + uv__convert_utf16_to_utf8(filenamew, sizew, &filename); switch (file_info->Action) { case FILE_ACTION_ADDED: @@ -506,6 +480,7 @@ filename = NULL; uv__free(long_filenamew); long_filenamew = NULL; + filenamew = NULL; } offset = file_info->NextEntryOffset; diff -Nru libuv1-1.8.0/src/win/getaddrinfo.c libuv1-1.9.1/src/win/getaddrinfo.c --- libuv1-1.8.0/src/win/getaddrinfo.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/win/getaddrinfo.c 2016-05-16 21:22:19.000000000 +0000 @@ -126,7 +126,14 @@ addrinfo_len += addrinfo_struct_len + ALIGNED_SIZE(addrinfow_ptr->ai_addrlen); if (addrinfow_ptr->ai_canonname != NULL) { - name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, -1, NULL, 0); + name_len = WideCharToMultiByte(CP_UTF8, + 0, + addrinfow_ptr->ai_canonname, + -1, + NULL, + 0, + NULL, + NULL); if (name_len == 0) { req->retcode = uv_translate_sys_error(GetLastError()); goto complete; @@ -170,16 +177,24 @@ /* convert canonical name to UTF-8 */ if (addrinfow_ptr->ai_canonname != NULL) { - name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, - -1, - NULL, - 0); + name_len = WideCharToMultiByte(CP_UTF8, + 0, + addrinfow_ptr->ai_canonname, + -1, + NULL, + 0, + NULL, + NULL); assert(name_len > 0); assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len); - name_len = uv_utf16_to_utf8(addrinfow_ptr->ai_canonname, - -1, - cur_ptr, - name_len); + name_len = WideCharToMultiByte(CP_UTF8, + 0, + addrinfow_ptr->ai_canonname, + -1, + cur_ptr, + name_len, + NULL, + NULL); assert(name_len > 0); addrinfo_ptr->ai_canonname = cur_ptr; cur_ptr += ALIGNED_SIZE(name_len); @@ -261,7 +276,8 @@ /* calculate required memory size for all input values */ if (node != NULL) { - nodesize = ALIGNED_SIZE(uv_utf8_to_utf16(node, NULL, 0) * sizeof(WCHAR)); + nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, node, -1, NULL, 0) * + sizeof(WCHAR)); if (nodesize == 0) { err = GetLastError(); goto error; @@ -269,7 +285,12 @@ } if (service != NULL) { - servicesize = ALIGNED_SIZE(uv_utf8_to_utf16(service, NULL, 0) * + servicesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, + 0, + service, + -1, + NULL, + 0) * sizeof(WCHAR)); if (servicesize == 0) { err = GetLastError(); @@ -294,9 +315,12 @@ /* the request. */ if (node != NULL) { req->node = (WCHAR*)alloc_ptr; - if (uv_utf8_to_utf16(node, - (WCHAR*) alloc_ptr, - nodesize / sizeof(WCHAR)) == 0) { + if (MultiByteToWideChar(CP_UTF8, + 0, + node, + -1, + (WCHAR*) alloc_ptr, + nodesize / sizeof(WCHAR)) == 0) { err = GetLastError(); goto error; } @@ -309,9 +333,12 @@ /* in the req. */ if (service != NULL) { req->service = (WCHAR*)alloc_ptr; - if (uv_utf8_to_utf16(service, - (WCHAR*) alloc_ptr, - servicesize / sizeof(WCHAR)) == 0) { + if (MultiByteToWideChar(CP_UTF8, + 0, + service, + -1, + (WCHAR*) alloc_ptr, + servicesize / sizeof(WCHAR)) == 0) { err = GetLastError(); goto error; } diff -Nru libuv1-1.8.0/src/win/internal.h libuv1-1.9.1/src/win/internal.h --- libuv1-1.8.0/src/win/internal.h 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/win/internal.h 2016-05-16 21:22:19.000000000 +0000 @@ -83,6 +83,7 @@ #define UV_HANDLE_ZERO_READ 0x00080000 #define UV_HANDLE_EMULATE_IOCP 0x00100000 #define UV_HANDLE_BLOCKING_WRITES 0x00200000 +#define UV_HANDLE_CANCELLATION_PENDING 0x00400000 /* Used by uv_tcp_t and uv_udp_t handles */ #define UV_HANDLE_IPV6 0x01000000 @@ -246,7 +247,6 @@ void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle); DWORD uv__next_timeout(const uv_loop_t* loop); -void uv__time_forward(uv_loop_t* loop, uint64_t msecs); void uv_process_timers(uv_loop_t* loop); @@ -329,6 +329,8 @@ int uv_parent_pid(); int uv_current_pid(); __declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall); +int uv__getpwuid_r(uv_passwd_t* pwd); +int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8); /* diff -Nru libuv1-1.8.0/src/win/pipe.c libuv1-1.9.1/src/win/pipe.c --- libuv1-1.8.0/src/win/pipe.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/win/pipe.c 2016-05-16 21:22:19.000000000 +0000 @@ -513,13 +513,18 @@ } /* Convert name to UTF16. */ - nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(WCHAR); + nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR); handle->name = (WCHAR*)uv__malloc(nameSize); if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } - if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) { + if (!MultiByteToWideChar(CP_UTF8, + 0, + name, + -1, + handle->name, + nameSize / sizeof(WCHAR))) { err = GetLastError(); goto error; } @@ -627,13 +632,18 @@ req->cb = cb; /* Convert name to UTF16. */ - nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(WCHAR); + nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR); handle->name = (WCHAR*)uv__malloc(nameSize); if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } - if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) { + if (!MultiByteToWideChar(CP_UTF8, + 0, + name, + -1, + handle->name, + nameSize / sizeof(WCHAR))) { err = GetLastError(); goto error; } @@ -2038,9 +2048,9 @@ *size = 0; err = uv_translate_sys_error(GetLastError()); goto error; - } else if (pipe_prefix_len + addrlen > *size) { + } else if (pipe_prefix_len + addrlen >= *size) { /* "\\\\.\\pipe" + name */ - *size = pipe_prefix_len + addrlen; + *size = pipe_prefix_len + addrlen + 1; err = UV_ENOBUFS; goto error; } @@ -2062,6 +2072,7 @@ addrlen += pipe_prefix_len; *size = addrlen; + buffer[addrlen] = '\0'; err = 0; goto cleanup; diff -Nru libuv1-1.8.0/src/win/poll.c libuv1-1.9.1/src/win/poll.c --- libuv1-1.8.0/src/win/poll.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/win/poll.c 2016-05-16 21:22:19.000000000 +0000 @@ -91,7 +91,11 @@ handle->mask_events_1 = handle->events; handle->mask_events_2 = 0; } else { - assert(0); + /* Just wait until there's an unsubmitted req. */ + /* This will happen almost immediately as one of the 2 outstanding */ + /* requests is about to return. When this happens, */ + /* uv__fast_poll_process_poll_req will be called, and the pending */ + /* events, if needed, will be processed in a subsequent request. */ return; } @@ -107,6 +111,10 @@ if (handle->events & UV_READABLE) { afd_poll_info->Handles[0].Events |= AFD_POLL_RECEIVE | AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT; + } else { + if (handle->events & UV_DISCONNECT) { + afd_poll_info->Handles[0].Events |= AFD_POLL_DISCONNECT; + } } if (handle->events & UV_WRITABLE) { afd_poll_info->Handles[0].Events |= AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL; @@ -184,6 +192,9 @@ if ((afd_poll_info->Handles[0].Events & (AFD_POLL_RECEIVE | AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT)) != 0) { events |= UV_READABLE; + if ((afd_poll_info->Handles[0].Events & AFD_POLL_DISCONNECT) != 0) { + events |= UV_DISCONNECT; + } } if ((afd_poll_info->Handles[0].Events & (AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL)) != 0) { @@ -218,7 +229,7 @@ static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) { assert(handle->type == UV_POLL); assert(!(handle->flags & UV__HANDLE_CLOSING)); - assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0); + assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0); handle->events = events; diff -Nru libuv1-1.8.0/src/win/timer.c libuv1-1.9.1/src/win/timer.c --- libuv1-1.8.0/src/win/timer.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/win/timer.c 2016-05-16 21:22:19.000000000 +0000 @@ -34,13 +34,8 @@ void uv_update_time(uv_loop_t* loop) { uint64_t new_time = uv__hrtime(UV__MILLISEC); - if (new_time > loop->time) { - loop->time = new_time; - } -} - -void uv__time_forward(uv_loop_t* loop, uint64_t msecs) { - loop->time += msecs; + assert(new_time >= loop->time); + loop->time = new_time; } diff -Nru libuv1-1.8.0/src/win/tty.c libuv1-1.9.1/src/win/tty.c --- libuv1-1.8.0/src/win/tty.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/win/tty.c 2016-05-16 21:22:19.000000000 +0000 @@ -57,11 +57,23 @@ static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info); static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info); +static int uv__cancel_read_console(uv_tty_t* handle); /* Null uv_buf_t */ static const uv_buf_t uv_null_buf_ = { 0, NULL }; +enum uv__read_console_status_e { + NOT_STARTED, + IN_PROGRESS, + TRAP_REQUESTED, + COMPLETED +}; + +static volatile LONG uv__read_console_status = NOT_STARTED; +static volatile LONG uv__restore_screen_state; +static CONSOLE_SCREEN_BUFFER_INFO uv__saved_screen_state; + /* * The console virtual window. @@ -173,7 +185,8 @@ if (readable) { /* Initialize TTY input specific fields. */ tty->flags |= UV_HANDLE_TTY_READABLE | UV_HANDLE_READABLE; - tty->tty.rd.read_line_handle = NULL; + /* TODO: remove me in v2.x. */ + tty->tty.rd.unused_ = NULL; tty->tty.rd.read_line_buffer = uv_null_buf_; tty->tty.rd.read_raw_wait = NULL; @@ -292,12 +305,9 @@ was_reading = 1; alloc_cb = tty->alloc_cb; read_cb = tty->read_cb; - - if (was_reading) { - err = uv_tty_read_stop(tty); - if (err) { - return uv_translate_sys_error(err); - } + err = uv_tty_read_stop(tty); + if (err) { + return uv_translate_sys_error(err); } } else { was_reading = 0; @@ -401,6 +411,8 @@ DWORD bytes, read_bytes; WCHAR utf16[MAX_INPUT_BUFFER_LENGTH / 3]; DWORD chars, read_chars; + LONG status; + COORD pos; assert(data); @@ -422,7 +434,15 @@ /* One utf-16 codeunit never takes more than 3 utf-8 codeunits to encode */ chars = bytes / 3; - if (ReadConsoleW(handle->tty.rd.read_line_handle, + status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS); + if (status == TRAP_REQUESTED) { + SET_REQ_SUCCESS(req); + req->u.io.overlapped.InternalHigh = 0; + POST_COMPLETION_FOR_REQ(loop, req); + return 0; + } + + if (ReadConsoleW(handle->handle, (void*) utf16, chars, &read_chars, @@ -441,6 +461,33 @@ SET_REQ_ERROR(req, GetLastError()); } + InterlockedExchange(&uv__read_console_status, COMPLETED); + + /* If we canceled the read by sending a VK_RETURN event, restore the screen + state to undo the visual effect of the VK_RETURN*/ + if (InterlockedOr(&uv__restore_screen_state, 0)) { + HANDLE active_screen_buffer = CreateFileA("conout$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (active_screen_buffer != INVALID_HANDLE_VALUE) { + pos = uv__saved_screen_state.dwCursorPosition; + + /* If the cursor was at the bottom line of the screen buffer, the + VK_RETURN would have caused the buffer contents to scroll up by + one line. The right position to reset the cursor to is therefore one + line higher */ + if (pos.Y == uv__saved_screen_state.dwSize.Y - 1) + pos.Y--; + + SetConsoleCursorPosition(active_screen_buffer, pos); + CloseHandle(active_screen_buffer); + } + } + POST_COMPLETION_FOR_REQ(loop, req); return 0; } @@ -466,25 +513,11 @@ } 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->tty.rd.read_line_handle == NULL) { - HANDLE this_process = GetCurrentProcess(); - r = DuplicateHandle(this_process, - handle->handle, - this_process, - &handle->tty.rd.read_line_handle, - 0, - 0, - DUPLICATE_SAME_ACCESS); - if (!r) { - handle->tty.rd.read_line_handle = NULL; - SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); - goto out; - } - } - + /* Reset flags No locking is required since there cannot be a line read + in progress. We are also relying on the memory barrier provided by + QueueUserWorkItem*/ + uv__restore_screen_state = FALSE; + uv__read_console_status = NOT_STARTED; r = QueueUserWorkItem(uv_tty_line_read_thread, (void*) req, WT_EXECUTELONGFUNCTION); @@ -493,7 +526,6 @@ uv_insert_pending_req(loop, (uv_req_t*)req); } - out: handle->flags |= UV_HANDLE_READ_PENDING; handle->reqs_pending++; } @@ -860,8 +892,7 @@ if (!REQ_SUCCESS(req)) { /* Read was not successful */ - if ((handle->flags & UV_HANDLE_READING) && - handle->tty.rd.read_line_handle != NULL) { + if (handle->flags & UV_HANDLE_READING) { /* Real error */ handle->flags &= ~UV_HANDLE_READING; DECREASE_ACTIVE_COUNT(loop, handle); @@ -874,10 +905,15 @@ } } else { - /* Read successful */ - /* TODO: read unicode, convert to utf-8 */ - DWORD bytes = req->u.io.overlapped.InternalHigh; - handle->read_cb((uv_stream_t*) handle, bytes, &buf); + if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) { + /* Read successful */ + /* TODO: read unicode, convert to utf-8 */ + DWORD bytes = req->u.io.overlapped.InternalHigh; + handle->read_cb((uv_stream_t*) handle, bytes, &buf); + } else { + handle->flags &= ~UV_HANDLE_CANCELLATION_PENDING; + handle->read_cb((uv_stream_t*) handle, 0, &buf); + } } /* Wait for more input events. */ @@ -940,30 +976,82 @@ int uv_tty_read_stop(uv_tty_t* handle) { + INPUT_RECORD record; + DWORD written, err; + handle->flags &= ~UV_HANDLE_READING; DECREASE_ACTIVE_COUNT(handle->loop, handle); - /* Cancel raw read */ - if ((handle->flags & UV_HANDLE_READ_PENDING) && - (handle->flags & UV_HANDLE_TTY_RAW)) { + if (!(handle->flags & UV_HANDLE_READ_PENDING)) + return 0; + + if (handle->flags & UV_HANDLE_TTY_RAW) { + /* Cancel raw read */ /* Write some bullshit event to force the console wait to return. */ - INPUT_RECORD record; - DWORD written; memset(&record, 0, sizeof record); if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) { return GetLastError(); } + } else if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) { + /* Cancel line-buffered read if not already pending */ + err = uv__cancel_read_console(handle); + if (err) + return err; + + handle->flags |= UV_HANDLE_CANCELLATION_PENDING; } - /* Cancel line-buffered read */ - if (handle->tty.rd.read_line_handle != NULL) { - /* Closing this handle will cancel the ReadConsole operation */ - CloseHandle(handle->tty.rd.read_line_handle); - handle->tty.rd.read_line_handle = NULL; + return 0; +} + +static int uv__cancel_read_console(uv_tty_t* handle) { + HANDLE active_screen_buffer = INVALID_HANDLE_VALUE; + INPUT_RECORD record; + DWORD written; + DWORD err = 0; + LONG status; + + assert(!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)); + + status = InterlockedExchange(&uv__read_console_status, TRAP_REQUESTED); + if (status != IN_PROGRESS) { + /* Either we have managed to set a trap for the other thread before + ReadConsole is called, or ReadConsole has returned because the user + has pressed ENTER. In either case, there is nothing else to do. */ + return 0; } + /* Save screen state before sending the VK_RETURN event */ + active_screen_buffer = CreateFileA("conout$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); - return 0; + if (active_screen_buffer != INVALID_HANDLE_VALUE && + GetConsoleScreenBufferInfo(active_screen_buffer, + &uv__saved_screen_state)) { + InterlockedOr(&uv__restore_screen_state, 1); + } + + /* Write enter key event to force the console wait to return. */ + record.EventType = KEY_EVENT; + record.Event.KeyEvent.bKeyDown = TRUE; + record.Event.KeyEvent.wRepeatCount = 1; + record.Event.KeyEvent.wVirtualKeyCode = VK_RETURN; + record.Event.KeyEvent.wVirtualScanCode = + MapVirtualKeyW(VK_RETURN, MAPVK_VK_TO_VSC); + record.Event.KeyEvent.uChar.UnicodeChar = L'\r'; + record.Event.KeyEvent.dwControlKeyState = 0; + if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) + err = GetLastError(); + + if (active_screen_buffer != INVALID_HANDLE_VALUE) + CloseHandle(active_screen_buffer); + + return err; } @@ -2048,11 +2136,6 @@ if (handle->flags & UV__HANDLE_CLOSING && handle->reqs_pending == 0) { - /* The console handle duplicate used for line reading should be destroyed */ - /* by uv_tty_read_stop. */ - assert(!(handle->flags & UV_HANDLE_TTY_READABLE) || - 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) || diff -Nru libuv1-1.8.0/src/win/util.c libuv1-1.9.1/src/win/util.c --- libuv1-1.8.0/src/win/util.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/src/win/util.c 2016-05-16 21:22:19.000000000 +0000 @@ -87,30 +87,6 @@ } -int uv_utf16_to_utf8(const WCHAR* utf16Buffer, size_t utf16Size, - char* utf8Buffer, size_t utf8Size) { - return WideCharToMultiByte(CP_UTF8, - 0, - utf16Buffer, - utf16Size, - utf8Buffer, - utf8Size, - NULL, - NULL); -} - - -int uv_utf8_to_utf16(const char* utf8Buffer, WCHAR* utf16Buffer, - size_t utf16Size) { - return MultiByteToWideChar(CP_UTF8, - 0, - utf8Buffer, - -1, - utf16Buffer, - utf16Size); -} - - int uv_exepath(char* buffer, size_t* size_ptr) { int utf8_len, utf16_buffer_len, utf16_len; WCHAR* utf16_buffer; @@ -148,7 +124,7 @@ utf16_buffer, -1, buffer, - *size_ptr > INT_MAX ? INT_MAX : (int) *size_ptr, + (int) *size_ptr, NULL, NULL); if (utf8_len == 0) { @@ -210,7 +186,7 @@ if (r == 0) { return uv_translate_sys_error(GetLastError()); } else if (r > (int) *size) { - *size = r -1; + *size = r; return UV_ENOBUFS; } @@ -384,7 +360,7 @@ uv__once_init(); /* Find out how big the buffer for the wide-char title must be */ - length = uv_utf8_to_utf16(title, NULL, 0); + length = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0); if (!length) { err = GetLastError(); goto done; @@ -396,7 +372,7 @@ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); } - length = uv_utf8_to_utf16(title, title_w, length); + length = MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, length); if (!length) { err = GetLastError(); goto done; @@ -427,29 +403,13 @@ static int uv__get_process_title() { WCHAR title_w[MAX_TITLE_LENGTH]; - int length; if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) { return -1; } - /* Find out what the size of the buffer is that we need */ - length = uv_utf16_to_utf8(title_w, -1, NULL, 0); - if (!length) { + if (uv__convert_utf16_to_utf8(title_w, -1, &process_title) != 0) return -1; - } - - assert(!process_title); - process_title = (char*)uv__malloc(length); - if (!process_title) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - - /* Do utf16 -> utf8 conversion here */ - if (!uv_utf16_to_utf8(title_w, -1, process_title, length)) { - uv__free(process_title); - return -1; - } return 0; } @@ -721,43 +681,9 @@ cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000; cpu_info->cpu_times.nice = 0; - - len = WideCharToMultiByte(CP_UTF8, - 0, - cpu_brand, + uv__convert_utf16_to_utf8(cpu_brand, cpu_brand_size / sizeof(WCHAR), - NULL, - 0, - NULL, - NULL); - if (len == 0) { - err = GetLastError(); - goto error; - } - - assert(len > 0); - - /* Allocate 1 extra byte for the null terminator. */ - cpu_info->model = uv__malloc(len + 1); - if (cpu_info->model == NULL) { - err = ERROR_OUTOFMEMORY; - goto error; - } - - if (WideCharToMultiByte(CP_UTF8, - 0, - cpu_brand, - cpu_brand_size / sizeof(WCHAR), - cpu_info->model, - len, - NULL, - NULL) == 0) { - err = GetLastError(); - goto error; - } - - /* Ensure that cpu_info->model is null terminated. */ - cpu_info->model[len] = '\0'; + &(cpu_info->model)); } uv__free(sppi); @@ -1135,6 +1061,7 @@ int uv_getrusage(uv_rusage_t *uv_rusage) { FILETIME createTime, exitTime, kernelTime, userTime; SYSTEMTIME kernelSystemTime, userSystemTime; + PROCESS_MEMORY_COUNTERS memCounters; int ret; ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime); @@ -1152,6 +1079,13 @@ return uv_translate_sys_error(GetLastError()); } + ret = GetProcessMemoryInfo(GetCurrentProcess(), + &memCounters, + sizeof(memCounters)); + if (ret == 0) { + return uv_translate_sys_error(GetLastError()); + } + memset(uv_rusage, 0, sizeof(*uv_rusage)); uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 + @@ -1164,12 +1098,15 @@ kernelSystemTime.wSecond; uv_rusage->ru_stime.tv_usec = kernelSystemTime.wMilliseconds * 1000; + uv_rusage->ru_majflt = (uint64_t) memCounters.PageFaultCount; + uv_rusage->ru_maxrss = (uint64_t) memCounters.PeakWorkingSetSize / 1024; + return 0; } int uv_os_homedir(char* buffer, size_t* size) { - HANDLE token; + uv_passwd_t pwd; wchar_t path[MAX_PATH]; DWORD bufsize; size_t len; @@ -1183,6 +1120,7 @@ if (len == 0) { r = GetLastError(); + /* Don't return an error if USERPROFILE was not found */ if (r != ERROR_ENVVAR_NOT_FOUND) return uv_translate_sys_error(r); @@ -1190,43 +1128,237 @@ /* This should not be possible */ return UV_EIO; } else { - goto convert_buffer; + /* Check how much space we need */ + bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL); + + if (bufsize == 0) { + return uv_translate_sys_error(GetLastError()); + } else if (bufsize > *size) { + *size = bufsize; + return UV_ENOBUFS; + } + + /* Convert to UTF-8 */ + bufsize = WideCharToMultiByte(CP_UTF8, + 0, + path, + -1, + buffer, + *size, + NULL, + NULL); + + if (bufsize == 0) + return uv_translate_sys_error(GetLastError()); + + *size = bufsize - 1; + return 0; } - /* USERPROFILE is not set, so call GetUserProfileDirectoryW() */ - if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0) - return uv_translate_sys_error(GetLastError()); + /* USERPROFILE is not set, so call uv__getpwuid_r() */ + r = uv__getpwuid_r(&pwd); - bufsize = MAX_PATH; - if (!GetUserProfileDirectoryW(token, path, &bufsize)) { - r = GetLastError(); - CloseHandle(token); + if (r != 0) { + return r; + } - /* This should not be possible */ - if (r == ERROR_INSUFFICIENT_BUFFER) - return UV_EIO; + len = strlen(pwd.homedir); - return uv_translate_sys_error(r); + if (len >= *size) { + *size = len + 1; + uv_os_free_passwd(&pwd); + return UV_ENOBUFS; } - CloseHandle(token); + memcpy(buffer, pwd.homedir, len + 1); + *size = len; + uv_os_free_passwd(&pwd); + + return 0; +} + -convert_buffer: +int uv_os_tmpdir(char* buffer, size_t* size) { + wchar_t path[MAX_PATH + 1]; + DWORD bufsize; + size_t len; + + if (buffer == NULL || size == NULL || *size == 0) + return UV_EINVAL; + + len = GetTempPathW(MAX_PATH + 1, path); + + if (len == 0) { + return uv_translate_sys_error(GetLastError()); + } else if (len > MAX_PATH + 1) { + /* This should not be possible */ + return UV_EIO; + } + + /* The returned directory should not have a trailing slash, unless it */ + /* points at a drive root, like c:\. Remove it if needed.*/ + if (path[len - 1] == L'\\' && + !(len == 3 && path[1] == L':')) { + len--; + path[len] = L'\0'; + } /* Check how much space we need */ - bufsize = uv_utf16_to_utf8(path, -1, NULL, 0); + bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL); + if (bufsize == 0) { return uv_translate_sys_error(GetLastError()); } else if (bufsize > *size) { - *size = bufsize - 1; + *size = bufsize; return UV_ENOBUFS; } /* Convert to UTF-8 */ - bufsize = uv_utf16_to_utf8(path, -1, buffer, *size); + bufsize = WideCharToMultiByte(CP_UTF8, + 0, + path, + -1, + buffer, + *size, + NULL, + NULL); + if (bufsize == 0) return uv_translate_sys_error(GetLastError()); *size = bufsize - 1; return 0; } + + +void uv_os_free_passwd(uv_passwd_t* pwd) { + if (pwd == NULL) + return; + + uv__free(pwd->username); + uv__free(pwd->homedir); + pwd->username = NULL; + pwd->homedir = NULL; +} + + +/* + * Converts a UTF-16 string into a UTF-8 one. The resulting string is + * null-terminated. + * + * If utf16 is null terminated, utf16len can be set to -1, otherwise it must + * be specified. + */ +int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) { + DWORD bufsize; + + if (utf16 == NULL) + return UV_EINVAL; + + /* Check how much space we need */ + bufsize = WideCharToMultiByte(CP_UTF8, + 0, + utf16, + utf16len, + NULL, + 0, + NULL, + NULL); + + if (bufsize == 0) + return uv_translate_sys_error(GetLastError()); + + /* Allocate the destination buffer adding an extra byte for the terminating + * NULL. If utf16len is not -1 WideCharToMultiByte will not add it, so + * we do it ourselves always, just in case. */ + *utf8 = uv__malloc(bufsize + 1); + + if (*utf8 == NULL) + return UV_ENOMEM; + + /* Convert to UTF-8 */ + bufsize = WideCharToMultiByte(CP_UTF8, + 0, + utf16, + utf16len, + *utf8, + bufsize, + NULL, + NULL); + + if (bufsize == 0) { + uv__free(*utf8); + *utf8 = NULL; + return uv_translate_sys_error(GetLastError()); + } + + (*utf8)[bufsize] = '\0'; + return 0; +} + + +int uv__getpwuid_r(uv_passwd_t* pwd) { + HANDLE token; + wchar_t username[UNLEN + 1]; + wchar_t path[MAX_PATH]; + DWORD bufsize; + int r; + + if (pwd == NULL) + return UV_EINVAL; + + /* Get the home directory using GetUserProfileDirectoryW() */ + if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0) + return uv_translate_sys_error(GetLastError()); + + bufsize = sizeof(path); + if (!GetUserProfileDirectoryW(token, path, &bufsize)) { + r = GetLastError(); + CloseHandle(token); + + /* This should not be possible */ + if (r == ERROR_INSUFFICIENT_BUFFER) + return UV_ENOMEM; + + return uv_translate_sys_error(r); + } + + CloseHandle(token); + + /* Get the username using GetUserNameW() */ + bufsize = sizeof(username); + if (!GetUserNameW(username, &bufsize)) { + r = GetLastError(); + + /* This should not be possible */ + if (r == ERROR_INSUFFICIENT_BUFFER) + return UV_ENOMEM; + + return uv_translate_sys_error(r); + } + + pwd->homedir = NULL; + r = uv__convert_utf16_to_utf8(path, -1, &pwd->homedir); + + if (r != 0) + return r; + + pwd->username = NULL; + r = uv__convert_utf16_to_utf8(username, -1, &pwd->username); + + if (r != 0) { + uv__free(pwd->homedir); + return r; + } + + pwd->shell = NULL; + pwd->uid = -1; + pwd->gid = -1; + + return 0; +} + + +int uv_os_get_passwd(uv_passwd_t* pwd) { + return uv__getpwuid_r(pwd); +} diff -Nru libuv1-1.8.0/test/runner-unix.c libuv1-1.9.1/test/runner-unix.c --- libuv1-1.8.0/test/runner-unix.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/runner-unix.c 2016-05-16 21:22:19.000000000 +0000 @@ -226,7 +226,7 @@ tv = timebase; for (;;) { /* Check that gettimeofday() doesn't jump back in time. */ - assert(tv.tv_sec == timebase.tv_sec || + assert(tv.tv_sec > timebase.tv_sec || (tv.tv_sec == timebase.tv_sec && tv.tv_usec >= timebase.tv_usec)); elapsed_ms = diff -Nru libuv1-1.8.0/test/task.h libuv1-1.9.1/test/task.h --- libuv1-1.8.0/test/task.h 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/task.h 2016-05-16 21:22:19.000000000 +0000 @@ -108,10 +108,10 @@ /* This macro cleans up the main loop. This is used to avoid valgrind * warnings about memory being "leaked" by the main event loop. */ -#define MAKE_VALGRIND_HAPPY() \ - do { \ - close_loop(uv_default_loop()); \ - uv_loop_delete(uv_default_loop()); \ +#define MAKE_VALGRIND_HAPPY() \ + do { \ + close_loop(uv_default_loop()); \ + ASSERT(0 == uv_loop_close(uv_default_loop())); \ } while (0) /* Just sugar for wrapping the main() for a task or helper. */ @@ -207,7 +207,7 @@ int i; if (uv_interface_addresses(&addr, &count)) - return 1; /* Assume IPv6 support on failure. */ + return 0; /* Assume no IPv6 support on failure. */ supported = 0; for (i = 0; supported == 0 && i < count; i += 1) diff -Nru libuv1-1.8.0/test/test-condvar.c libuv1-1.9.1/test/test-condvar.c --- libuv1-1.8.0/test/test-condvar.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-condvar.c 2016-05-16 21:22:19.000000000 +0000 @@ -25,24 +25,33 @@ #include #include -typedef struct { +typedef struct worker_config { uv_mutex_t mutex; uv_cond_t cond; - int delay; + int signal_delay; + int wait_delay; int use_broadcast; - volatile int posted; + volatile int posted_1; + volatile int posted_2; + void (*signal_cond)(struct worker_config* c, volatile int* flag); + void (*wait_cond)(struct worker_config* c, const volatile int* flag); } worker_config; static void worker(void* arg) { worker_config* c = arg; + c->signal_cond(c, &c->posted_1); + c->wait_cond(c, &c->posted_2); +} + - if (c->delay) - uv_sleep(c->delay); +static void condvar_signal(worker_config* c, volatile int* flag) { + if (c->signal_delay) + uv_sleep(c->signal_delay); uv_mutex_lock(&c->mutex); - ASSERT(c->posted == 0); - c->posted = 1; + ASSERT(*flag == 0); + *flag = 1; if (c->use_broadcast) uv_cond_broadcast(&c->cond); else @@ -51,21 +60,33 @@ } +static void condvar_wait(worker_config* c, const volatile int* flag) { + uv_mutex_lock(&c->mutex); + if (c->wait_delay) + uv_sleep(c->wait_delay); + while (*flag == 0) { + uv_cond_wait(&c->cond, &c->mutex); + } + ASSERT(*flag == 1); + uv_mutex_unlock(&c->mutex); +} + + TEST_IMPL(condvar_1) { uv_thread_t thread; worker_config wc; memset(&wc, 0, sizeof(wc)); + wc.wait_delay = 100; + wc.signal_cond = condvar_signal; + wc.wait_cond = condvar_wait; ASSERT(0 == uv_cond_init(&wc.cond)); ASSERT(0 == uv_mutex_init(&wc.mutex)); ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - uv_mutex_lock(&wc.mutex); - uv_sleep(100); - uv_cond_wait(&wc.cond, &wc.mutex); - ASSERT(wc.posted == 1); - uv_mutex_unlock(&wc.mutex); + wc.wait_cond(&wc, &wc.posted_1); + wc.signal_cond(&wc, &wc.posted_2); ASSERT(0 == uv_thread_join(&thread)); uv_mutex_destroy(&wc.mutex); @@ -80,15 +101,16 @@ worker_config wc; memset(&wc, 0, sizeof(wc)); - wc.delay = 100; + wc.signal_delay = 100; + wc.signal_cond = condvar_signal; + wc.wait_cond = condvar_wait; ASSERT(0 == uv_cond_init(&wc.cond)); ASSERT(0 == uv_mutex_init(&wc.mutex)); ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - uv_mutex_lock(&wc.mutex); - uv_cond_wait(&wc.cond, &wc.mutex); - uv_mutex_unlock(&wc.mutex); + wc.wait_cond(&wc, &wc.posted_1); + wc.signal_cond(&wc, &wc.posted_2); ASSERT(0 == uv_thread_join(&thread)); uv_mutex_destroy(&wc.mutex); @@ -98,22 +120,35 @@ } +static void condvar_timedwait(worker_config* c, const volatile int* flag) { + int r; + + uv_mutex_lock(&c->mutex); + if (c->wait_delay) + uv_sleep(c->wait_delay); + while (*flag == 0) { + r = uv_cond_timedwait(&c->cond, &c->mutex, (uint64_t)(150 * 1e6)); + ASSERT(r == 0); + } + uv_mutex_unlock(&c->mutex); +} + + TEST_IMPL(condvar_3) { uv_thread_t thread; worker_config wc; - int r; memset(&wc, 0, sizeof(wc)); - wc.delay = 100; + wc.signal_delay = 100; + wc.signal_cond = condvar_signal; + wc.wait_cond = condvar_timedwait; ASSERT(0 == uv_cond_init(&wc.cond)); ASSERT(0 == uv_mutex_init(&wc.mutex)); ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - uv_mutex_lock(&wc.mutex); - r = uv_cond_timedwait(&wc.cond, &wc.mutex, (uint64_t)(50 * 1e6)); - ASSERT(r == UV_ETIMEDOUT); - uv_mutex_unlock(&wc.mutex); + wc.wait_cond(&wc, &wc.posted_1); + wc.signal_cond(&wc, &wc.posted_2); ASSERT(0 == uv_thread_join(&thread)); uv_mutex_destroy(&wc.mutex); @@ -126,19 +161,18 @@ TEST_IMPL(condvar_4) { uv_thread_t thread; worker_config wc; - int r; memset(&wc, 0, sizeof(wc)); - wc.delay = 100; + wc.signal_delay = 100; + wc.signal_cond = condvar_signal; + wc.wait_cond = condvar_timedwait; ASSERT(0 == uv_cond_init(&wc.cond)); ASSERT(0 == uv_mutex_init(&wc.mutex)); ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - uv_mutex_lock(&wc.mutex); - r = uv_cond_timedwait(&wc.cond, &wc.mutex, (uint64_t)(150 * 1e6)); - ASSERT(r == 0); - uv_mutex_unlock(&wc.mutex); + wc.wait_cond(&wc, &wc.posted_1); + wc.signal_cond(&wc, &wc.posted_2); ASSERT(0 == uv_thread_join(&thread)); uv_mutex_destroy(&wc.mutex); @@ -154,16 +188,16 @@ memset(&wc, 0, sizeof(wc)); wc.use_broadcast = 1; + wc.signal_delay = 100; + wc.signal_cond = condvar_signal; + wc.wait_cond = condvar_wait; ASSERT(0 == uv_cond_init(&wc.cond)); ASSERT(0 == uv_mutex_init(&wc.mutex)); ASSERT(0 == uv_thread_create(&thread, worker, &wc)); - uv_mutex_lock(&wc.mutex); - uv_sleep(100); - uv_cond_wait(&wc.cond, &wc.mutex); - ASSERT(wc.posted == 1); - uv_mutex_unlock(&wc.mutex); + wc.wait_cond(&wc, &wc.posted_1); + wc.signal_cond(&wc, &wc.posted_2); ASSERT(0 == uv_thread_join(&thread)); uv_mutex_destroy(&wc.mutex); diff -Nru libuv1-1.8.0/test/test-eintr-handling.c libuv1-1.9.1/test/test-eintr-handling.c --- libuv1-1.8.0/test/test-eintr-handling.c 1970-01-01 00:00:00.000000000 +0000 +++ libuv1-1.9.1/test/test-eintr-handling.c 2016-05-16 21:22:19.000000000 +0000 @@ -0,0 +1,94 @@ +/* Copyright libuv project 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" + +#ifdef _WIN32 + +TEST_IMPL(eintr_handling) { + RETURN_SKIP("Test not implemented on Windows."); +} + +#else /* !_WIN32 */ + +#include +#include + +static uv_loop_t* loop; +static uv_fs_t read_req; +static uv_buf_t iov; + +static char buf[32]; +static char test_buf[] = "test-buffer\n"; +int pipe_fds[2]; + +struct thread_ctx { + uv_barrier_t barrier; + int fd; +}; + +static void thread_main(void* arg) { + int nwritten; + ASSERT(0 == kill(getpid(), SIGUSR1)); + + do + nwritten = write(pipe_fds[1], test_buf, sizeof(test_buf)); + while (nwritten == -1 && errno == EINTR); + + ASSERT(nwritten == sizeof(test_buf)); +} + +static void sig_func(uv_signal_t* handle, int signum) { + uv_signal_stop(handle); +} + +TEST_IMPL(eintr_handling) { + struct thread_ctx ctx; + uv_thread_t thread; + uv_signal_t signal; + int nread; + + iov = uv_buf_init(buf, sizeof(buf)); + loop = uv_default_loop(); + + ASSERT(0 == uv_signal_init(loop, &signal)); + ASSERT(0 == uv_signal_start(&signal, sig_func, SIGUSR1)); + + ASSERT(0 == pipe(pipe_fds)); + ASSERT(0 == uv_thread_create(&thread, thread_main, &ctx)); + + nread = uv_fs_read(loop, &read_req, pipe_fds[0], &iov, 1, -1, NULL); + + ASSERT(nread == sizeof(test_buf)); + ASSERT(0 == strcmp(buf, test_buf)); + + ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); + + ASSERT(0 == close(pipe_fds[0])); + ASSERT(0 == close(pipe_fds[1])); + uv_close((uv_handle_t*) &signal, NULL); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#endif /* !_WIN32 */ diff -Nru libuv1-1.8.0/test/test-emfile.c libuv1-1.9.1/test/test-emfile.c --- libuv1-1.8.0/test/test-emfile.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-emfile.c 2016-05-16 21:22:19.000000000 +0000 @@ -38,6 +38,13 @@ TEST_IMPL(emfile) { +#ifdef _AIX + /* On AIX, if a 'accept' call fails ECONNRESET is set on the socket + * which causes uv__emfile_trick to not work as intended and this test + * to fail. + */ + RETURN_SKIP("uv__emfile_trick does not work on AIX"); +#endif struct sockaddr_in addr; struct rlimit limits; uv_connect_t connect_req; diff -Nru libuv1-1.8.0/test/test-fs.c libuv1-1.9.1/test/test-fs.c --- libuv1-1.8.0/test/test-fs.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-fs.c 2016-05-16 21:22:19.000000000 +0000 @@ -2033,6 +2033,9 @@ TEST_IMPL(fs_futime) { +#if defined(_AIX) && !defined(_AIX71) + RETURN_SKIP("futime is not implemented for AIX versions below 7.1"); +#else utime_check_t checkme; const char* path = "test_file"; double atime; @@ -2087,6 +2090,7 @@ MAKE_VALGRIND_HAPPY(); return 0; +#endif } diff -Nru libuv1-1.8.0/test/test-fs-event.c libuv1-1.9.1/test/test-fs-event.c --- libuv1-1.8.0/test/test-fs-event.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-fs-event.c 2016-05-16 21:22:19.000000000 +0000 @@ -511,7 +511,7 @@ r = uv_timer_init(loop, &timer); ASSERT(r == 0); - r = uv_timer_start(&timer, timer_cb_touch, 10, 0); + r = uv_timer_start(&timer, timer_cb_touch, 100, 0); ASSERT(r == 0); ASSERT(timer_cb_touch_called == 0); @@ -531,6 +531,33 @@ return 0; } +#ifdef _WIN32 +TEST_IMPL(fs_event_watch_file_root_dir) { + uv_loop_t* loop; + int r; + + const char* sys_drive = getenv("SystemDrive"); + char path[] = "\\\\?\\X:\\bootsect.bak"; + + ASSERT(sys_drive != NULL); + strncpy(path + sizeof("\\\\?\\") - 1, sys_drive, 1); + + loop = uv_default_loop(); + + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event, fail_cb, path, 0); + if (r == UV_ENOENT) + RETURN_SKIP("bootsect.bak doesn't exist in system root.\n"); + ASSERT(r == 0); + + uv_close((uv_handle_t*) &fs_event, NULL); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif + TEST_IMPL(fs_event_no_callback_after_close) { uv_loop_t* loop = uv_default_loop(); int r; @@ -671,18 +698,19 @@ return 0; } -#if defined(HAVE_KQUEUE) +#if defined(HAVE_KQUEUE) || defined(_AIX) /* kqueue doesn't register fs events if you don't have an active watcher. * The file descriptor needs to be part of the kqueue set of interest and * that's not the case until we actually enter the event loop. + * This is also observed on AIX with ahafs. */ TEST_IMPL(fs_event_close_in_callback) { - fprintf(stderr, "Skipping test, doesn't work with kqueue.\n"); + fprintf(stderr, "Skipping test, doesn't work with kqueue and AIX.\n"); return 0; } -#else /* !HAVE_KQUEUE */ +#else /* !HAVE_KQUEUE || !_AIX */ static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename, int events, int status) { @@ -739,7 +767,7 @@ return 0; } -#endif /* HAVE_KQUEUE */ +#endif /* HAVE_KQUEUE || _AIX */ TEST_IMPL(fs_event_start_and_close) { uv_loop_t* loop; @@ -792,6 +820,7 @@ r = uv_fs_event_getpath(&fs_event, buf, &len); ASSERT(r == 0); ASSERT(buf[len - 1] != 0); + ASSERT(buf[len] == '\0'); ASSERT(memcmp(buf, "watch_dir", len) == 0); r = uv_fs_event_stop(&fs_event); ASSERT(r == 0); diff -Nru libuv1-1.8.0/test/test-fs-poll.c libuv1-1.9.1/test/test-fs-poll.c --- libuv1-1.8.0/test/test-fs-poll.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-fs-poll.c 2016-05-16 21:22:19.000000000 +0000 @@ -173,6 +173,7 @@ len = sizeof buf; ASSERT(0 == uv_fs_poll_getpath(&poll_handle, buf, &len)); ASSERT(buf[len - 1] != 0); + ASSERT(buf[len] == '\0'); ASSERT(0 == memcmp(buf, FIXTURE, len)); uv_close((uv_handle_t*) &poll_handle, close_cb); diff -Nru libuv1-1.8.0/test/test-get-passwd.c libuv1-1.9.1/test/test-get-passwd.c --- libuv1-1.8.0/test/test-get-passwd.c 1970-01-01 00:00:00.000000000 +0000 +++ libuv1-1.9.1/test/test-get-passwd.c 2016-05-16 21:22:19.000000000 +0000 @@ -0,0 +1,86 @@ +/* Copyright libuv 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 + +TEST_IMPL(get_passwd) { + uv_passwd_t pwd; + size_t len; + int r; + + /* Test the normal case */ + r = uv_os_get_passwd(&pwd); + ASSERT(r == 0); + len = strlen(pwd.username); + ASSERT(len > 0); + +#ifdef _WIN32 + ASSERT(pwd.shell == NULL); +#else + len = strlen(pwd.shell); + ASSERT(len > 0); +#endif + + len = strlen(pwd.homedir); + ASSERT(len > 0); + +#ifdef _WIN32 + if (len == 3 && pwd.homedir[1] == ':') + ASSERT(pwd.homedir[2] == '\\'); + else + ASSERT(pwd.homedir[len - 1] != '\\'); +#else + if (len == 1) + ASSERT(pwd.homedir[0] == '/'); + else + ASSERT(pwd.homedir[len - 1] != '/'); +#endif + +#ifdef _WIN32 + ASSERT(pwd.uid == -1); + ASSERT(pwd.gid == -1); +#else + ASSERT(pwd.uid >= 0); + ASSERT(pwd.gid >= 0); +#endif + + /* Test uv_os_free_passwd() */ + uv_os_free_passwd(&pwd); + + ASSERT(pwd.username == NULL); + ASSERT(pwd.shell == NULL); + ASSERT(pwd.homedir == NULL); + + /* Test a double free */ + uv_os_free_passwd(&pwd); + + ASSERT(pwd.username == NULL); + ASSERT(pwd.shell == NULL); + ASSERT(pwd.homedir == NULL); + + /* Test invalid input */ + r = uv_os_get_passwd(NULL); + ASSERT(r == UV_EINVAL); + + return 0; +} diff -Nru libuv1-1.8.0/test/test-homedir.c libuv1-1.9.1/test/test-homedir.c --- libuv1-1.8.0/test/test-homedir.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-homedir.c 2016-05-16 21:22:19.000000000 +0000 @@ -1,3 +1,24 @@ +/* Copyright libuv project 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 @@ -8,7 +29,6 @@ TEST_IMPL(homedir) { char homedir[PATHMAX]; size_t len; - char last; int r; /* Test the normal case */ @@ -21,14 +41,17 @@ ASSERT(len > 0); ASSERT(homedir[len] == '\0'); - if (len > 1) { - last = homedir[len - 1]; #ifdef _WIN32 - ASSERT(last != '\\'); + if (len == 3 && homedir[1] == ':') + ASSERT(homedir[2] == '\\'); + else + ASSERT(homedir[len - 1] != '\\'); #else - ASSERT(last != '/'); + if (len == 1) + ASSERT(homedir[0] == '/'); + else + ASSERT(homedir[len - 1] != '/'); #endif - } /* Test the case where the buffer is too small */ len = SMALLPATH; diff -Nru libuv1-1.8.0/test/test-list.h libuv1-1.9.1/test/test-list.h --- libuv1-1.8.0/test/test-list.h 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-list.h 2016-05-16 21:22:19.000000000 +0000 @@ -43,7 +43,11 @@ TEST_DECLARE (semaphore_2) TEST_DECLARE (semaphore_3) TEST_DECLARE (tty) +#ifdef _WIN32 +TEST_DECLARE (tty_raw) +#endif TEST_DECLARE (tty_file) +TEST_DECLARE (tty_pty) TEST_DECLARE (stdio_over_pipes) TEST_DECLARE (ip6_pton) TEST_DECLARE (ipc_listen_before_write) @@ -154,6 +158,7 @@ TEST_DECLARE (timer_run_once) TEST_DECLARE (timer_from_check) TEST_DECLARE (timer_null_callback) +TEST_DECLARE (timer_early_check) TEST_DECLARE (idle_starvation) TEST_DECLARE (loop_handles) TEST_DECLARE (get_loadavg) @@ -191,12 +196,15 @@ TEST_DECLARE (embed) TEST_DECLARE (async) TEST_DECLARE (async_null_cb) +TEST_DECLARE (eintr_handling) TEST_DECLARE (get_currentexe) TEST_DECLARE (process_title) TEST_DECLARE (cwd_and_chdir) TEST_DECLARE (get_memory) +TEST_DECLARE (get_passwd) TEST_DECLARE (handle_fileno) TEST_DECLARE (homedir) +TEST_DECLARE (tmpdir) TEST_DECLARE (hrtime) TEST_DECLARE (getaddrinfo_fail) TEST_DECLARE (getaddrinfo_fail_sync) @@ -267,6 +275,9 @@ TEST_DECLARE (fs_event_watch_file) TEST_DECLARE (fs_event_watch_file_twice) TEST_DECLARE (fs_event_watch_file_current_dir) +#ifdef _WIN32 +TEST_DECLARE (fs_event_watch_file_root_dir) +#endif TEST_DECLARE (fs_event_no_callback_after_close) TEST_DECLARE (fs_event_no_callback_on_close) TEST_DECLARE (fs_event_immediate_close) @@ -292,6 +303,7 @@ TEST_DECLARE (threadpool_cancel_fs) TEST_DECLARE (threadpool_cancel_single) TEST_DECLARE (thread_local_storage) +TEST_DECLARE (thread_stack_size) TEST_DECLARE (thread_mutex) TEST_DECLARE (thread_rwlock) TEST_DECLARE (thread_rwlock_trylock) @@ -301,6 +313,7 @@ TEST_DECLARE (poll_duplex) TEST_DECLARE (poll_unidirectional) TEST_DECLARE (poll_close) +TEST_DECLARE (poll_bad_fdtype) TEST_DECLARE (ip4_addr) TEST_DECLARE (ip6_addr_link_local) @@ -377,7 +390,11 @@ #endif TEST_ENTRY (pipe_set_non_blocking) TEST_ENTRY (tty) +#ifdef _WIN32 + TEST_ENTRY (tty_raw) +#endif TEST_ENTRY (tty_file) + TEST_ENTRY (tty_pty) TEST_ENTRY (stdio_over_pipes) TEST_ENTRY (ip6_pton) TEST_ENTRY (ipc_listen_before_write) @@ -522,6 +539,7 @@ TEST_ENTRY (timer_run_once) TEST_ENTRY (timer_from_check) TEST_ENTRY (timer_null_callback) + TEST_ENTRY (timer_early_check) TEST_ENTRY (idle_starvation) @@ -566,6 +584,7 @@ TEST_ENTRY (async) TEST_ENTRY (async_null_cb) + TEST_ENTRY (eintr_handling) TEST_ENTRY (get_currentexe) @@ -575,12 +594,16 @@ TEST_ENTRY (get_memory) + TEST_ENTRY (get_passwd) + TEST_ENTRY (get_loadavg) TEST_ENTRY (handle_fileno) TEST_ENTRY (homedir) + TEST_ENTRY (tmpdir) + TEST_ENTRY (hrtime) TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000) @@ -600,6 +623,7 @@ TEST_ENTRY (poll_duplex) TEST_ENTRY (poll_unidirectional) TEST_ENTRY (poll_close) + TEST_ENTRY (poll_bad_fdtype) TEST_ENTRY (socket_buffer_size) @@ -688,6 +712,9 @@ TEST_ENTRY (fs_event_watch_file) TEST_ENTRY (fs_event_watch_file_twice) TEST_ENTRY (fs_event_watch_file_current_dir) +#ifdef _WIN32 + TEST_ENTRY (fs_event_watch_file_root_dir) +#endif TEST_ENTRY (fs_event_no_callback_after_close) TEST_ENTRY (fs_event_no_callback_on_close) TEST_ENTRY (fs_event_immediate_close) @@ -706,13 +733,21 @@ TEST_ENTRY (fs_read_write_null_arguments) TEST_ENTRY (threadpool_queue_work_simple) TEST_ENTRY (threadpool_queue_work_einval) +#if defined(__PPC__) || defined(__PPC64__) /* For linux PPC and AIX */ + /* pthread_join takes a while, especially on AIX. + * Therefore being gratuitous with timeout. + */ + TEST_ENTRY_CUSTOM (threadpool_multiple_event_loops, 0, 0, 120000) +#else TEST_ENTRY (threadpool_multiple_event_loops) +#endif TEST_ENTRY (threadpool_cancel_getaddrinfo) TEST_ENTRY (threadpool_cancel_getnameinfo) TEST_ENTRY (threadpool_cancel_work) TEST_ENTRY (threadpool_cancel_fs) TEST_ENTRY (threadpool_cancel_single) TEST_ENTRY (thread_local_storage) + TEST_ENTRY (thread_stack_size) TEST_ENTRY (thread_mutex) TEST_ENTRY (thread_rwlock) TEST_ENTRY (thread_rwlock_trylock) diff -Nru libuv1-1.8.0/test/test-pipe-close-stdout-read-stdin.c libuv1-1.9.1/test/test-pipe-close-stdout-read-stdin.c --- libuv1-1.8.0/test/test-pipe-close-stdout-read-stdin.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-pipe-close-stdout-read-stdin.c 2016-05-16 21:22:19.000000000 +0000 @@ -53,6 +53,7 @@ int pid; int fd[2]; int status; + char buf; uv_pipe_t stdin_pipe; r = pipe(fd); @@ -64,6 +65,8 @@ * The write side will be closed by the parent process. */ close(fd[1]); + /* block until write end of pipe is closed */ + read(fd[0], &buf, 1); close(0); r = dup(fd[0]); ASSERT(r != -1); diff -Nru libuv1-1.8.0/test/test-pipe-getsockname.c libuv1-1.9.1/test/test-pipe-getsockname.c --- libuv1-1.8.0/test/test-pipe-getsockname.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-pipe-getsockname.c 2016-05-16 21:22:19.000000000 +0000 @@ -114,6 +114,7 @@ ASSERT(r == 0); ASSERT(buf[len - 1] != 0); + ASSERT(buf[len] == '\0'); ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); len = sizeof buf; diff -Nru libuv1-1.8.0/test/test-platform-output.c libuv1-1.9.1/test/test-platform-output.c --- libuv1-1.8.0/test/test-platform-output.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-platform-output.c 2016-05-16 21:22:19.000000000 +0000 @@ -32,6 +32,7 @@ uv_rusage_t rusage; uv_cpu_info_t* cpus; uv_interface_address_t* interfaces; + uv_passwd_t pwd; int count; int i; int err; @@ -60,6 +61,8 @@ ASSERT(rusage.ru_utime.tv_usec >= 0); ASSERT(rusage.ru_stime.tv_sec >= 0); ASSERT(rusage.ru_stime.tv_usec >= 0); + ASSERT(rusage.ru_majflt >= 0); + ASSERT(rusage.ru_maxrss >= 0); printf("uv_getrusage:\n"); printf(" user: %llu sec %llu microsec\n", (unsigned long long) rusage.ru_utime.tv_sec, @@ -67,6 +70,9 @@ printf(" system: %llu sec %llu microsec\n", (unsigned long long) rusage.ru_stime.tv_sec, (unsigned long long) rusage.ru_stime.tv_usec); + printf(" page faults: %llu\n", (unsigned long long) rusage.ru_majflt); + printf(" maximum resident set size: %llu\n", + (unsigned long long) rusage.ru_maxrss); err = uv_cpu_info(&cpus, &count); ASSERT(err == 0); @@ -122,5 +128,15 @@ } uv_free_interface_addresses(interfaces, count); + err = uv_os_get_passwd(&pwd); + ASSERT(err == 0); + + printf("uv_os_get_passwd:\n"); + printf(" euid: %ld\n", pwd.uid); + printf(" gid: %ld\n", pwd.gid); + printf(" username: %s\n", pwd.username); + printf(" shell: %s\n", pwd.shell); + printf(" home directory: %s\n", pwd.homedir); + return 0; } diff -Nru libuv1-1.8.0/test/test-poll.c libuv1-1.9.1/test/test-poll.c --- libuv1-1.8.0/test/test-poll.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-poll.c 2016-05-16 21:22:19.000000000 +0000 @@ -21,7 +21,9 @@ #include -#ifndef _WIN32 +#ifdef _WIN32 +# include +#else # include # include #endif @@ -49,7 +51,7 @@ size_t read, sent; int is_server_connection; int open_handles; - int got_fin, sent_fin; + int got_fin, sent_fin, got_disconnect; unsigned int events, delayed_events; } connection_context_t; @@ -70,6 +72,9 @@ static int valid_writable_wakeups = 0; static int spurious_writable_wakeups = 0; +#ifndef _AIX +static int disconnects = 0; +#endif /* !_AIX */ static int got_eagain(void) { #ifdef _WIN32 @@ -140,6 +145,7 @@ context->delayed_events = 0; context->got_fin = 0; context->sent_fin = 0; + context->got_disconnect = 0; r = uv_poll_init_socket(uv_default_loop(), &context->poll_handle, sock); context->open_handles++; @@ -372,8 +378,17 @@ new_events &= ~UV_WRITABLE; } } +#ifndef _AIX + if (events & UV_DISCONNECT) { + context->got_disconnect = 1; + ++disconnects; + new_events &= ~UV_DISCONNECT; + } + if (context->got_fin && context->sent_fin && context->got_disconnect) { +#else /* _AIX */ if (context->got_fin && context->sent_fin) { +#endif /* !_AIx */ /* Sent and received FIN. Close and destroy context. */ close_socket(context->sock); destroy_connection_context(context); @@ -461,9 +476,9 @@ #endif connection_context = create_connection_context(sock, 1); - connection_context->events = UV_READABLE | UV_WRITABLE; + connection_context->events = UV_READABLE | UV_WRITABLE | UV_DISCONNECT; r = uv_poll_start(&connection_context->poll_handle, - UV_READABLE | UV_WRITABLE, + UV_READABLE | UV_WRITABLE | UV_DISCONNECT, connection_poll_cb); ASSERT(r == 0); @@ -505,9 +520,9 @@ sock = create_bound_socket(addr); context = create_connection_context(sock, 0); - context->events = UV_READABLE | UV_WRITABLE; + context->events = UV_READABLE | UV_WRITABLE | UV_DISCONNECT; r = uv_poll_start(&context->poll_handle, - UV_READABLE | UV_WRITABLE, + UV_READABLE | UV_WRITABLE | UV_DISCONNECT, connection_poll_cb); ASSERT(r == 0); @@ -541,7 +556,9 @@ spurious_writable_wakeups > 20); ASSERT(closed_connections == NUM_CLIENTS * 2); - +#ifndef _AIX + ASSERT(disconnects == NUM_CLIENTS * 2); +#endif MAKE_VALGRIND_HAPPY(); } @@ -558,3 +575,29 @@ start_poll_test(); return 0; } + + +/* Windows won't let you open a directory so we open a file instead. + * OS X lets you poll a file so open the $PWD instead. Both fail + * on Linux so it doesn't matter which one we pick. Both succeed + * on FreeBSD, Solaris and AIX so skip the test on those platforms. + */ +TEST_IMPL(poll_bad_fdtype) { +#if !defined(__DragonFly__) && !defined(__FreeBSD__) && !defined(__sun) && \ + !defined(_AIX) + uv_poll_t poll_handle; + int fd; + +#if defined(_WIN32) + fd = open("test/fixtures/empty_file", O_RDONLY); +#else + fd = open(".", O_RDONLY); +#endif + ASSERT(fd != -1); + ASSERT(0 != uv_poll_init(uv_default_loop(), &poll_handle, fd)); + ASSERT(0 == close(fd)); +#endif + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff -Nru libuv1-1.8.0/test/test-tcp-close-while-connecting.c libuv1-1.9.1/test/test-tcp-close-while-connecting.c --- libuv1-1.8.0/test/test-tcp-close-while-connecting.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-tcp-close-while-connecting.c 2016-05-16 21:22:19.000000000 +0000 @@ -72,7 +72,7 @@ RETURN_SKIP("Network unreachable."); ASSERT(r == 0); ASSERT(0 == uv_timer_init(loop, &timer1_handle)); - ASSERT(0 == uv_timer_start(&timer1_handle, timer1_cb, 50, 0)); + ASSERT(0 == uv_timer_start(&timer1_handle, timer1_cb, 1, 0)); ASSERT(0 == uv_timer_init(loop, &timer2_handle)); ASSERT(0 == uv_timer_start(&timer2_handle, timer2_cb, 86400 * 1000, 0)); ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); diff -Nru libuv1-1.8.0/test/test-tcp-create-socket-early.c libuv1-1.9.1/test/test-tcp-create-socket-early.c --- libuv1-1.8.0/test/test-tcp-create-socket-early.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-tcp-create-socket-early.c 2016-05-16 21:22:19.000000000 +0000 @@ -139,6 +139,9 @@ uv_os_fd_t fd; int r; + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); r = uv_tcp_init_ex(uv_default_loop(), &client, AF_INET6); diff -Nru libuv1-1.8.0/test/test-tcp-write-queue-order.c libuv1-1.9.1/test/test-tcp-write-queue-order.c --- libuv1-1.8.0/test/test-tcp-write-queue-order.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-tcp-write-queue-order.c 2016-05-16 21:22:19.000000000 +0000 @@ -107,6 +107,7 @@ TEST_IMPL(tcp_write_queue_order) { uv_connect_t connect_req; struct sockaddr_in addr; + int buffer_size = 16 * 1024; start_server(); @@ -117,6 +118,7 @@ &client, (struct sockaddr*) &addr, connect_cb)); + ASSERT(0 == uv_send_buffer_size((uv_handle_t*) &client, &buffer_size)); ASSERT(0 == uv_timer_init(uv_default_loop(), &timer)); ASSERT(0 == uv_timer_start(&timer, timer_cb, 100, 0)); diff -Nru libuv1-1.8.0/test/test-thread.c libuv1-1.9.1/test/test-thread.c --- libuv1-1.8.0/test/test-thread.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-thread.c 2016-05-16 21:22:19.000000000 +0000 @@ -209,3 +209,24 @@ uv_key_delete(&tls_key); return 0; } + + +#if defined(__APPLE__) +static void thread_check_stack(void* arg) { + /* 512KB is the default stack size of threads other than the main thread + * on OSX. */ + ASSERT(pthread_get_stacksize_np(pthread_self()) > 512*1024); +} +#endif + + +TEST_IMPL(thread_stack_size) { +#if defined(__APPLE__) + uv_thread_t thread; + ASSERT(0 == uv_thread_create(&thread, thread_check_stack, NULL)); + ASSERT(0 == uv_thread_join(&thread)); + return 0; +#else + RETURN_SKIP("OSX only test"); +#endif +} diff -Nru libuv1-1.8.0/test/test-timer.c libuv1-1.9.1/test/test-timer.c --- libuv1-1.8.0/test/test-timer.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-timer.c 2016-05-16 21:22:19.000000000 +0000 @@ -301,3 +301,30 @@ MAKE_VALGRIND_HAPPY(); return 0; } + + +static uint64_t timer_early_check_expected_time; + + +static void timer_early_check_cb(uv_timer_t* handle) { + uint64_t hrtime = uv_hrtime() / 1000000; + ASSERT(hrtime >= timer_early_check_expected_time); +} + + +TEST_IMPL(timer_early_check) { + uv_timer_t timer_handle; + const uint64_t timeout_ms = 10; + + timer_early_check_expected_time = uv_now(uv_default_loop()) + timeout_ms; + + ASSERT(0 == uv_timer_init(uv_default_loop(), &timer_handle)); + ASSERT(0 == uv_timer_start(&timer_handle, timer_early_check_cb, timeout_ms, 0)); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + uv_close((uv_handle_t*) &timer_handle, NULL); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff -Nru libuv1-1.8.0/test/test-tmpdir.c libuv1-1.9.1/test/test-tmpdir.c --- libuv1-1.8.0/test/test-tmpdir.c 1970-01-01 00:00:00.000000000 +0000 +++ libuv1-1.9.1/test/test-tmpdir.c 2016-05-16 21:22:19.000000000 +0000 @@ -0,0 +1,71 @@ +/* Copyright libuv project 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 + +#define PATHMAX 1024 +#define SMALLPATH 1 + +TEST_IMPL(tmpdir) { + char tmpdir[PATHMAX]; + size_t len; + char last; + int r; + + /* Test the normal case */ + len = sizeof tmpdir; + tmpdir[0] = '\0'; + + ASSERT(strlen(tmpdir) == 0); + r = uv_os_tmpdir(tmpdir, &len); + ASSERT(r == 0); + ASSERT(strlen(tmpdir) == len); + ASSERT(len > 0); + ASSERT(tmpdir[len] == '\0'); + + if (len > 1) { + last = tmpdir[len - 1]; +#ifdef _WIN32 + ASSERT(last != '\\'); +#else + ASSERT(last != '/'); +#endif + } + + /* Test the case where the buffer is too small */ + len = SMALLPATH; + r = uv_os_tmpdir(tmpdir, &len); + ASSERT(r == UV_ENOBUFS); + ASSERT(len > SMALLPATH); + + /* Test invalid inputs */ + r = uv_os_tmpdir(NULL, &len); + ASSERT(r == UV_EINVAL); + r = uv_os_tmpdir(tmpdir, NULL); + ASSERT(r == UV_EINVAL); + len = 0; + r = uv_os_tmpdir(tmpdir, &len); + ASSERT(r == UV_EINVAL); + + return 0; +} diff -Nru libuv1-1.8.0/test/test-tty.c libuv1-1.9.1/test/test-tty.c --- libuv1-1.8.0/test/test-tty.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-tty.c 2016-05-16 21:22:19.000000000 +0000 @@ -28,6 +28,13 @@ #else /* Unix */ # include # include +# if defined(__linux__) +# include +# elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) +# include +# elif defined(__FreeBSD__) || defined(__DragonFly__) +# include +# endif #endif #include @@ -139,6 +146,75 @@ } +#ifdef _WIN32 +static void tty_raw_alloc(uv_handle_t* handle, size_t size, uv_buf_t* buf) { + buf->base = malloc(size); + buf->len = size; +} + +static void tty_raw_read(uv_stream_t* tty_in, ssize_t nread, const uv_buf_t* buf) { + if (nread > 0) { + ASSERT(nread == 1); + ASSERT(buf->base[0] == ' '); + uv_close((uv_handle_t*) tty_in, NULL); + } else { + ASSERT(nread == 0); + } +} + +TEST_IMPL(tty_raw) { + int r; + int ttyin_fd; + uv_tty_t tty_in; + uv_loop_t* loop = uv_default_loop(); + HANDLE handle; + INPUT_RECORD record; + DWORD written; + + /* Make sure we have an FD that refers to a tty */ + handle = CreateFileA("conin$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + ASSERT(handle != INVALID_HANDLE_VALUE); + ttyin_fd = _open_osfhandle((intptr_t) handle, 0); + ASSERT(ttyin_fd >= 0); + ASSERT(UV_TTY == uv_guess_handle(ttyin_fd)); + + r = uv_tty_init(uv_default_loop(), &tty_in, ttyin_fd, 1); /* Readable. */ + ASSERT(r == 0); + + r = uv_read_start((uv_stream_t*)&tty_in, tty_raw_alloc, tty_raw_read); + ASSERT(r == 0); + + /* Give uv_tty_line_read_thread time to block on ReadConsoleW */ + Sleep(100); + + /* Turn on raw mode. */ + r = uv_tty_set_mode(&tty_in, UV_TTY_MODE_RAW); + ASSERT(r == 0); + + /* Write ' ' that should be read in raw mode */ + record.EventType = KEY_EVENT; + record.Event.KeyEvent.bKeyDown = TRUE; + record.Event.KeyEvent.wRepeatCount = 1; + record.Event.KeyEvent.wVirtualKeyCode = VK_SPACE; + record.Event.KeyEvent.wVirtualScanCode = MapVirtualKeyW(VK_SPACE, MAPVK_VK_TO_VSC); + record.Event.KeyEvent.uChar.UnicodeChar = L' '; + record.Event.KeyEvent.dwControlKeyState = 0; + WriteConsoleInputW(handle, &record, 1, &written); + + uv_run(loop, UV_RUN_DEFAULT); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif + + TEST_IMPL(tty_file) { #ifndef _WIN32 uv_loop_t loop; @@ -180,5 +256,37 @@ MAKE_VALGRIND_HAPPY(); #endif + return 0; +} + +TEST_IMPL(tty_pty) { +# if defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ + defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) + int master_fd, slave_fd; + struct winsize w; + uv_loop_t loop; + uv_tty_t master_tty, slave_tty; + + ASSERT(0 == uv_loop_init(&loop)); + + ASSERT(0 == openpty(&master_fd, &slave_fd, NULL, NULL, &w)); + ASSERT(0 == uv_tty_init(&loop, &slave_tty, slave_fd, 0)); + ASSERT(0 == uv_tty_init(&loop, &master_tty, master_fd, 0)); + /* Check if the file descriptor was reopened. If it is, + * UV_STREAM_BLOCKING (value 0x80) isn't set on flags. + */ + ASSERT(0 == (slave_tty.flags & 0x80)); + /* The master_fd of a pty should never be reopened. + */ + ASSERT(master_tty.flags & 0x80); + ASSERT(0 == close(slave_fd)); + uv_close((uv_handle_t*) &slave_tty, NULL); + ASSERT(0 == close(master_fd)); + uv_close((uv_handle_t*) &master_tty, NULL); + + ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT)); + + MAKE_VALGRIND_HAPPY(); +#endif return 0; } diff -Nru libuv1-1.8.0/test/test-udp-create-socket-early.c libuv1-1.9.1/test/test-udp-create-socket-early.c --- libuv1-1.8.0/test/test-udp-create-socket-early.c 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/test/test-udp-create-socket-early.c 2016-05-16 21:22:19.000000000 +0000 @@ -79,6 +79,9 @@ uv_os_fd_t fd; int r; + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); r = uv_udp_init_ex(uv_default_loop(), &client, AF_INET6); diff -Nru libuv1-1.8.0/uv.gyp libuv1-1.9.1/uv.gyp --- libuv1-1.8.0/uv.gyp 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/uv.gyp 2016-05-16 21:22:19.000000000 +0000 @@ -17,6 +17,7 @@ }], ], 'xcode_settings': { + 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden 'WARNING_CFLAGS': [ '-Wall', '-Wextra', '-Wno-unused-parameter' ], 'OTHER_CFLAGS': [ '-g', '--std=gnu89', '-pedantic' ], } @@ -92,6 +93,7 @@ 'src/win/req.c', 'src/win/req-inl.h', 'src/win/signal.c', + 'src/win/snprintf.c', 'src/win/stream.c', 'src/win/stream-inl.h', 'src/win/tcp.c', @@ -104,25 +106,20 @@ 'src/win/winsock.c', 'src/win/winsock.h', ], - 'conditions': [ - ['MSVS_VERSION < "2015"', { - 'sources': [ - 'src/win/snprintf.c' - ] - }] - ], 'link_settings': { 'libraries': [ '-ladvapi32', '-liphlpapi', '-lpsapi', '-lshell32', + '-luser32', '-luserenv', '-lws2_32' ], }, }, { # Not Windows i.e. POSIX 'cflags': [ + '-fvisibility=hidden', '-g', '--std=gnu89', '-pedantic', @@ -190,6 +187,7 @@ 'src/unix/darwin.c', 'src/unix/fsevents.c', 'src/unix/darwin-proctitle.c', + 'src/unix/pthread-barrier.c' ], 'defines': [ '_DARWIN_USE_64_BIT_INODE=1', @@ -220,7 +218,8 @@ 'src/unix/linux-syscalls.c', 'src/unix/linux-syscalls.h', 'src/unix/pthread-fixes.c', - 'src/unix/android-ifaddrs.c' + 'src/unix/android-ifaddrs.c', + 'src/unix/pthread-barrier.c' ], 'link_settings': { 'libraries': [ '-ldl' ], @@ -247,6 +246,7 @@ '_ALL_SOURCE', '_XOPEN_SOURCE=500', '_LINUX_SOURCE_COMPAT', + '_THREAD_SAFE', ], 'link_settings': { 'libraries': [ @@ -300,6 +300,7 @@ 'test/test-cwd-and-chdir.c', 'test/test-default-loop-close.c', 'test/test-delayed-accept.c', + 'test/test-eintr-handling.c', 'test/test-error.c', 'test/test-embed.c', 'test/test-emfile.c', @@ -308,6 +309,7 @@ 'test/test-fs-event.c', 'test/test-get-currentexe.c', 'test/test-get-memory.c', + 'test/test-get-passwd.c', 'test/test-getaddrinfo.c', 'test/test-getnameinfo.c', 'test/test-getsockname.c', @@ -386,6 +388,7 @@ 'test/test-threadpool.c', 'test/test-threadpool-cancel.c', 'test/test-thread-equal.c', + 'test/test-tmpdir.c', 'test/test-mutexes.c', 'test/test-thread.c', 'test/test-barrier.c', @@ -417,7 +420,8 @@ [ 'OS=="win"', { 'sources': [ 'test/runner-win.c', - 'test/runner-win.h' + 'test/runner-win.h', + 'src/win/snprintf.c', ], 'libraries': [ '-lws2_32' ] }, { # POSIX @@ -427,6 +431,11 @@ 'test/runner-unix.h', ], }], + [ 'OS in "mac dragonflybsd freebsd linux netbsd openbsd".split()', { + 'link_settings': { + 'libraries': [ '-lutil' ], + }, + }], [ 'OS=="solaris"', { # make test-fs.c compile, needs _POSIX_C_SOURCE 'defines': [ '__EXTENSIONS__', @@ -485,6 +494,7 @@ 'sources': [ 'test/runner-win.c', 'test/runner-win.h', + 'src/win/snprintf.c', ], 'libraries': [ '-lws2_32' ] }, { # POSIX diff -Nru libuv1-1.8.0/vcbuild.bat libuv1-1.9.1/vcbuild.bat --- libuv1-1.8.0/vcbuild.bat 2015-12-14 19:54:30.000000000 +0000 +++ libuv1-1.9.1/vcbuild.bat 2016-05-16 21:22:19.000000000 +0000 @@ -19,7 +19,7 @@ set run= set target_arch=ia32 set vs_toolset=x86 -set platform=WIN32 +set msbuild_platform=WIN32 set library=static_library :next-arg @@ -31,9 +31,9 @@ if /i "%1"=="clean" set target=Clean&goto arg-ok if /i "%1"=="noprojgen" set noprojgen=1&goto arg-ok if /i "%1"=="nobuild" set nobuild=1&goto arg-ok -if /i "%1"=="x86" set target_arch=ia32&set platform=WIN32&set vs_toolset=x86&goto arg-ok -if /i "%1"=="ia32" set target_arch=ia32&set platform=WIN32&set vs_toolset=x86&goto arg-ok -if /i "%1"=="x64" set target_arch=x64&set platform=x64&set vs_toolset=x64&goto arg-ok +if /i "%1"=="x86" set target_arch=ia32&set msbuild_platform=WIN32&set vs_toolset=x86&goto arg-ok +if /i "%1"=="ia32" set target_arch=ia32&set msbuild_platform=WIN32&set vs_toolset=x86&goto arg-ok +if /i "%1"=="x64" set target_arch=x64&set msbuild_platform=x64&set vs_toolset=x64&goto arg-ok if /i "%1"=="shared" set library=shared_library&goto arg-ok if /i "%1"=="static" set library=static_library&goto arg-ok :arg-ok @@ -49,6 +49,7 @@ if not exist "%VS140COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2013 call "%VS140COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% set GYP_MSVS_VERSION=2015 +echo Using Visual Studio 2015 goto select-target :vc-set-2013 @@ -57,6 +58,7 @@ if not exist "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2012 call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% set GYP_MSVS_VERSION=2013 +echo Using Visual Studio 2013 goto select-target :vc-set-2012 @@ -65,6 +67,7 @@ if not exist "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2010 call "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% set GYP_MSVS_VERSION=2012 +echo Using Visual Studio 2012 goto select-target :vc-set-2010 @@ -73,6 +76,7 @@ if not exist "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2008 call "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% set GYP_MSVS_VERSION=2010 +echo Using Visual Studio 2010 goto select-target :vc-set-2008 @@ -81,6 +85,7 @@ if not exist "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-notfound call "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset% set GYP_MSVS_VERSION=2008 +echo Using Visual Studio 2008 goto select-target :vc-set-notfound @@ -127,7 +132,7 @@ @rem Build the sln with msbuild. :msbuild-found -msbuild uv.sln /t:%target% /p:Configuration=%config% /p:Platform="%platform%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo +msbuild uv.sln /t:%target% /p:Configuration=%config% /p:Platform="%msbuild_platform%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo if errorlevel 1 exit /b 1 :run