diff --git a/deps/uv/.gitignore b/deps/uv/.gitignore index 14a174adf63d..1eaaca8406e9 100644 --- a/deps/uv/.gitignore +++ b/deps/uv/.gitignore @@ -34,9 +34,6 @@ vgcore.* Makefile Makefile.in -# Generated by dtrace(1) when doing an in-tree build. -/include/uv-dtrace.h - # Generated by gyp for android *.target.mk @@ -52,7 +49,10 @@ Makefile.in /test/run-benchmarks.dSYM *.sln +*.sln.cache +*.ncb *.vcproj +*.vcproj*.user *.vcxproj *.vcxproj.filters *.vcxproj.user @@ -67,3 +67,6 @@ ipch *.xcodeproj *.xcworkspace + +# make dist output +libuv-*.tar.* diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index 34f5e4daf350..0a152ba8dbb0 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.mailmap @@ -14,15 +14,12 @@ Isaac Z. Schlueter Justin Venus Keno Fischer Keno Fischer +Leith Bade Leonard Hecker Maciej Małecki Marc Schlaich -Rasmus Christian Pedersen -Rasmus Christian Pedersen -Rasmus Christian Pedersen -Rasmus Christian Pedersen +Rasmus Christian Pedersen Rasmus Christian Pedersen -Rasmus Pedersen Robert Mustacchi Ryan Dahl Ryan Emery diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 02d94589d64f..6929fff222cd 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -173,5 +173,11 @@ Michael Ira Krufky Helge Deller Joey Geralnik Tim Caswell -Michael Hudson-Doyle -Helge Deller +Logan Rosen +Kenneth Perry +John Marino +Alexey Melnichuk +Johan Bergström +Alex Mo +Luis Martinez de Bartolome +Michael Penick diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index e2169998429e..7bbe5027a7aa 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,267 @@ +2015.02.27, Version 1.4.2 (Stable) + +Changes since version 1.4.1: + +* stream: ignore EINVAL for SO_OOBINLINE on OS X (Fedor Indutny) + + +2015.02.25, Version 1.4.1 (Stable), e8e3fc5789cc0f02937879d141cca0411274093c + +Changes since version 1.4.0: + +* win: don't use inline keyword in thread.c (Ben Noordhuis) + +* windows: fix setting dirent types on uv_fs_scandir_next (Saúl Ibarra + Corretgé) + +* unix,windows: make uv_thread_create() return errno (Ben Noordhuis) + +* tty: fix build for SmartOS (Julien Gilli) + +* unix: fix for uv_async data race (Michael Penick) + +* unix, windows: map EHOSTDOWN errno (Ben Noordhuis) + +* stream: use SO_OOBINLINE on OS X (Fedor Indutny) + + +2015.02.10, Version 1.4.0 (Stable), 19fb8a90648f3763240db004b77ab984264409be + +Changes since version 1.3.0: + +* unix: check Android support for pthread_cond_timedwait_monotonic_np (Leith + Bade) + +* test: use modified path in test (cjihrig) + +* unix: implement uv_stream_set_blocking() (Ben Noordhuis) + + +2015.01.29, Version 1.3.0 (Stable), 165685b2a9a42cf96501d79cd6d48a18aaa16e3b + +Changes since version 1.2.1: + +* unix, windows: set non-block mode in uv_poll_init (Saúl Ibarra Corretgé) + +* doc: clarify which flags are supported in uv_fs_event_start (Saúl Ibarra + Corretgé) + +* win,unix: move loop functions which have identical implementations (Andrius + Bentkus) + +* doc: explain how the threadpool is allocated (Alex Mo) + +* doc: clarify uv_default_loop (Saúl Ibarra Corretgé) + +* unix: fix implicit declaration compiler warning (Ben Noordhuis) + +* unix: fix long line introduced in commit 94e628fa (Ben Noordhuis) + +* unix, win: add synchronous uv_get{addr,name}info (Saúl Ibarra Corretgé) + +* linux: fix epoll_pwait() regression with < 2.6.19 (Ben Noordhuis) + +* build: compile -D_GNU_SOURCE on linux (Ben Noordhuis) + +* build: use -fvisibility=hidden in autotools build (Ben Noordhuis) + +* fs, pipe: no trailing terminator in exact sized buffers (Andrius Bentkus) + +* style: rename buf to buffer and len to size for consistency (Andrius Bentkus) + +* test: fix test-spawn on MinGW32 (Luis Martinez de Bartolome) + +* win, pipe: fix assertion when destroying timer (Andrius Bentkus) + +* win, unix: add pipe_peername implementation (Andrius Bentkus) + + +2015.01.29, Version 0.10.33 (Stable), 7a2253d33ad8215a26c1b34f1952aee7242dd687 + +Changes since version 0.10.32: + +* linux: fix epoll_pwait() regression with < 2.6.19 (Ben Noordhuis) + +* test: back-port uv_loop_configure() test (Ben Noordhuis) + + +2015.01.15, Version 1.2.1 (Stable), 4ca78e989062a1099dc4b9ad182a98e8374134b1 + +Changes since version 1.2.0: + +* unix: remove unused dtrace file (Saúl Ibarra Corretgé) + +* test: skip TTY select test if /dev/tty can't be opened (Saúl Ibarra Corretgé) + +* doc: clarify the behavior of uv_tty_init (Saúl Ibarra Corretgé) + +* doc: clarify how uv_async_send behaves (Saúl Ibarra Corretgé) + +* build: make dist now generates a full tarball (Johan Bergström) + +* freebsd: make uv_exepath more resilient (Saúl Ibarra Corretgé) + +* unix: make setting the tty mode to the same value a no-op (Saúl Ibarra + Corretgé) + +* win,tcp: support uv_try_write (Bert Belder) + +* test: enable test-tcp-try-write on windows (Bert Belder) + +* win,tty: support uv_try_write (Bert Belder) + +* unix: set non-block mode in uv_{pipe,tcp,udp}_open (Ben Noordhuis) + + +2015.01.06, Version 1.2.0 (Stable), 09f25b13cd149c7981108fc1a75611daf1277f83 + +Changes since version 1.1.0: + +* linux: fix epoll_pwait() sigmask size calculation (Ben Noordhuis) + +* tty: implement binary I/O terminal mode (Yuri D'Elia) + +* test: fix spawn test with autotools build (Ben Noordhuis) + +* test: skip ipv6 tests when ipv6 is not supported (Ben Noordhuis) + +* common: move STATIC_ASSERT to uv-common.h (Alexey Melnichuk) + +* win/thread: store thread handle in a TLS slot (Alexey Melnichuk) + +* unix: fix ttl, multicast ttl and loop options on IPv6 (Saúl Ibarra Corretgé) + +* linux: fix support for preadv/pwritev-less kernels (Ben Noordhuis) + +* unix: make uv_exepath(size=0) return UV_EINVAL (Ben Noordhuis) + +* darwin: fix uv_exepath(smallbuf) UV_EPERM error (Ben Noordhuis) + +* openbsd: fix uv_exepath(smallbuf) UV_EINVAL error (Ben Noordhuis) + +* linux: fix uv_exepath(size=1) UV_EINVAL error (Ben Noordhuis) + +* sunos: preemptively fix uv_exepath(size=1) (Ben Noordhuis) + +* win: fix and clarify comments in winapi.h (Bert Belder) + +* win: make available NtQueryDirectoryFile (Bert Belder) + +* win: add definitions for directory information types (Bert Belder) + +* win: use NtQueryDirectoryFile to implement uv_fs_scandir (Bert Belder) + +* unix: don't unlink unix socket on bind error (Ben Noordhuis) + +* build: fix bad comment in autogen.sh (Ben Noordhuis) + +* build: add AC_PROG_LIBTOOL to configure.ac (Ben Noordhuis) + +* test: skip udp_options6 if there no IPv6 support (Saúl Ibarra Corretgé) + +* win: add definitions for MUI errors mingw lacks (Bert Belder) + +* build: enable warnings in autotools build (Ben Noordhuis) + +* build: remove -Wno-dollar-in-identifier-extension (Ben Noordhuis) + +* build: move flags from Makefile.am to configure.ac (Ben Noordhuis) + + +2015.01.06, Version 0.10.32 (Stable), 378de30c59aef5fdb6d130fa5cfcb0a68fce571c + +Changes since version 0.10.31: + +* linux: fix epoll_pwait() sigmask size calculation (Ben Noordhuis) + + +2014.12.25, Version 1.1.0 (Stable), 9572f3e74a167f59a8017e57ca3ebe91ffd88e18 + +Changes since version 1.0.2: + +* test: test that closing a poll handle doesn't corrupt the stack (Bert Belder) + +* win: fix compilation of tests (Marc Schlaich) + +* Revert "win: keep a reference to AFD_POLL_INFO in cancel poll" (Bert Belder) + +* win: avoid stack corruption when closing a poll handle (Bert Belder) + +* test: fix test-fs-file-loop on Windows (Bert Belder) + +* test: fix test-cwd-and-chdir (Bert Belder) + +* doc: indicate what version uv_loop_configure was added on (Saúl Ibarra + Corretgé) + +* doc: fix sphinx warning (Saúl Ibarra Corretgé) + +* test: skip spawn_setuid_setgid if we get EACCES (Saúl Ibarra Corretgé) + +* test: silence some Clang warnings (Saúl Ibarra Corretgé) + +* test: relax osx_select_many_fds (Saúl Ibarra Corretgé) + +* test: fix compilation warnings when building with Clang (Saúl Ibarra + Corretgé) + +* win: fix autotools build of tests (Luis Lavena) + +* gitignore: ignore Visual Studio files (Marc Schlaich) + +* win: set fallback message if FormatMessage fails (Marc Schlaich) + +* win: fall back to default language in uv_dlerror (Marc Schlaich) + +* test: improve compatibility for dlerror test (Marc Schlaich) + +* test: check dlerror is "no error" in no error case (Marc Schlaich) + +* unix: change uv_cwd not to return a trailing slash (Saúl Ibarra Corretgé) + +* test: fix cwd_and_chdir test on Unix (Saúl Ibarra Corretgé) + +* test: add uv_cwd output to platform_output test (Saúl Ibarra Corretgé) + +* build: fix dragonflybsd autotools build (John Marino) + +* win: scandir use 'ls' for formatting long strings (Kenneth Perry) + +* build: remove clang and gcc_version gyp defines (Ben Noordhuis) + +* unix, windows: don't treat uv_run_mode as a bitmask (Saúl Ibarra Corretgé) + +* unix, windows: fix UV_RUN_ONCE mode if progress was made (Saúl Ibarra + Corretgé) + + +2014.12.25, Version 0.10.31 (Stable), 4dbd27e2219069a6daa769fb37f98673b77b4261 + +Changes since version 0.10.30: + +* test: test that closing a poll handle doesn't corrupt the stack (Bert Belder) + +* win: fix compilation of tests (Marc Schlaich) + +* Revert "win: keep a reference to AFD_POLL_INFO in cancel poll" (Bert Belder) + +* win: avoid stack corruption when closing a poll handle (Bert Belder) + +* gitignore: ignore Visual Studio files (Marc Schlaich) + +* win: set fallback message if FormatMessage fails (Marc Schlaich) + +* win: fall back to default language in uv_dlerror (Marc Schlaich) + +* test: improve compatibility for dlerror test (Marc Schlaich) + +* test: check dlerror is "no error" in no error case (Marc Schlaich) + +* build: link against -pthread (Logan Rosen) + +* win: scandir use 'ls' for formatting long strings (Kenneth Perry) + + 2014.12.10, Version 1.0.2 (Stable), eec671f0059953505f9a3c9aeb7f9f31466dd7cd Changes since version 1.0.1: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 371df711d656..9c511db47a6c 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -34,6 +34,8 @@ libuv_la_SOURCES = src/fs-poll.c \ src/version.c if SUNOS +# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers +# on other platforms complain that the argument is unused during compilation. libuv_la_CFLAGS += -pthread endif @@ -81,7 +83,6 @@ else # WINNT include_HEADERS += include/uv-unix.h AM_CPPFLAGS += -I$(top_srcdir)/src/unix -libuv_la_CFLAGS += -g --std=gnu89 -pedantic -Wall -Wextra -Wno-unused-parameter libuv_la_SOURCES += src/unix/async.c \ src/unix/atomic-ops.h \ src/unix/core.c \ @@ -107,7 +108,24 @@ libuv_la_SOURCES += src/unix/async.c \ endif # WINNT EXTRA_DIST = test/fixtures/empty_file \ - test/fixtures/load_error.node + test/fixtures/load_error.node \ + include \ + test \ + docs \ + img \ + samples \ + android-configure \ + CONTRIBUTING.md \ + LICENSE \ + README.md \ + checksparse.sh \ + vcbuild.bat \ + Makefile.mingw \ + common.gypi \ + gyp_uv.py \ + uv.gyp + + TESTS = test/run-tests check_PROGRAMS = test/run-tests @@ -159,6 +177,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-loop-close.c \ test/test-loop-stop.c \ test/test-loop-time.c \ + test/test-loop-configure.c \ test/test-multiple-listen.c \ test/test-mutexes.c \ test/test-osx-select.c \ @@ -170,8 +189,10 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-pipe-sendmsg.c \ test/test-pipe-server-close.c \ test/test-pipe-close-stdout-read-stdin.c \ + test/test-pipe-set-non-blocking.c \ test/test-platform-output.c \ test/test-poll-close.c \ + test/test-poll-close-doesnt-corrupt-stack.c \ test/test-poll-closesocket.c \ test/test-poll.c \ test/test-process-title.c \ @@ -201,6 +222,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-tcp-read-stop.c \ test/test-tcp-shutdown-after-write.c \ test/test-tcp-unexpected-read.c \ + test/test-tcp-oob.c \ test/test-tcp-write-to-half-open-connection.c \ test/test-tcp-write-after-connect.c \ test/test-tcp-writealot.c \ @@ -274,7 +296,6 @@ endif if DRAGONFLY include_HEADERS += include/uv-bsd.h -libuv_la_SOURCES += src/unix/kqueue.c src/unix/freebsd.c endif if FREEBSD @@ -284,6 +305,7 @@ endif if LINUX include_HEADERS += include/uv-linux.h +libuv_la_CFLAGS += -D_GNU_SOURCE libuv_la_SOURCES += src/unix/linux-core.c \ src/unix/linux-inotify.c \ src/unix/linux-syscalls.c \ diff --git a/deps/uv/README.md b/deps/uv/README.md index 7b67d4172a3a..a267f0d5b527 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -46,15 +46,6 @@ SemVer. libuv will keep a stable ABI across major releases. ## Documentation - * [include/uv.h](https://github.com/libuv/libuv/blob/master/include/uv.h) - — API documentation in the form of detailed header comments. - * [An Introduction to libuv](http://nikhilm.github.com/uvbook/) — An - overview of libuv with tutorials. - * [LXJS 2012 talk](http://www.youtube.com/watch?v=nGn60vDSxQ4) - High-level - introductory talk about libuv. - * [Tests and benchmarks](https://github.com/libuv/libuv/tree/master/test) - - API specification and usage examples. - ### Official API documentation Located in the docs/ subdirectory. It uses the [Sphinx](http://sphinx-doc.org/) diff --git a/deps/uv/autogen.sh b/deps/uv/autogen.sh index 751b4f556249..0574778a4e10 100755 --- a/deps/uv/autogen.sh +++ b/deps/uv/autogen.sh @@ -33,7 +33,7 @@ UV_EXTRA_AUTOMAKE_FLAGS= if test "$automake_version_major" -gt 1 || \ test "$automake_version_major" -eq 1 && \ test "$automake_version_minor" -gt 11; then - # serial-tests is available in v0.12 and newer. + # serial-tests is available in v1.12 and newer. UV_EXTRA_AUTOMAKE_FLAGS="$UV_EXTRA_AUTOMAKE_FLAGS serial-tests" fi echo "m4_define([UV_EXTRA_AUTOMAKE_FLAGS], [$UV_EXTRA_AUTOMAKE_FLAGS])" \ diff --git a/deps/uv/checksparse.sh b/deps/uv/checksparse.sh index d2dc3a5982a2..9442c202eabe 100755 --- a/deps/uv/checksparse.sh +++ b/deps/uv/checksparse.sh @@ -145,6 +145,7 @@ test/test-tcp-open.c test/test-tcp-read-stop.c test/test-tcp-shutdown-after-write.c test/test-tcp-unexpected-read.c +test/test-tcp-oob.c test/test-tcp-write-error.c test/test-tcp-write-to-half-open-connection.c test/test-tcp-writealot.c diff --git a/deps/uv/common.gypi b/deps/uv/common.gypi index a8e2ef44c613..ecf9475234f3 100644 --- a/deps/uv/common.gypi +++ b/deps/uv/common.gypi @@ -6,8 +6,6 @@ 'uv_library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds 'component%': 'static_library', # NB. these names match with what V8 expects 'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way - 'gcc_version%': 'unknown', - 'clang%': 0, }, 'target_defaults': { @@ -158,7 +156,7 @@ 'cflags': [ '-pthread' ], 'ldflags': [ '-pthread' ], }], - [ 'visibility=="hidden" and (clang==1 or gcc_version >= 40)', { + [ 'visibility=="hidden"', { 'cflags': [ '-fvisibility=hidden' ], }], ], diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index 6ae53cc9164f..9473d5ffcb09 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.0.2], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.4.2], [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]) @@ -24,9 +24,17 @@ AC_ENABLE_SHARED AC_ENABLE_STATIC AC_PROG_CC AM_PROG_CC_C_O -CC_CHECK_CFLAGS_APPEND([-Wno-dollar-in-identifier-extension]) +CC_CHECK_CFLAGS_APPEND([-fvisibility=hidden]) +CC_CHECK_CFLAGS_APPEND([-g]) +CC_CHECK_CFLAGS_APPEND([-std=gnu89]) +CC_CHECK_CFLAGS_APPEND([-pedantic]) +CC_CHECK_CFLAGS_APPEND([-Wall]) +CC_CHECK_CFLAGS_APPEND([-Wextra]) +CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter]) # AM_PROG_AR is not available in automake v0.11 but it's essential in v0.12. m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) +# autoconf complains if AC_PROG_LIBTOOL precedes AM_PROG_AR. +AC_PROG_LIBTOOL m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) LT_INIT # TODO(bnoordhuis) Check for -pthread vs. -pthreads diff --git a/deps/uv/docs/Makefile b/deps/uv/docs/Makefile new file mode 100644 index 000000000000..1e0fc8f0220e --- /dev/null +++ b/deps/uv/docs/Makefile @@ -0,0 +1,178 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build +SRCDIR = src + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRCDIR) +# 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 + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @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" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/libuv.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/libuv.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/libuv" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/libuv" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/deps/uv/docs/make.bat b/deps/uv/docs/make.bat index 10eb94b013b7..aa7089ab5cf2 100644 --- a/deps/uv/docs/make.bat +++ b/deps/uv/docs/make.bat @@ -1,243 +1,243 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=build -set SRCDIR=src -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% %SRCDIR% -set I18NSPHINXOPTS=%SPHINXOPTS% %SRCDIR% -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% - set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - 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 - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. texinfo to make Texinfo files - echo. gettext to make PO message catalogs - echo. changes to make an overview over all changed/added/deprecated items - echo. xml to make Docutils-native XML files - echo. pseudoxml to make pseudoxml-XML files for display purposes - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - - -%SPHINXBUILD% 2> nul -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\libuv.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\libuv.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdf" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdfja" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf-ja - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. - goto end -) - -if "%1" == "gettext" ( - %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -if "%1" == "xml" ( - %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The XML files are in %BUILDDIR%/xml. - goto end -) - -if "%1" == "pseudoxml" ( - %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. - goto end -) - -:end +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=build +set SRCDIR=src +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% %SRCDIR% +set I18NSPHINXOPTS=%SPHINXOPTS% %SRCDIR% +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + 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 + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\libuv.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\libuv.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/deps/uv/docs/src/async.rst b/deps/uv/docs/src/async.rst index 7afc92a71bcc..5c400458244a 100644 --- a/deps/uv/docs/src/async.rst +++ b/deps/uv/docs/src/async.rst @@ -48,9 +48,10 @@ API .. warning:: libuv will coalesce calls to :c:func:`uv_async_send`, that is, not every call to it will - yield an execution of the callback, the only guarantee is that it will be called at least - once. Thus, calling this function may not wakeup the event loop if it was already called - previously within a short period of time. + yield an execution of the callback. For example: if :c:func:`uv_async_send` is called 5 + times in a row before the callback is called, the callback will only be called once. If + :c:func:`uv_async_send` is called again after the callback was called, it will be called + again. .. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/deps/uv/docs/src/dns.rst b/deps/uv/docs/src/dns.rst index d7c889f7adaa..3b15377f91e4 100644 --- a/deps/uv/docs/src/dns.rst +++ b/deps/uv/docs/src/dns.rst @@ -39,6 +39,13 @@ Public members Loop that started this getaddrinfo request and where completion will be reported. Readonly. +.. c:member:: struct addrinfo* uv_getaddrinfo_t.addrinfo + + Pointer to a `struct addrinfo` containing the result. Must be freed by the user + with :c:func:`uv_freeaddrinfo`. + + .. versionchanged:: 1.3.0 the field is declared as public. + .. c:member:: uv_loop_t* uv_getnameinfo_t.loop Loop that started this getnameinfo request and where completion will be @@ -68,6 +75,9 @@ API Call :c:func:`uv_freeaddrinfo` to free the addrinfo structure. + .. versionchanged:: 1.3.0 the callback parameter is now allowed to be NULL, + in which case the request will run **synchronously**. + .. c:function:: void uv_freeaddrinfo(struct addrinfo* ai) Free the struct addrinfo. Passing NULL is allowed and is a no-op. @@ -80,4 +90,7 @@ API callback will get called sometime in the future with the lookup result. Consult `man -s 3 getnameinfo` for more details. + .. versionchanged:: 1.3.0 the callback parameter is now allowed to be NULL, + in which case the request will run **synchronously**. + .. seealso:: The :c:type:`uv_req_t` API functions also apply. diff --git a/deps/uv/docs/src/fs_event.rst b/deps/uv/docs/src/fs_event.rst index 9bc9939fc2ce..681ae52f95c7 100644 --- a/deps/uv/docs/src/fs_event.rst +++ b/deps/uv/docs/src/fs_event.rst @@ -87,16 +87,22 @@ API Start the handle with the given callback, which will watch the specified `path` for changes. `flags` can be an ORed mask of :c:type:`uv_fs_event_flags`. + .. note:: Currently the only supported flag is ``UV_FS_EVENT_RECURSIVE`` and + only on OSX. + .. c:function:: int uv_fs_event_stop(uv_fs_event_t* handle) Stop the handle, the callback will no longer be called. -.. c:function:: int uv_fs_event_getpath(uv_fs_event_t* handle, char* buf, size_t* len) +.. c:function:: int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) Get the path being monitored by the handle. The buffer must be preallocated by the user. Returns 0 on success or an error code < 0 in case of failure. - On success, `buf` will contain the path and `len` its length. If the buffer + On success, `buffer` will contain the path and `size` its length. If the buffer is not big enough UV_ENOBUFS will be returned and len will be set to the required size. + .. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte, + and the buffer is not null terminated. + .. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/deps/uv/docs/src/fs_poll.rst b/deps/uv/docs/src/fs_poll.rst index df3105352143..4efb2440e0ba 100644 --- a/deps/uv/docs/src/fs_poll.rst +++ b/deps/uv/docs/src/fs_poll.rst @@ -58,12 +58,15 @@ API Stop the handle, the callback will no longer be called. -.. c:function:: int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buf, size_t* len) +.. c:function:: int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) Get the path being monitored by the handle. The buffer must be preallocated by the user. Returns 0 on success or an error code < 0 in case of failure. - On success, `buf` will contain the path and `len` its length. If the buffer + On success, `buffer` will contain the path and `size` its length. If the buffer is not big enough UV_ENOBUFS will be returned and len will be set to the required size. + .. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte, + and the buffer is not null terminated. + .. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/deps/uv/docs/src/loop.rst b/deps/uv/docs/src/loop.rst index 0a9e8a608699..203672bd34f0 100644 --- a/deps/uv/docs/src/loop.rst +++ b/deps/uv/docs/src/loop.rst @@ -52,6 +52,8 @@ API .. c:function:: int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) + .. versionadded:: 1.0.2 + Set additional loop options. You should normally call this before the first call to :c:func:`uv_run` unless mentioned otherwise. @@ -78,6 +80,12 @@ API Returns the initialized default loop. It may return NULL in case of allocation failure. + This function is just a convenient way for having a global loop throughout + an application, the default loop is in no way different than the ones + initialized with :c:func:`uv_loop_init`. As such, the default loop can (and + should) be closed with :c:func:`uv_loop_close` so the resources associated + with it are freed. + .. c:function:: int uv_run(uv_loop_t* loop, uv_run_mode mode) This function runs the event loop. It will act differently depending on the diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index 4b810fe08475..10c349e9b736 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -2,7 +2,7 @@ .. _misc: Miscellaneous utilities -====================== +======================= This section contains miscellaneous functions that don't really belong in any other section. @@ -207,6 +207,10 @@ API Gets the current working directory. + .. versionchanged:: 1.1.0 + + On Unix the path no longer ends in a slash. + .. c:function:: int uv_chdir(const char* dir) Changes the current working directory. diff --git a/deps/uv/docs/src/pipe.rst b/deps/uv/docs/src/pipe.rst index 614bb2e3b1ff..8f8402c29bba 100644 --- a/deps/uv/docs/src/pipe.rst +++ b/deps/uv/docs/src/pipe.rst @@ -38,8 +38,7 @@ API Open an existing file descriptor or HANDLE as a pipe. - .. note:: - The user is responsible for setting the file descriptor in non-blocking mode. + .. versionchanged:: 1.2.1 the file descriptor is set to non-blocking mode. .. c:function:: int uv_pipe_bind(uv_pipe_t* handle, const char* name) @@ -57,15 +56,30 @@ API Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between 92 and 108 bytes. -.. c:function:: int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) +.. c:function:: int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) Get the name of the Unix domain socket or the named pipe. - A preallocated buffer must be provided. The len parameter holds the length + A preallocated buffer must be provided. The size parameter holds the length of the buffer and it's set to the number of bytes written to the buffer on output. If the buffer is not big enough ``UV_ENOBUFS`` will be returned and len will contain the required size. + .. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte, + and the buffer is not null terminated. + +.. c:function:: int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) + + Get the name of the Unix domain socket or the named pipe to which the handle + is connected. + + A preallocated buffer must be provided. The size parameter holds the length + of the buffer and it's set to the number of bytes written to the buffer on + output. If the buffer is not big enough ``UV_ENOBUFS`` will be returned and + len will contain the required size. + + .. versionadded:: 1.3.0 + .. c:function:: void uv_pipe_pending_instances(uv_pipe_t* handle, int count) Set the number of pending pipe instance handles when the pipe server is diff --git a/deps/uv/docs/src/poll.rst b/deps/uv/docs/src/poll.rst index f34842256b62..907cb1a613df 100644 --- a/deps/uv/docs/src/poll.rst +++ b/deps/uv/docs/src/poll.rst @@ -70,11 +70,15 @@ API Initialize the handle using a file descriptor. + .. versionchanged:: 1.2.2 the file descriptor is set to non-blocking mode. + .. c:function:: int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, uv_os_sock_t socket) Initialize the handle using a socket descriptor. On Unix this is identical to :c:func:`uv_poll_init`. On windows it takes a SOCKET handle. + .. versionchanged:: 1.2.2 the socket is set to non-blocking mode. + .. 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 diff --git a/deps/uv/docs/src/stream.rst b/deps/uv/docs/src/stream.rst index 2c669cf0418f..1f6682adc1cf 100644 --- a/deps/uv/docs/src/stream.rst +++ b/deps/uv/docs/src/stream.rst @@ -206,12 +206,14 @@ API Relying too much on this API is not recommended. It is likely to change significantly in the future. - Currently this only works on Windows and only for - :c:type:`uv_pipe_t` handles. + Currently only works on Windows for :c:type:`uv_pipe_t` handles. + On UNIX platforms, all :c:type:`uv_stream_t` handles are supported. Also libuv currently makes no ordering guarantee when the blocking mode is changed after write requests have already been submitted. Therefore it is recommended to set the blocking mode immediately after opening or creating the stream. + .. versionchanged:: 1.4.0 UNIX implementation added. + .. seealso:: The :c:type:`uv_handle_t` API functions also apply. diff --git a/deps/uv/docs/src/tcp.rst b/deps/uv/docs/src/tcp.rst index 2c1001b531fd..8baedde86c5c 100644 --- a/deps/uv/docs/src/tcp.rst +++ b/deps/uv/docs/src/tcp.rst @@ -36,9 +36,7 @@ API Open an existing file descriptor or SOCKET as a TCP handle. - .. note:: - The user is responsible for setting the file descriptor in - non-blocking mode. + .. versionchanged:: 1.2.1 the file descriptor is set to non-blocking mode. .. c:function:: int uv_tcp_nodelay(uv_tcp_t* handle, int enable) diff --git a/deps/uv/docs/src/threading.rst b/deps/uv/docs/src/threading.rst index aab13f84b627..e876dde1256d 100644 --- a/deps/uv/docs/src/threading.rst +++ b/deps/uv/docs/src/threading.rst @@ -56,6 +56,9 @@ Threads ^^^^^^^ .. c:function:: int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg) + + .. versionchanged:: 1.4.1 returns a UV_E* error code on failure + .. c:function:: uv_thread_t uv_thread_self(void) .. c:function:: int uv_thread_join(uv_thread_t *tid) .. c:function:: int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) diff --git a/deps/uv/docs/src/threadpool.rst b/deps/uv/docs/src/threadpool.rst index 66ff53e23059..89f00844ef2c 100644 --- a/deps/uv/docs/src/threadpool.rst +++ b/deps/uv/docs/src/threadpool.rst @@ -12,7 +12,11 @@ Its default size is 4, but it can be changed at startup time by setting the ``UV_THREADPOOL_SIZE`` environment variable to any value (the absolute maximum is 128). -The threadpool is global and shared across all event loops. +The threadpool is global and shared across all event loops. When a particular +function makes use of the threadpool (i.e. when using :c:func:`uv_queue_work`) +libuv preallocates and initializes the maximum number of threads allowed by +``UV_THREADPOOL_SIZE``. This causes a relatively minor memory overhead +(~1MB for 128 threads) but increases the performance of threading at runtime. Data types diff --git a/deps/uv/docs/src/tty.rst b/deps/uv/docs/src/tty.rst index 8cb006632038..6c20c84bf75e 100644 --- a/deps/uv/docs/src/tty.rst +++ b/deps/uv/docs/src/tty.rst @@ -16,6 +16,24 @@ Data types TTY handle type. +.. c:type:: uv_tty_mode_t + + .. versionadded:: 1.2.0 + + TTY mode type: + + :: + + typedef enum { + /* Initial/normal terminal mode */ + UV_TTY_MODE_NORMAL, + /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */ + UV_TTY_MODE_RAW, + /* Binary-safe I/O mode for IPC (Unix-only) */ + UV_TTY_MODE_IO + } uv_tty_mode_t; + + Public members ^^^^^^^^^^^^^^ @@ -40,12 +58,20 @@ API `readable`, specifies if you plan on calling :c:func:`uv_read_start` with this stream. stdin is readable, stdout is not. + On Unix this function will try to open ``/dev/tty`` and use it if the passed file + descriptor refers to a TTY. This lets libuv put the tty in non-blocking mode + without affecting other processes that share the tty. + .. note:: - TTY streams which are not readable have blocking writes. + If opening ``/dev/tty`` fails, libuv falls back to blocking writes for non-readable + TTY streams. + +.. c:function:: int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode) -.. c:function:: int uv_tty_set_mode(uv_tty_t*, int mode) + .. versionchanged:: 1.2.0: the mode is specified as a :c:type:`uv_tty_mode_t` + value. - Set the TTY mode. 0 for normal, 1 for raw. + Set the TTY using the specified terminal mode. .. c:function:: int uv_tty_reset_mode(void) diff --git a/deps/uv/docs/src/udp.rst b/deps/uv/docs/src/udp.rst index 175ce07a2dbd..9c4aa2102bdc 100644 --- a/deps/uv/docs/src/udp.rst +++ b/deps/uv/docs/src/udp.rst @@ -120,6 +120,8 @@ API In other words, other datagram-type sockets like raw sockets or netlink sockets can also be passed to this function. + .. versionchanged:: 1.2.1 the file descriptor is set to non-blocking mode. + .. c:function:: int uv_udp_bind(uv_udp_t* handle, const struct sockaddr* addr, unsigned int flags) Bind the UDP handle to an IP address and port. diff --git a/deps/uv/gyp_uv.py b/deps/uv/gyp_uv.py index f5afc6da2d6b..0491ff873f1a 100755 --- a/deps/uv/gyp_uv.py +++ b/deps/uv/gyp_uv.py @@ -1,9 +1,7 @@ #!/usr/bin/env python -import glob -import platform import os -import subprocess +import platform import sys try: @@ -35,16 +33,6 @@ def host_arch(): return machine # Return as-is and hope for the best. -def compiler_version(): - proc = subprocess.Popen(CC.split() + ['--version'], stdout=subprocess.PIPE) - is_clang = 'clang' in proc.communicate()[0].split('\n')[0] - proc = subprocess.Popen(CC.split() + ['-dumpversion'], stdout=subprocess.PIPE) - version = proc.communicate()[0].split('.') - version = map(int, version[:2]) - version = tuple(version) - return (version, is_clang) - - def run_gyp(args): rc = gyp.main(args) if rc != 0: @@ -85,9 +73,6 @@ def run_gyp(args): if 'eclipse' not in args and 'ninja' not in args: args.extend(['-Goutput_dir=' + output_dir]) args.extend(['--generator-output', output_dir]) - (major, minor), is_clang = compiler_version() - args.append('-Dgcc_version=%d' % (10 * major + minor)) - args.append('-Dclang=%d' % int(is_clang)) if not any(a.startswith('-Dhost_arch=') for a in args): args.append('-Dhost_arch=%s' % host_arch()) diff --git a/deps/uv/include/uv-errno.h b/deps/uv/include/uv-errno.h index c34132795cd6..53f30296c1cd 100644 --- a/deps/uv/include/uv-errno.h +++ b/deps/uv/include/uv-errno.h @@ -399,4 +399,20 @@ # define UV__EMLINK (-4032) #endif +/* EHOSTDOWN is not visible on BSD-like systems when _POSIX_C_SOURCE is + * defined. Fortunately, its value is always 64 so it's possible albeit + * icky to hard-code it. + */ +#if defined(EHOSTDOWN) && !defined(_WIN32) +# define UV__EHOSTDOWN (-EHOSTDOWN) +#elif defined(__APPLE__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__OpenBSD__) +# define UV__EHOSTDOWN (-64) +#else +# define UV__EHOSTDOWN (-4031) +#endif + #endif /* UV_ERRNO_H_ */ diff --git a/deps/uv/include/uv-unix.h b/deps/uv/include/uv-unix.h index e72492564db3..82d193bdca4f 100644 --- a/deps/uv/include/uv-unix.h +++ b/deps/uv/include/uv-unix.h @@ -326,7 +326,7 @@ typedef struct { struct addrinfo* hints; \ char* hostname; \ char* service; \ - struct addrinfo* res; \ + struct addrinfo* addrinfo; \ int retcode; #define UV_GETNAMEINFO_PRIVATE_FIELDS \ diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h index 25c31ab5e109..b53f9c5ca056 100644 --- a/deps/uv/include/uv-version.h +++ b/deps/uv/include/uv-version.h @@ -31,9 +31,9 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 0 +#define UV_VERSION_MINOR 4 #define UV_VERSION_PATCH 2 -#define UV_VERSION_IS_RELEASE 1 -#define UV_VERSION_SUFFIX "" +#define UV_VERSION_IS_RELEASE 0 +#define UV_VERSION_SUFFIX "node1" #endif /* UV_VERSION_H */ diff --git a/deps/uv/include/uv-win.h b/deps/uv/include/uv-win.h index 0c188e7e22af..24b22b31a956 100644 --- a/deps/uv/include/uv-win.h +++ b/deps/uv/include/uv-win.h @@ -294,6 +294,7 @@ typedef struct uv__dirent_s { char d_name[1]; } uv__dirent_t; +#define HAVE_DIRENT_TYPES #define UV__DT_DIR UV_DIRENT_DIR #define UV__DT_FILE UV_DIRENT_FILE #define UV__DT_LINK UV_DIRENT_LINK @@ -517,10 +518,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); /* Used in fast mode */ \ SOCKET peer_socket; \ AFD_POLL_INFO afd_poll_info_1; \ - union { \ - AFD_POLL_INFO* afd_poll_info_ptr; \ - AFD_POLL_INFO afd_poll_info; \ - } afd_poll_info_2; \ + AFD_POLL_INFO afd_poll_info_2; \ /* Used in fast and slow mode. */ \ uv_req_t poll_req_1; \ uv_req_t poll_req_2; \ @@ -568,8 +566,11 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); void* alloc; \ WCHAR* node; \ WCHAR* service; \ - struct addrinfoW* hints; \ - struct addrinfoW* res; \ + /* The addrinfoW field is used to store a pointer to the hints, and */ \ + /* later on to store the result of GetAddrInfoW. The final result will */ \ + /* be converted to struct addrinfo* and stored in the addrinfo field. */ \ + struct addrinfoW* addrinfow; \ + struct addrinfo* addrinfo; \ int retcode; #define UV_GETNAMEINFO_PRIVATE_FIELDS \ diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 7b3c25223b29..55f75218b586 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -138,6 +138,7 @@ extern "C" { XX(EOF, "end of file") \ XX(ENXIO, "no such device or address") \ XX(EMLINK, "too many links") \ + XX(EHOSTDOWN, "host is down") \ #define UV_HANDLE_TYPE_MAP(XX) \ XX(ASYNC, async) \ @@ -628,11 +629,30 @@ struct uv_tty_s { UV_TTY_PRIVATE_FIELDS }; +typedef enum { + /* Initial/normal terminal mode */ + UV_TTY_MODE_NORMAL, + /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */ + UV_TTY_MODE_RAW, + /* Binary-safe I/O mode for IPC (Unix-only) */ + UV_TTY_MODE_IO +} uv_tty_mode_t; + UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable); -UV_EXTERN int uv_tty_set_mode(uv_tty_t*, int mode); +UV_EXTERN int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode); UV_EXTERN int uv_tty_reset_mode(void); UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); +#ifdef __cplusplus +} /* extern "C" */ + +inline int uv_tty_set_mode(uv_tty_t* handle, int mode) { + return uv_tty_set_mode(handle, static_cast(mode)); +} + +extern "C" { +#endif + UV_EXTERN uv_handle_type uv_guess_handle(uv_file file); /* @@ -656,8 +676,11 @@ UV_EXTERN void uv_pipe_connect(uv_connect_t* req, const char* name, uv_connect_cb cb); UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle, - char* buf, - size_t* len); + char* buffer, + size_t* size); +UV_EXTERN int uv_pipe_getpeername(const uv_pipe_t* handle, + char* buffer, + size_t* size); UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count); UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle); UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle); @@ -753,6 +776,7 @@ struct uv_getaddrinfo_s { UV_REQ_FIELDS /* read-only */ uv_loop_t* loop; + /* struct addrinfo* addrinfo is marked as private, but it really isn't. */ UV_GETADDRINFO_PRIVATE_FIELDS }; @@ -1241,7 +1265,9 @@ UV_EXTERN int uv_fs_poll_start(uv_fs_poll_t* handle, const char* path, unsigned int interval); UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle); -UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buf, size_t* len); +UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle, + char* buffer, + size_t* size); struct uv_signal_s { @@ -1298,8 +1324,8 @@ UV_EXTERN int uv_fs_event_start(uv_fs_event_t* handle, unsigned int flags); UV_EXTERN int uv_fs_event_stop(uv_fs_event_t* handle); UV_EXTERN int uv_fs_event_getpath(uv_fs_event_t* handle, - char* buf, - size_t* len); + char* buffer, + size_t* size); UV_EXTERN int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr); UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr); diff --git a/deps/uv/m4/dtrace.m4 b/deps/uv/m4/dtrace.m4 deleted file mode 100644 index 09f7dc89cf56..000000000000 --- a/deps/uv/m4/dtrace.m4 +++ /dev/null @@ -1,66 +0,0 @@ -dnl Copyright (C) 2009 Sun Microsystems -dnl This file is free software; Sun Microsystems -dnl gives unlimited permission to copy and/or distribute it, -dnl with or without modifications, as long as this notice is preserved. - -dnl --------------------------------------------------------------------------- -dnl Macro: PANDORA_ENABLE_DTRACE -dnl --------------------------------------------------------------------------- -AC_DEFUN([PANDORA_ENABLE_DTRACE],[ - AC_ARG_ENABLE([dtrace], - [AS_HELP_STRING([--disable-dtrace], - [enable DTrace USDT probes. @<:@default=yes@:>@])], - [ac_cv_enable_dtrace="$enableval"], - [ac_cv_enable_dtrace="yes"]) - - AS_IF([test "$ac_cv_enable_dtrace" = "yes"],[ - AC_CHECK_PROGS([DTRACE], [dtrace]) - AS_IF([test "x$ac_cv_prog_DTRACE" = "xdtrace"],[ - - AC_CACHE_CHECK([if dtrace works],[ac_cv_dtrace_works],[ - cat >conftest.d <<_ACEOF -provider Example { - probe increment(int); -}; -_ACEOF - $DTRACE -h -o conftest.h -s conftest.d 2>/dev/zero - AS_IF([test $? -eq 0],[ac_cv_dtrace_works=yes], - [ac_cv_dtrace_works=no]) - rm -f conftest.h conftest.d - ]) - AS_IF([test "x$ac_cv_dtrace_works" = "xyes"],[ - AC_DEFINE([HAVE_DTRACE], [1], [Enables DTRACE Support]) - AC_CACHE_CHECK([if dtrace should instrument object files], - [ac_cv_dtrace_needs_objects],[ - dnl DTrace on MacOSX does not use -G option - cat >conftest.d <<_ACEOF -provider Example { - probe increment(int); -}; -_ACEOF - cat > conftest.c <<_ACEOF -#include "conftest.h" -void foo() { - EXAMPLE_INCREMENT(1); -} -_ACEOF - $DTRACE -h -o conftest.h -s conftest.d 2>/dev/zero - $CC -c -o conftest.o conftest.c - $DTRACE -G -o conftest.d.o -s conftest.d conftest.o 2>/dev/zero - AS_IF([test $? -eq 0],[ac_cv_dtrace_needs_objects=yes], - [ac_cv_dtrace_needs_objects=no]) - rm -f conftest.d.o conftest.d conftest.h conftest.o conftest.c - ]) - ]) - AC_SUBST(DTRACEFLAGS) dnl TODO: test for -G on OSX - ac_cv_have_dtrace=yes - ])]) - -AM_CONDITIONAL([HAVE_DTRACE], [test "x$ac_cv_dtrace_works" = "xyes"]) -AM_CONDITIONAL([DTRACE_NEEDS_OBJECTS], - [test "x$ac_cv_dtrace_needs_objects" = "xyes"]) - -]) -dnl --------------------------------------------------------------------------- -dnl End Macro: PANDORA_ENABLE_DTRACE -dnl --------------------------------------------------------------------------- diff --git a/deps/uv/samples/socks5-proxy/Makefile b/deps/uv/samples/socks5-proxy/Makefile new file mode 100644 index 000000000000..ca43985ec806 --- /dev/null +++ b/deps/uv/samples/socks5-proxy/Makefile @@ -0,0 +1,46 @@ +# Copyright StrongLoop, Inc. 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. + +BUILDTYPE ?= Debug +BUILDDIR ?= build +GYP ?= gyp +V ?= + +SOURCES := client.c defs.h getopt.c main.c s5.c s5.h server.c util.c + +.PHONY: all clean + +all: $(BUILDDIR)/$(BUILDTYPE)/s5-proxy + +clean: + $(RM) $(BUILDDIR) + +$(BUILDDIR)/$(BUILDTYPE)/s5-proxy: $(BUILDDIR)/Makefile $(SOURCES) + $(MAKE) -C $(BUILDDIR) V=$(V) + +$(BUILDDIR)/Makefile: ../../common.gypi build.gyp + $(GYP) \ + -Duv_library=static_library \ + -Goutput_dir=. \ + -I../../common.gypi \ + -f make \ + --depth=. \ + --generator-output=$(BUILDDIR) \ + build.gyp diff --git a/deps/uv/src/fs-poll.c b/deps/uv/src/fs-poll.c index 0de15b1739fd..1145e5fc3443 100644 --- a/deps/uv/src/fs-poll.c +++ b/deps/uv/src/fs-poll.c @@ -125,26 +125,26 @@ int uv_fs_poll_stop(uv_fs_poll_t* handle) { } -int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buf, size_t* len) { +int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) { struct poll_ctx* ctx; size_t required_len; if (!uv__is_active(handle)) { - *len = 0; + *size = 0; return UV_EINVAL; } ctx = handle->poll_ctx; assert(ctx != NULL); - required_len = strlen(ctx->path) + 1; - if (required_len > *len) { - *len = required_len; + required_len = strlen(ctx->path); + if (required_len > *size) { + *size = required_len; return UV_ENOBUFS; } - memcpy(buf, ctx->path, required_len); - *len = required_len; + memcpy(buffer, ctx->path, required_len); + *size = required_len; return 0; } diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c index 349c2b558e4f..ec800c7a323f 100644 --- a/deps/uv/src/unix/aix.c +++ b/deps/uv/src/unix/aix.c @@ -61,7 +61,7 @@ #define RDWR_BUF_SIZE 4096 #define EQ(a,b) (strcmp(a,b) == 0) -int uv__platform_loop_init(uv_loop_t* loop, int default_loop) { +int uv__platform_loop_init(uv_loop_t* loop) { loop->fs_fd = -1; /* Passing maxfd of -1 should mean the limit is determined @@ -294,7 +294,7 @@ int uv_exepath(char* buffer, size_t* size) { int fd; char **argv; - if ((buffer == NULL) || (size == NULL)) + if (buffer == NULL || size == NULL || *size == 0) return -EINVAL; snprintf(pp, sizeof(pp), "/proc/%lu/psinfo", (unsigned long) getpid()); diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c index b794ea6121b1..9ff24aeb3d7d 100644 --- a/deps/uv/src/unix/async.c +++ b/deps/uv/src/unix/async.c @@ -24,6 +24,7 @@ #include "uv.h" #include "internal.h" +#include "atomic-ops.h" #include #include /* snprintf() */ @@ -35,7 +36,6 @@ static void uv__async_event(uv_loop_t* loop, struct uv__async* w, unsigned int nevents); -static int uv__async_make_pending(int* pending); static int uv__async_eventfd(void); @@ -58,7 +58,11 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { int uv_async_send(uv_async_t* handle) { - if (uv__async_make_pending(&handle->pending) == 0) + /* Do a cheap read first. */ + if (ACCESS_ONCE(int, handle->pending) != 0) + return 0; + + if (cmpxchgi(&handle->pending, 0, 1) == 0) uv__async_send(&handle->loop->async_watcher); return 0; @@ -80,9 +84,8 @@ static void uv__async_event(uv_loop_t* loop, QUEUE_FOREACH(q, &loop->async_handles) { h = QUEUE_DATA(q, uv_async_t, queue); - if (h->pending == 0) + if (cmpxchgi(&h->pending, 1, 0) == 0) continue; - h->pending = 0; if (h->async_cb == NULL) continue; @@ -91,37 +94,6 @@ static void uv__async_event(uv_loop_t* loop, } -static int uv__async_make_pending(int* pending) { - /* Do a cheap read first. */ - if (ACCESS_ONCE(int, *pending) != 0) - return 1; - - /* Micro-optimization: use atomic memory operations to detect if we've been - * preempted by another thread and don't have to make an expensive syscall. - * This speeds up the heavily contended case by about 1-2% and has little - * if any impact on the non-contended case. - * - * Use XCHG instead of the CMPXCHG that __sync_val_compare_and_swap() emits - * on x86, it's about 4x faster. It probably makes zero difference in the - * grand scheme of things but I'm OCD enough not to let this one pass. - */ -#if defined(__i386__) || defined(__x86_64__) - { - unsigned int val = 1; - __asm__ __volatile__ ("xchgl %0, %1" - : "+r" (val) - : "m" (*pending)); - return val != 0; - } -#elif defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 0) - return __sync_val_compare_and_swap(pending, 0, 1) != 0; -#else - ACCESS_ONCE(int, *pending) = 1; - return 0; -#endif -} - - static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { struct uv__async* wa; char buf[1024]; diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index c08040e5378f..6f284ffa7aea 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -74,7 +74,7 @@ #include #endif -static void uv__run_pending(uv_loop_t* loop); +static int uv__run_pending(uv_loop_t* loop); /* Verify that uv_buf_t is ABI-compatible with struct iovec. */ STATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec)); @@ -304,6 +304,7 @@ int uv_loop_alive(const uv_loop_t* loop) { int uv_run(uv_loop_t* loop, uv_run_mode mode) { int timeout; int r; + int ran_pending; r = uv__loop_alive(loop); if (!r) @@ -312,12 +313,12 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) { while (r != 0 && loop->stop_flag == 0) { uv__update_time(loop); uv__run_timers(loop); - uv__run_pending(loop); + ran_pending = uv__run_pending(loop); uv__run_idle(loop); uv__run_prepare(loop); timeout = 0; - if ((mode & UV_RUN_NOWAIT) == 0) + if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) timeout = uv_backend_timeout(loop); uv__io_poll(loop, timeout); @@ -338,8 +339,7 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) { } r = uv__loop_alive(loop); - - if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT)) + if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT) break; } @@ -635,6 +635,11 @@ int uv_cwd(char* buffer, size_t* size) { return -errno; *size = strlen(buffer); + if (*size > 1 && buffer[*size - 1] == '/') { + buffer[*size-1] = '\0'; + (*size)--; + } + return 0; } @@ -689,10 +694,13 @@ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) { } -static void uv__run_pending(uv_loop_t* loop) { +static int uv__run_pending(uv_loop_t* loop) { QUEUE* q; uv__io_t* w; + if (QUEUE_EMPTY(&loop->pending_queue)) + return 0; + while (!QUEUE_EMPTY(&loop->pending_queue)) { q = QUEUE_HEAD(&loop->pending_queue); QUEUE_REMOVE(q); @@ -701,6 +709,8 @@ static void uv__run_pending(uv_loop_t* loop) { w = QUEUE_DATA(q, uv__io_t, pending_queue); w->cb(loop, w, UV__POLLOUT); } + + return 1; } diff --git a/deps/uv/src/unix/darwin-proctitle.c b/deps/uv/src/unix/darwin-proctitle.c index b7267caa99df..1142311609fb 100644 --- a/deps/uv/src/unix/darwin-proctitle.c +++ b/deps/uv/src/unix/darwin-proctitle.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -36,7 +37,9 @@ static int uv__pthread_setname_np(const char* name) { int err; /* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */ - *(void **)(&dynamic_pthread_setname_np) = dlsym(RTLD_DEFAULT, "pthread_setname_np"); + *(void **)(&dynamic_pthread_setname_np) = + dlsym(RTLD_DEFAULT, "pthread_setname_np"); + if (dynamic_pthread_setname_np == NULL) return -ENOSYS; diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c index c9a45edee425..d276adac2e7f 100644 --- a/deps/uv/src/unix/darwin.c +++ b/deps/uv/src/unix/darwin.c @@ -37,7 +37,7 @@ #include /* sysconf */ -int uv__platform_loop_init(uv_loop_t* loop, int default_loop) { +int uv__platform_loop_init(uv_loop_t* loop) { loop->cf_state = NULL; if (uv__kqueue_init(loop)) @@ -65,28 +65,33 @@ uint64_t uv__hrtime(uv_clocktype_t type) { int uv_exepath(char* buffer, size_t* size) { - uint32_t usize; - int result; - char* path; - char* fullpath; + /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */ + char abspath[PATH_MAX * 2 + 1]; + char exepath[PATH_MAX + 1]; + uint32_t exepath_size; + size_t abspath_size; - if (buffer == NULL || size == NULL) + if (buffer == NULL || size == NULL || *size == 0) return -EINVAL; - usize = *size; - result = _NSGetExecutablePath(buffer, &usize); - if (result) return result; + exepath_size = sizeof(exepath); + if (_NSGetExecutablePath(exepath, &exepath_size)) + return -EIO; - path = malloc(2 * PATH_MAX); - fullpath = realpath(buffer, path); - if (fullpath == NULL) { - SAVE_ERRNO(free(path)); + if (realpath(exepath, abspath) != abspath) return -errno; - } - strncpy(buffer, fullpath, *size); - free(fullpath); - *size = strlen(buffer); + abspath_size = strlen(abspath); + if (abspath_size == 0) + return -EIO; + + *size -= 1; + if (*size > abspath_size) + *size = abspath_size; + + memcpy(buffer, abspath, *size); + buffer[*size] = '\0'; + return 0; } diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c index d59e3773a557..2dbb1ec169a6 100644 --- a/deps/uv/src/unix/freebsd.c +++ b/deps/uv/src/unix/freebsd.c @@ -58,7 +58,7 @@ static char *process_title; -int uv__platform_loop_init(uv_loop_t* loop, int default_loop) { +int uv__platform_loop_init(uv_loop_t* loop) { return uv__kqueue_init(loop); } @@ -75,10 +75,11 @@ uint64_t uv__hrtime(uv_clocktype_t type) { int uv_exepath(char* buffer, size_t* size) { + char abspath[PATH_MAX * 2 + 1]; int mib[4]; - size_t cb; + size_t abspath_size; - if (buffer == NULL || size == NULL) + if (buffer == NULL || size == NULL || *size == 0) return -EINVAL; #ifdef __DragonFly__ @@ -93,10 +94,19 @@ int uv_exepath(char* buffer, size_t* size) { mib[3] = -1; #endif - cb = *size; - if (sysctl(mib, 4, buffer, &cb, NULL, 0)) + abspath_size = sizeof abspath;; + if (sysctl(mib, 4, abspath, &abspath_size, NULL, 0)) return -errno; - *size = strlen(buffer); + + assert(abspath_size > 0); + abspath_size -= 1; + *size -= 1; + + if (*size > abspath_size) + *size = abspath_size; + + memcpy(buffer, abspath, *size); + buffer[*size] = '\0'; return 0; } diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 65fd01230b3e..e7eee2f9abc4 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -35,8 +35,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -48,30 +50,12 @@ defined(__OpenBSD__) || \ defined(__NetBSD__) # define HAVE_PREADV 1 -#elif defined(__linux__) -# include -# if defined(__GLIBC_PREREQ) -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) && \ - __GLIBC_PREREQ(2,10) -# define HAVE_PREADV 1 -# else -# define HAVE_PREADV 0 -# endif -# else -# define HAVE_PREADV 0 -# endif #else # define HAVE_PREADV 0 #endif #if defined(__linux__) || defined(__sun) # include -#elif defined(__APPLE__) || defined(__FreeBSD__) -# include -#endif - -#if HAVE_PREADV || defined(__APPLE__) -# include #endif #define INIT(type) \ @@ -219,6 +203,9 @@ static ssize_t uv__fs_mkdtemp(uv_fs_t* req) { static ssize_t uv__fs_read(uv_fs_t* req) { +#if defined(__linux__) + static int no_preadv; +#endif ssize_t result; #if defined(_AIX) @@ -245,16 +232,12 @@ static ssize_t uv__fs_read(uv_fs_t* req) { result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off); #else # if defined(__linux__) - static int no_preadv; - if (no_preadv) + if (no_preadv) retry: # endif { off_t nread; size_t index; -# if defined(__linux__) - retry: -# endif nread = 0; index = 0; result = 1; @@ -578,6 +561,9 @@ static ssize_t uv__fs_utime(uv_fs_t* req) { static ssize_t uv__fs_write(uv_fs_t* req) { +#if defined(__linux__) + static int no_pwritev; +#endif ssize_t r; /* Serialize writes on OS X, concurrent write() and pwrite() calls result in @@ -603,16 +589,12 @@ static ssize_t uv__fs_write(uv_fs_t* req) { r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off); #else # if defined(__linux__) - static int no_pwritev; - if (no_pwritev) + if (no_pwritev) retry: # endif { off_t written; size_t index; -# if defined(__linux__) - retry: -# endif written = 0; index = 0; r = 0; diff --git a/deps/uv/src/unix/getaddrinfo.c b/deps/uv/src/unix/getaddrinfo.c index faf9add9285e..0d684e24e1a5 100644 --- a/deps/uv/src/unix/getaddrinfo.c +++ b/deps/uv/src/unix/getaddrinfo.c @@ -99,21 +99,17 @@ static void uv__getaddrinfo_work(struct uv__work* w) { int err; req = container_of(w, uv_getaddrinfo_t, work_req); - err = getaddrinfo(req->hostname, req->service, req->hints, &req->res); + err = getaddrinfo(req->hostname, req->service, req->hints, &req->addrinfo); req->retcode = uv__getaddrinfo_translate_error(err); } static void uv__getaddrinfo_done(struct uv__work* w, int status) { uv_getaddrinfo_t* req; - struct addrinfo *res; req = container_of(w, uv_getaddrinfo_t, work_req); uv__req_unregister(req->loop, req); - res = req->res; - req->res = NULL; - /* See initialization in uv_getaddrinfo(). */ if (req->hints) free(req->hints); @@ -133,7 +129,8 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) { req->retcode = UV_EAI_CANCELED; } - req->cb(req, req->retcode, res); + if (req->cb) + req->cb(req, req->retcode, req->addrinfo); } @@ -149,7 +146,7 @@ int uv_getaddrinfo(uv_loop_t* loop, size_t len; char* buf; - if (req == NULL || cb == NULL || (hostname == NULL && service == NULL)) + if (req == NULL || (hostname == NULL && service == NULL)) return -EINVAL; hostname_len = hostname ? strlen(hostname) + 1 : 0; @@ -163,7 +160,7 @@ int uv_getaddrinfo(uv_loop_t* loop, uv__req_init(loop, req, UV_GETADDRINFO); req->loop = loop; req->cb = cb; - req->res = NULL; + req->addrinfo = NULL; req->hints = NULL; req->service = NULL; req->hostname = NULL; @@ -185,12 +182,17 @@ int uv_getaddrinfo(uv_loop_t* loop, if (hostname) req->hostname = memcpy(buf + len, hostname, hostname_len); - uv__work_submit(loop, - &req->work_req, - uv__getaddrinfo_work, - uv__getaddrinfo_done); - - return 0; + if (cb) { + uv__work_submit(loop, + &req->work_req, + uv__getaddrinfo_work, + uv__getaddrinfo_done); + return 0; + } else { + uv__getaddrinfo_work(&req->work_req); + uv__getaddrinfo_done(&req->work_req, 0); + return req->retcode; + } } diff --git a/deps/uv/src/unix/getnameinfo.c b/deps/uv/src/unix/getnameinfo.c index c3fb9831c6bf..daa798a450e2 100644 --- a/deps/uv/src/unix/getnameinfo.c +++ b/deps/uv/src/unix/getnameinfo.c @@ -69,7 +69,8 @@ static void uv__getnameinfo_done(struct uv__work* w, int status) { service = req->service; } - req->getnameinfo_cb(req, req->retcode, host, service); + if (req->getnameinfo_cb) + req->getnameinfo_cb(req, req->retcode, host, service); } /* @@ -82,7 +83,7 @@ int uv_getnameinfo(uv_loop_t* loop, uv_getnameinfo_cb getnameinfo_cb, const struct sockaddr* addr, int flags) { - if (req == NULL || getnameinfo_cb == NULL || addr == NULL) + if (req == NULL || addr == NULL) return UV_EINVAL; if (addr->sa_family == AF_INET) { @@ -105,10 +106,15 @@ int uv_getnameinfo(uv_loop_t* loop, req->loop = loop; req->retcode = 0; - uv__work_submit(loop, - &req->work_req, - uv__getnameinfo_work, - uv__getnameinfo_done); - - return 0; + if (getnameinfo_cb) { + uv__work_submit(loop, + &req->work_req, + uv__getnameinfo_work, + uv__getnameinfo_done); + return 0; + } else { + uv__getnameinfo_work(&req->work_req); + uv__getnameinfo_done(&req->work_req, 0); + return req->retcode; + } } diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index daad61b782f1..31db5e29ea68 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -52,12 +52,12 @@ # include #endif -#define STATIC_ASSERT(expr) \ - void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)]) - #define ACCESS_ONCE(type, var) \ (*(volatile type*) &(var)) +#define ROUND_UP(a, b) \ + ((a) % (b) ? ((a) + (b)) - ((a) % (b)) : (a)) + #define UNREACHABLE() \ do { \ assert(0 && "unreachable code"); \ @@ -224,7 +224,7 @@ void uv__signal_loop_cleanup(uv_loop_t* loop); /* platform specific */ uint64_t uv__hrtime(uv_clocktype_t type); int uv__kqueue_init(uv_loop_t* loop); -int uv__platform_loop_init(uv_loop_t* loop, int default_loop); +int uv__platform_loop_init(uv_loop_t* loop); void uv__platform_loop_delete(uv_loop_t* loop); void uv__platform_invalidate_fd(uv_loop_t* loop, int fd); diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index a2145b0f369e..c1be21a8b4ff 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -75,7 +74,7 @@ static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci); static unsigned long read_cpufreq(unsigned int cpunum); -int uv__platform_loop_init(uv_loop_t* loop, int default_loop) { +int uv__platform_loop_init(uv_loop_t* loop) { int fd; fd = uv__epoll_create1(UV__EPOLL_CLOEXEC); @@ -137,13 +136,15 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { void uv__io_poll(uv_loop_t* loop, int timeout) { + static int no_epoll_pwait; + static int no_epoll_wait; struct uv__epoll_event events[1024]; struct uv__epoll_event* pe; struct uv__epoll_event e; QUEUE* q; uv__io_t* w; - sigset_t* pset; - sigset_t set; + sigset_t sigset; + uint64_t sigmask; uint64_t base; uint64_t diff; int nevents; @@ -152,7 +153,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { int fd; int op; int i; - static int no_epoll_wait; if (loop->nfds == 0) { assert(QUEUE_EMPTY(&loop->watcher_queue)); @@ -194,11 +194,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { w->events = w->pevents; } - pset = NULL; + sigmask = 0; if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { - pset = &set; - sigemptyset(pset); - sigaddset(pset, SIGPROF); + sigemptyset(&sigset); + sigaddset(&sigset, SIGPROF); + sigmask |= 1 << (SIGPROF - 1); } assert(timeout >= -1); @@ -206,23 +206,31 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { count = 48; /* Benchmarks suggest this gives the best throughput. */ for (;;) { - if (no_epoll_wait || pset != NULL) { + if (sigmask != 0 && no_epoll_pwait != 0) + if (pthread_sigmask(SIG_BLOCK, &sigset, NULL)) + abort(); + + if (sigmask != 0 && no_epoll_pwait == 0) { nfds = uv__epoll_pwait(loop->backend_fd, events, ARRAY_SIZE(events), timeout, - pset); + sigmask); + if (nfds == -1 && errno == ENOSYS) + no_epoll_pwait = 1; } else { nfds = uv__epoll_wait(loop->backend_fd, events, ARRAY_SIZE(events), timeout); - if (nfds == -1 && errno == ENOSYS) { + if (nfds == -1 && errno == ENOSYS) no_epoll_wait = 1; - continue; - } } + if (sigmask != 0 && no_epoll_pwait != 0) + if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL)) + abort(); + /* Update loop->time unconditionally. It's tempting to skip the update when * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the * operating system didn't reschedule our process while in the syscall. @@ -235,6 +243,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { } if (nfds == -1) { + if (errno == ENOSYS) { + /* epoll_wait() or epoll_pwait() failed, try the other system call. */ + assert(no_epoll_wait == 0 || no_epoll_pwait == 0); + continue; + } + if (errno != EINTR) abort(); @@ -383,10 +397,13 @@ void uv_loadavg(double avg[3]) { int uv_exepath(char* buffer, size_t* size) { ssize_t n; - if (buffer == NULL || size == NULL) + if (buffer == NULL || size == NULL || *size == 0) return -EINVAL; - n = readlink("/proc/self/exe", buffer, *size - 1); + n = *size - 1; + if (n > 0) + n = readlink("/proc/self/exe", buffer, n); + if (n == -1) return -errno; diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c index e036fad5ef64..7bf2c0f87dbe 100644 --- a/deps/uv/src/unix/linux-syscalls.c +++ b/deps/uv/src/unix/linux-syscalls.c @@ -321,15 +321,15 @@ int uv__epoll_pwait(int epfd, struct uv__epoll_event* events, int nevents, int timeout, - const sigset_t* sigmask) { + uint64_t sigmask) { #if defined(__NR_epoll_pwait) return syscall(__NR_epoll_pwait, epfd, events, nevents, timeout, - sigmask, - _NSIG / 8); + &sigmask, + sizeof(sigmask)); #else return errno = ENOSYS, -1; #endif diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h index fd6bb48665fb..6f249b724536 100644 --- a/deps/uv/src/unix/linux-syscalls.h +++ b/deps/uv/src/unix/linux-syscalls.h @@ -131,7 +131,7 @@ int uv__epoll_pwait(int epfd, struct uv__epoll_event* events, int nevents, int timeout, - const sigset_t* sigmask); + uint64_t sigmask); int uv__eventfd2(unsigned int count, int flags); int uv__inotify_init(void); int uv__inotify_init1(int flags); diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c index 616cf5bc43b0..7e167d049e4f 100644 --- a/deps/uv/src/unix/loop.c +++ b/deps/uv/src/unix/loop.c @@ -27,78 +27,7 @@ #include #include -static int uv__loop_init(uv_loop_t* loop, int default_loop); -static void uv__loop_close(uv_loop_t* loop); - -static uv_loop_t default_loop_struct; -static uv_loop_t* default_loop_ptr; - - -uv_loop_t* uv_default_loop(void) { - if (default_loop_ptr != NULL) - return default_loop_ptr; - - if (uv__loop_init(&default_loop_struct, /* default_loop? */ 1)) - return NULL; - - default_loop_ptr = &default_loop_struct; - return default_loop_ptr; -} - - int uv_loop_init(uv_loop_t* loop) { - return uv__loop_init(loop, /* default_loop? */ 0); -} - - -int uv_loop_close(uv_loop_t* loop) { - QUEUE* q; - uv_handle_t* h; - if (!QUEUE_EMPTY(&(loop)->active_reqs)) - return -EBUSY; - QUEUE_FOREACH(q, &loop->handle_queue) { - h = QUEUE_DATA(q, uv_handle_t, handle_queue); - if (!(h->flags & UV__HANDLE_INTERNAL)) - return -EBUSY; - } - uv__loop_close(loop); -#ifndef NDEBUG - memset(loop, -1, sizeof(*loop)); -#endif - if (loop == default_loop_ptr) - default_loop_ptr = NULL; - return 0; -} - - -uv_loop_t* uv_loop_new(void) { - uv_loop_t* loop; - - loop = malloc(sizeof(*loop)); - if (loop == NULL) - return NULL; - - if (uv_loop_init(loop)) { - free(loop); - return NULL; - } - - return loop; -} - - -void uv_loop_delete(uv_loop_t* loop) { - uv_loop_t* default_loop; - int err; - default_loop = default_loop_ptr; - err = uv_loop_close(loop); - assert(err == 0); - if (loop != default_loop) - free(loop); -} - - -static int uv__loop_init(uv_loop_t* loop, int default_loop) { int err; uv__signal_global_once_init(); @@ -130,7 +59,7 @@ static int uv__loop_init(uv_loop_t* loop, int default_loop) { loop->timer_counter = 0; loop->stop_flag = 0; - err = uv__platform_loop_init(loop, default_loop); + err = uv__platform_loop_init(loop); if (err) return err; @@ -155,7 +84,7 @@ static int uv__loop_init(uv_loop_t* loop, int default_loop) { } -static void uv__loop_close(uv_loop_t* loop) { +void uv__loop_close(uv_loop_t* loop) { uv__signal_loop_cleanup(loop); uv__platform_loop_delete(loop); uv__async_stop(loop, &loop->async_watcher); diff --git a/deps/uv/src/unix/netbsd.c b/deps/uv/src/unix/netbsd.c index 5f1182f8b43e..9eb0679de98f 100644 --- a/deps/uv/src/unix/netbsd.c +++ b/deps/uv/src/unix/netbsd.c @@ -49,7 +49,7 @@ static char *process_title; -int uv__platform_loop_init(uv_loop_t* loop, int default_loop) { +int uv__platform_loop_init(uv_loop_t* loop) { return uv__kqueue_init(loop); } @@ -83,7 +83,7 @@ int uv_exepath(char* buffer, size_t* size) { size_t cb; pid_t mypid; - if (buffer == NULL || size == NULL) + if (buffer == NULL || size == NULL || *size == 0) return -EINVAL; mypid = getpid(); diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c index cde8d4d0c962..859bc0ccb187 100644 --- a/deps/uv/src/unix/openbsd.c +++ b/deps/uv/src/unix/openbsd.c @@ -47,7 +47,7 @@ static char *process_title; -int uv__platform_loop_init(uv_loop_t* loop, int default_loop) { +int uv__platform_loop_init(uv_loop_t* loop) { return uv__kqueue_init(loop); } @@ -85,7 +85,7 @@ int uv_exepath(char* buffer, size_t* size) { pid_t mypid; int err; - if (buffer == NULL || size == NULL) + if (buffer == NULL || size == NULL || *size == 0) return -EINVAL; mypid = getpid(); @@ -108,17 +108,19 @@ int uv_exepath(char* buffer, size_t* size) { } argsbuf_size *= 2U; } + if (argsbuf[0] == NULL) { err = -EINVAL; /* FIXME(bnoordhuis) More appropriate error. */ goto out; } + + *size -= 1; exepath_size = strlen(argsbuf[0]); - if (exepath_size >= *size) { - err = -EINVAL; - goto out; - } - memcpy(buffer, argsbuf[0], exepath_size + 1U); - *size = exepath_size; + if (*size > exepath_size) + *size = exepath_size; + + memcpy(buffer, argsbuf[0], *size); + buffer[*size] = '\0'; err = 0; out: diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c index b20fb9210c07..bc8b856337bb 100644 --- a/deps/uv/src/unix/pipe.c +++ b/deps/uv/src/unix/pipe.c @@ -55,17 +55,15 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { /* Make a copy of the file name, it outlives this function's scope. */ pipe_fname = strdup(name); - if (pipe_fname == NULL) { - err = -ENOMEM; - goto out; - } + if (pipe_fname == NULL) + return -ENOMEM; /* We've got a copy, don't touch the original any more. */ name = NULL; err = uv__socket(AF_UNIX, SOCK_STREAM, 0); if (err < 0) - goto out; + goto err_socket; sockfd = err; memset(&saddr, 0, sizeof saddr); @@ -78,7 +76,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { /* Convert ENOENT to EACCES for compatibility with Windows. */ if (err == -ENOENT) err = -EACCES; - goto out; + goto err_bind; } /* Success. */ @@ -86,11 +84,10 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { handle->io_watcher.fd = sockfd; return 0; -out: - /* unlink() before uv__close() to avoid races. */ - assert(pipe_fname != NULL); - unlink(pipe_fname); +err_bind: uv__close(sockfd); + +err_socket: free((void*)pipe_fname); return err; } @@ -128,9 +125,13 @@ void uv__pipe_close(uv_pipe_t* handle) { int uv_pipe_open(uv_pipe_t* handle, uv_file fd) { -#if defined(__APPLE__) int err; + err = uv__nonblock(fd, 1); + if (err) + return err; + +#if defined(__APPLE__) err = uv__stream_try_select((uv_stream_t*) handle, &fd); if (err) return err; @@ -205,38 +206,56 @@ void uv_pipe_connect(uv_connect_t* req, } -int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) { +typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*); + + +static int uv__pipe_getsockpeername(const uv_pipe_t* handle, + uv__peersockfunc func, + char* buffer, + size_t* size) { struct sockaddr_un sa; socklen_t addrlen; int err; addrlen = sizeof(sa); memset(&sa, 0, addrlen); - err = getsockname(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen); + err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen); if (err < 0) { - *len = 0; + *size = 0; return -errno; } +#if defined(__linux__) if (sa.sun_path[0] == 0) /* Linux abstract namespace */ addrlen -= offsetof(struct sockaddr_un, sun_path); else - addrlen = strlen(sa.sun_path) + 1; +#endif + addrlen = strlen(sa.sun_path); - if (addrlen > *len) { - *len = addrlen; + if (addrlen > *size) { + *size = addrlen; return UV_ENOBUFS; } - memcpy(buf, sa.sun_path, addrlen); - *len = addrlen; + memcpy(buffer, sa.sun_path, addrlen); + *size = addrlen; return 0; } +int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { + return uv__pipe_getsockpeername(handle, getsockname, buffer, size); +} + + +int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { + return uv__pipe_getsockpeername(handle, getpeername, buffer, size); +} + + void uv_pipe_pending_instances(uv_pipe_t* handle, int count) { } diff --git a/deps/uv/src/unix/poll.c b/deps/uv/src/unix/poll.c index a34a8d1e145a..37da3b95851b 100644 --- a/deps/uv/src/unix/poll.c +++ b/deps/uv/src/unix/poll.c @@ -51,6 +51,12 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { + int err; + + err = uv__nonblock(fd, 1); + if (err) + return err; + uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL); uv__io_init(&handle->io_watcher, uv__poll_io, fd); handle->poll_cb = NULL; diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index d41a3429a78b..7de1d8215111 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -301,7 +301,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { if (fds[1] > max_fd) max_fd = fds[1]; - sread_sz = (max_fd + NBBY) / NBBY; + sread_sz = ROUND_UP(max_fd + 1, sizeof(uint32_t) * NBBY) / NBBY; swrite_sz = sread_sz; s = malloc(sizeof(*s) + sread_sz + swrite_sz); @@ -375,6 +375,10 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { int uv__stream_open(uv_stream_t* stream, int fd, int flags) { +#if defined(__APPLE__) + int enable; +#endif + assert(fd >= 0); stream->flags |= flags; @@ -387,6 +391,15 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) { return -errno; } +#if defined(__APPLE__) + enable = 1; + if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) && + errno != ENOTSOCK && + errno != EINVAL) { + return -errno; + } +#endif + stream->io_watcher.fd = fd; return 0; @@ -1573,5 +1586,8 @@ void uv__stream_close(uv_stream_t* handle) { int uv_stream_set_blocking(uv_stream_t* handle, int blocking) { - return UV_ENOSYS; + /* Don't need to check the file descriptor, uv__nonblock() + * will fail with EBADF if it's not valid. + */ + return uv__nonblock(uv__stream_fd(handle), !blocking); } diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index d6fb7f495091..c41d0f0e52bd 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -62,7 +62,7 @@ #endif -int uv__platform_loop_init(uv_loop_t* loop, int default_loop) { +int uv__platform_loop_init(uv_loop_t* loop) { int err; int fd; @@ -300,11 +300,15 @@ int uv_exepath(char* buffer, size_t* size) { ssize_t res; char buf[128]; - if (buffer == NULL || size == NULL) + if (buffer == NULL || size == NULL || *size == 0) return -EINVAL; snprintf(buf, sizeof(buf), "/proc/%lu/path/a.out", (unsigned long) getpid()); - res = readlink(buf, buffer, *size - 1); + + res = *size - 1; + if (res > 0) + res = readlink(buf, buffer, res); + if (res == -1) return -errno; diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c index 8c19c1ab9560..4060e7bd7094 100644 --- a/deps/uv/src/unix/tcp.c +++ b/deps/uv/src/unix/tcp.c @@ -156,6 +156,12 @@ int uv__tcp_connect(uv_connect_t* req, int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { + int err; + + err = uv__nonblock(sock, 1); + if (err) + return err; + return uv__stream_open((uv_stream_t*)handle, sock, UV_STREAM_READABLE | UV_STREAM_WRITABLE); diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index 7a55bd632476..ea8563fecf95 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -68,7 +68,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { if (err) free(ctx); - return err ? -1 : 0; + return -err; } @@ -330,7 +330,7 @@ int uv_cond_init(uv_cond_t* cond) { if (err) return -err; -#if !defined(__ANDROID__) +#if !(defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); if (err) goto error2; @@ -388,7 +388,7 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { timeout += uv__hrtime(UV_CLOCK_PRECISE); ts.tv_sec = timeout / NANOSEC; ts.tv_nsec = timeout % NANOSEC; -#if defined(__ANDROID__) +#if defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) /* * The bionic pthread implementation doesn't support CLOCK_MONOTONIC, * but has this alternative function instead. diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c index 7ae19905fbff..b1782df95b20 100644 --- a/deps/uv/src/unix/tty.c +++ b/deps/uv/src/unix/tty.c @@ -98,19 +98,39 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { uv__nonblock(fd, 1); uv__stream_open((uv_stream_t*) tty, fd, flags); - tty->mode = 0; + tty->mode = UV_TTY_MODE_NORMAL; return 0; } +static void uv__tty_make_raw(struct termios* tio) { + assert(tio != NULL); -int uv_tty_set_mode(uv_tty_t* tty, int mode) { - struct termios raw; +#ifdef __sun + /* + * This implementation of cfmakeraw for Solaris and derivatives is taken from + * http://www.perkin.org.uk/posts/solaris-portability-cfmakeraw.html. + */ + tio->c_iflag &= ~(IMAXBEL | IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | + IGNCR | ICRNL | IXON); + tio->c_oflag &= ~OPOST; + tio->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + tio->c_cflag &= ~(CSIZE | PARENB); + tio->c_cflag |= CS8; +#else + cfmakeraw(tio); +#endif /* #ifdef __sun */ +} + +int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { + struct termios tmp; int fd; - fd = uv__stream_fd(tty); + if (tty->mode == (int) mode) + return 0; - if (mode && tty->mode == 0) { /* on */ + fd = uv__stream_fd(tty); + if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) { if (tcgetattr(fd, &tty->orig_termios)) return -errno; @@ -121,27 +141,30 @@ int uv_tty_set_mode(uv_tty_t* tty, int mode) { orig_termios_fd = fd; } uv_spinlock_unlock(&termios_spinlock); + } - raw = tty->orig_termios; - raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - raw.c_oflag |= (ONLCR); - raw.c_cflag |= (CS8); - raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); - raw.c_cc[VMIN] = 1; - raw.c_cc[VTIME] = 0; - - /* Put terminal in raw mode after draining */ - if (tcsetattr(fd, TCSADRAIN, &raw)) - return -errno; - - tty->mode = 1; - } else if (mode == 0 && tty->mode) { /* off */ - /* Put terminal in original mode after flushing */ - if (tcsetattr(fd, TCSAFLUSH, &tty->orig_termios)) - return -errno; - tty->mode = 0; + tmp = tty->orig_termios; + switch (mode) { + case UV_TTY_MODE_NORMAL: + break; + case UV_TTY_MODE_RAW: + tmp.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + tmp.c_oflag |= (ONLCR); + tmp.c_cflag |= (CS8); + tmp.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + tmp.c_cc[VMIN] = 1; + tmp.c_cc[VTIME] = 0; + break; + case UV_TTY_MODE_IO: + uv__tty_make_raw(&tmp); + break; } + /* Apply changes after draining */ + if (tcsetattr(fd, TCSADRAIN, &tmp)) + return -errno; + + tty->mode = mode; return 0; } diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index 71a0e41f1f74..22c2e1388e14 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -565,6 +565,10 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { if (handle->io_watcher.fd != -1) return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */ + err = uv__nonblock(sock, 1); + if (err) + return err; + err = uv__set_reuse(sock); if (err) return err; @@ -597,8 +601,35 @@ int uv_udp_set_membership(uv_udp_t* handle, } } +static int uv__setsockopt(uv_udp_t* handle, + int option4, + int option6, + const void* val, + size_t size) { + int r; + + if (handle->flags & UV_HANDLE_IPV6) + r = setsockopt(handle->io_watcher.fd, + IPPROTO_IPV6, + option6, + val, + size); + else + r = setsockopt(handle->io_watcher.fd, + IPPROTO_IP, + option4, + val, + size); + if (r) + return -errno; + + return 0; +} -static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) { +static int uv__setsockopt_maybe_char(uv_udp_t* handle, + int option4, + int option6, + int val) { #if defined(__sun) || defined(_AIX) char arg = val; #else @@ -608,10 +639,7 @@ static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) { if (val < 0 || val > 255) return -EINVAL; - if (setsockopt(handle->io_watcher.fd, IPPROTO_IP, option, &arg, sizeof(arg))) - return -errno; - - return 0; + return uv__setsockopt(handle, option4, option6, &arg, sizeof(arg)); } @@ -632,20 +660,70 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { if (ttl < 1 || ttl > 255) return -EINVAL; - if (setsockopt(handle->io_watcher.fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl))) - return -errno; - - return 0; +/* + * On Solaris and derivatives such as SmartOS, the length of socket options + * is sizeof(int) for IP_TTL and IPV6_UNICAST_HOPS, + * so hardcode the size of these options on this platform, + * and use the general uv__setsockopt_maybe_char call on other platforms. + */ +#if defined(__sun) + return uv__setsockopt(handle, + IP_TTL, + IPV6_UNICAST_HOPS, + &ttl, + sizeof(ttl)); +#endif /* defined(__sun) */ + + return uv__setsockopt_maybe_char(handle, + IP_TTL, + IPV6_UNICAST_HOPS, + ttl); } int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { - return uv__setsockopt_maybe_char(handle, IP_MULTICAST_TTL, ttl); +/* + * On Solaris and derivatives such as SmartOS, the length of socket options + * is sizeof(int) for IPV6_MULTICAST_HOPS and sizeof(char) for + * IP_MULTICAST_TTL, so hardcode the size of the option in the IPv6 case, + * and use the general uv__setsockopt_maybe_char call otherwise. + */ +#if defined(__sun) + if (handle->flags & UV_HANDLE_IPV6) + return uv__setsockopt(handle, + IP_MULTICAST_TTL, + IPV6_MULTICAST_HOPS, + &ttl, + sizeof(ttl)); +#endif /* defined(__sun) */ + + return uv__setsockopt_maybe_char(handle, + IP_MULTICAST_TTL, + IPV6_MULTICAST_HOPS, + ttl); } int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { - return uv__setsockopt_maybe_char(handle, IP_MULTICAST_LOOP, on); +/* + * On Solaris and derivatives such as SmartOS, the length of socket options + * is sizeof(int) for IPV6_MULTICAST_LOOP and sizeof(char) for + * IP_MULTICAST_LOOP, so hardcode the size of the option in the IPv6 case, + * and use the general uv__setsockopt_maybe_char call otherwise. + */ +#if defined(__sun) + if (handle->flags & UV_HANDLE_IPV6) + return uv__setsockopt(handle, + IP_MULTICAST_LOOP, + IPV6_MULTICAST_LOOP, + &on, + sizeof(on)); +#endif /* defined(__sun) */ + + return uv__setsockopt_maybe_char(handle, + IP_MULTICAST_LOOP, + IPV6_MULTICAST_LOOP, + on); } int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) { diff --git a/deps/uv/src/unix/uv-dtrace.d b/deps/uv/src/unix/uv-dtrace.d deleted file mode 100644 index 7848450c949f..000000000000 --- a/deps/uv/src/unix/uv-dtrace.d +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -provider uv { - probe tick__start(void* loop, int mode); - probe tick__stop(void* loop, int mode); -}; diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index f84f8c4ae10d..791c09b4e28e 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -359,22 +359,22 @@ int uv_send_buffer_size(uv_handle_t* handle, int *value) { return uv__socket_sockopt(handle, SO_SNDBUF, value); } -int uv_fs_event_getpath(uv_fs_event_t* handle, char* buf, size_t* len) { +int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) { size_t required_len; if (!uv__is_active(handle)) { - *len = 0; + *size = 0; return UV_EINVAL; } - required_len = strlen(handle->path) + 1; - if (required_len > *len) { - *len = required_len; + required_len = strlen(handle->path); + if (required_len > *size) { + *size = required_len; return UV_ENOBUFS; } - memcpy(buf, handle->path, required_len); - *len = required_len; + memcpy(buffer, handle->path, required_len); + *size = required_len; return 0; } @@ -456,3 +456,73 @@ int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) { return err; } + + +static uv_loop_t default_loop_struct; +static uv_loop_t* default_loop_ptr; + + +uv_loop_t* uv_default_loop(void) { + if (default_loop_ptr != NULL) + return default_loop_ptr; + + if (uv_loop_init(&default_loop_struct)) + return NULL; + + default_loop_ptr = &default_loop_struct; + return default_loop_ptr; +} + + +uv_loop_t* uv_loop_new(void) { + uv_loop_t* loop; + + loop = malloc(sizeof(*loop)); + if (loop == NULL) + return NULL; + + if (uv_loop_init(loop)) { + free(loop); + return NULL; + } + + return loop; +} + + +int uv_loop_close(uv_loop_t* loop) { + QUEUE* q; + uv_handle_t* h; + + if (!QUEUE_EMPTY(&(loop)->active_reqs)) + return UV_EBUSY; + + QUEUE_FOREACH(q, &loop->handle_queue) { + h = QUEUE_DATA(q, uv_handle_t, handle_queue); + if (!(h->flags & UV__HANDLE_INTERNAL)) + return UV_EBUSY; + } + + uv__loop_close(loop); + +#ifndef NDEBUG + memset(loop, -1, sizeof(*loop)); +#endif + if (loop == default_loop_ptr) + default_loop_ptr = NULL; + + return 0; +} + + +void uv_loop_delete(uv_loop_t* loop) { + uv_loop_t* default_loop; + int err; + + default_loop = default_loop_ptr; + + err = uv_loop_close(loop); + assert(err == 0); + if (loop != default_loop) + free(loop); +} diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index 7d3c58f12185..463cabac29d5 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -46,6 +46,9 @@ #define container_of(ptr, type, member) \ ((type *) ((char *) (ptr) - offsetof(type, member))) +#define STATIC_ASSERT(expr) \ + void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)]) + #ifndef _WIN32 enum { UV__HANDLE_INTERNAL = 0x8000, @@ -62,6 +65,8 @@ enum { int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap); +void uv__loop_close(uv_loop_t* loop); + int uv__tcp_bind(uv_tcp_t* tcp, const struct sockaddr* addr, unsigned int addrlen, diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index 48897cf29bc7..a10115943834 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -184,19 +184,7 @@ void uv__once_init(void) { } -uv_loop_t* uv_default_loop(void) { - if (default_loop_ptr != NULL) - return default_loop_ptr; - - if (uv_loop_init(&default_loop_struct)) - return NULL; - - default_loop_ptr = &default_loop_struct; - return default_loop_ptr; -} - - -static void uv__loop_close(uv_loop_t* loop) { +void uv__loop_close(uv_loop_t* loop) { size_t i; /* close the async handle without needing an extra loop iteration */ @@ -221,57 +209,6 @@ static void uv__loop_close(uv_loop_t* loop) { } -int uv_loop_close(uv_loop_t* loop) { - QUEUE* q; - uv_handle_t* h; - if (!QUEUE_EMPTY(&(loop)->active_reqs)) - return UV_EBUSY; - QUEUE_FOREACH(q, &loop->handle_queue) { - h = QUEUE_DATA(q, uv_handle_t, handle_queue); - if (!(h->flags & UV__HANDLE_INTERNAL)) - return UV_EBUSY; - } - - uv__loop_close(loop); - -#ifndef NDEBUG - memset(loop, -1, sizeof(*loop)); -#endif - if (loop == default_loop_ptr) - default_loop_ptr = NULL; - - return 0; -} - - -uv_loop_t* uv_loop_new(void) { - uv_loop_t* loop; - - loop = (uv_loop_t*)malloc(sizeof(uv_loop_t)); - if (loop == NULL) { - return NULL; - } - - if (uv_loop_init(loop)) { - free(loop); - return NULL; - } - - return loop; -} - - -void uv_loop_delete(uv_loop_t* loop) { - uv_loop_t* default_loop; - int err; - default_loop = default_loop_ptr; - err = uv_loop_close(loop); - assert(err == 0); - if (loop != default_loop) - free(loop); -} - - int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) { return UV_ENOSYS; } @@ -387,6 +324,7 @@ int uv_loop_alive(const uv_loop_t* loop) { int uv_run(uv_loop_t *loop, uv_run_mode mode) { DWORD timeout; int r; + int ran_pending; void (*poll)(uv_loop_t* loop, DWORD timeout); if (pGetQueuedCompletionStatusEx) @@ -402,12 +340,12 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { uv_update_time(loop); uv_process_timers(loop); - uv_process_reqs(loop); + ran_pending = uv_process_reqs(loop); uv_idle_invoke(loop); uv_prepare_invoke(loop); timeout = 0; - if ((mode & UV_RUN_NOWAIT) == 0) + if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) timeout = uv_backend_timeout(loop); (*poll)(loop, timeout); @@ -428,7 +366,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { } r = uv__loop_alive(loop); - if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT)) + if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT) break; } diff --git a/deps/uv/src/win/dl.c b/deps/uv/src/win/dl.c index 2ef1f6c54f2f..e5f3407f8eb2 100644 --- a/deps/uv/src/win/dl.c +++ b/deps/uv/src/win/dl.c @@ -69,17 +69,44 @@ const char* uv_dlerror(const uv_lib_t* lib) { } +static void uv__format_fallback_error(uv_lib_t* lib, int errorno){ + DWORD_PTR args[1] = { (DWORD_PTR) errorno }; + LPSTR fallback_error = "error: %1!d!"; + + FormatMessageA(FORMAT_MESSAGE_FROM_STRING | + FORMAT_MESSAGE_ARGUMENT_ARRAY | + FORMAT_MESSAGE_ALLOCATE_BUFFER, + fallback_error, 0, 0, + (LPSTR) &lib->errmsg, + 0, (va_list*) args); +} + + + static int uv__dlerror(uv_lib_t* lib, int errorno) { + DWORD res; + if (lib->errmsg) { LocalFree((void*)lib->errmsg); lib->errmsg = NULL; } if (errorno) { - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, - MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), - (LPSTR)&lib->errmsg, 0, NULL); + res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + (LPSTR) &lib->errmsg, 0, NULL); + if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) { + res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno, + 0, (LPSTR) &lib->errmsg, 0, NULL); + } + + if (!res) { + uv__format_fallback_error(lib, errorno); + } } return errorno ? -1 : 0; diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 30a457a023b4..33bc9da30405 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -43,8 +43,6 @@ #define UV_FS_FREE_PTR 0x0008 #define UV_FS_CLEANEDUP 0x0010 -static const int uv__fs_dirent_slide = 0x20; - #define QUEUE_FS_TP_JOB(loop, req) \ do { \ @@ -788,123 +786,203 @@ void fs__mkdtemp(uv_fs_t* req) { void fs__scandir(uv_fs_t* req) { - WCHAR* pathw = req->pathw; - size_t len = wcslen(pathw); - int result; - WCHAR* name; - HANDLE dir; - WIN32_FIND_DATAW ent = { 0 }; - WCHAR* path2; - const WCHAR* fmt; - uv__dirent_t** dents; - int dent_size; - - if (len == 0) { - fmt = L"./*"; - } else if (pathw[len - 1] == L'/' || pathw[len - 1] == L'\\') { - fmt = L"%s*"; - } else { - fmt = L"%s\\*"; - } + static const size_t dirents_initial_size = 32; - /* Figure out whether path is a file or a directory. */ - if (!(GetFileAttributesW(pathw) & FILE_ATTRIBUTE_DIRECTORY)) { - req->result = UV_ENOTDIR; - req->sys_errno_ = ERROR_SUCCESS; - return; - } - - path2 = (WCHAR*)malloc(sizeof(WCHAR) * (len + 4)); - if (!path2) { - SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); - return; - } + HANDLE dir_handle = INVALID_HANDLE_VALUE; - _snwprintf(path2, len + 3, fmt, pathw); - dir = FindFirstFileW(path2, &ent); - free(path2); - - if(dir == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - - result = 0; - dents = NULL; - dent_size = 0; - - do { - uv__dirent_t* dent; - int utf8_len; - - name = ent.cFileName; - - if (!(name[0] != L'.' || (name[1] && (name[1] != L'.' || name[2])))) - continue; + uv__dirent_t** dirents = NULL; + size_t dirents_size = 0; + size_t dirents_used = 0; - /* Grow dents buffer, if needed */ - if (result >= dent_size) { - uv__dirent_t** tmp; + IO_STATUS_BLOCK iosb; + NTSTATUS status; - dent_size += uv__fs_dirent_slide; - tmp = realloc(dents, dent_size * sizeof(*dents)); - if (tmp == NULL) { - SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); - goto fatal; + /* Buffer to hold directory entries returned by NtQueryDirectoryFile. + * It's important that this buffer can hold at least one entry, regardless + * of the length of the file names present in the enumerated directory. + * A file name is at most 256 WCHARs long. + * According to MSDN, the buffer must be aligned at an 8-byte boundary. + */ + __declspec(align(8)) char buffer[8192]; + + STATIC_ASSERT(sizeof buffer >= + sizeof(FILE_DIRECTORY_INFORMATION) + 256 * sizeof(WCHAR)); + + /* Open the directory. */ + dir_handle = + CreateFileW(req->pathw, + FILE_LIST_DIRECTORY | SYNCHRONIZE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if (dir_handle == INVALID_HANDLE_VALUE) + goto win32_error; + + /* Read the first chunk. */ + status = pNtQueryDirectoryFile(dir_handle, + NULL, + NULL, + NULL, + &iosb, + &buffer, + sizeof buffer, + FileDirectoryInformation, + FALSE, + NULL, + TRUE); + + /* If the handle is not a directory, we'll get STATUS_INVALID_PARAMETER. + * This should be reported back as UV_ENOTDIR. + */ + if (status == STATUS_INVALID_PARAMETER) + goto not_a_directory_error; + + while (NT_SUCCESS(status)) { + char* position = buffer; + size_t next_entry_offset = 0; + + do { + FILE_DIRECTORY_INFORMATION* info; + uv__dirent_t* dirent; + + size_t wchar_len; + size_t utf8_len; + + /* Obtain a pointer to the current directory entry. */ + position += next_entry_offset; + info = (FILE_DIRECTORY_INFORMATION*) position; + + /* Fetch the offset to the next directory entry. */ + next_entry_offset = info->NextEntryOffset; + + /* Compute the length of the filename in WCHARs. */ + wchar_len = info->FileNameLength / sizeof info->FileName[0]; + + /* Skip over '.' and '..' entries. */ + if (wchar_len == 1 && info->FileName[0] == L'.') + continue; + if (wchar_len == 2 && info->FileName[0] == L'.' && + info->FileName[1] == L'.') + continue; + + /* Compute the space required to store the filename as UTF-8. */ + utf8_len = WideCharToMultiByte( + CP_UTF8, 0, &info->FileName[0], wchar_len, NULL, 0, NULL, NULL); + if (utf8_len == 0) + goto win32_error; + + /* Resize the dirent array if needed. */ + if (dirents_used >= dirents_size) { + size_t new_dirents_size = + dirents_size == 0 ? dirents_initial_size : dirents_size << 1; + uv__dirent_t** new_dirents = + realloc(dirents, new_dirents_size * sizeof *dirents); + + if (new_dirents == NULL) + goto out_of_memory_error; + + dirents_size = new_dirents_size; + dirents = new_dirents; } - dents = tmp; - } - - /* Allocate enough space to fit utf8 encoding of file name */ - len = wcslen(name); - utf8_len = uv_utf16_to_utf8(name, len, NULL, 0); - if (!utf8_len) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - goto fatal; - } - - dent = malloc(sizeof(*dent) + utf8_len + 1); - if (dent == NULL) { - SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); - goto fatal; - } - /* Copy file name */ - utf8_len = uv_utf16_to_utf8(name, len, dent->d_name, utf8_len); - if (!utf8_len) { - free(dent); - SET_REQ_WIN32_ERROR(req, GetLastError()); - goto fatal; - } - dent->d_name[utf8_len] = '\0'; - - /* Copy file type */ - if ((ent.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) - dent->d_type = UV__DT_DIR; - else if ((ent.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) - dent->d_type = UV__DT_LINK; - else - dent->d_type = UV__DT_FILE; + /* Allocate space for the uv dirent structure. The dirent structure + * includes room for the first character of the filename, but `utf8_len` + * doesn't count the NULL terminator at this point. + */ + dirent = malloc(sizeof *dirent + utf8_len); + if (dirent == NULL) + goto out_of_memory_error; + + dirents[dirents_used++] = dirent; + + /* Convert file name to UTF-8. */ + if (WideCharToMultiByte(CP_UTF8, + 0, + &info->FileName[0], + wchar_len, + &dirent->d_name[0], + utf8_len, + NULL, + NULL) == 0) + goto win32_error; + + /* Add a null terminator to the filename. */ + dirent->d_name[utf8_len] = '\0'; + + /* Fill out the type field. */ + if (info->FileAttributes & FILE_ATTRIBUTE_DEVICE) + dirent->d_type = UV__DT_CHAR; + else if (info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + dirent->d_type = UV__DT_LINK; + else if (info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) + dirent->d_type = UV__DT_DIR; + else + dirent->d_type = UV__DT_FILE; + } while (next_entry_offset != 0); + + /* Read the next chunk. */ + status = pNtQueryDirectoryFile(dir_handle, + NULL, + NULL, + NULL, + &iosb, + &buffer, + sizeof buffer, + FileDirectoryInformation, + FALSE, + NULL, + FALSE); + + /* After the first pNtQueryDirectoryFile call, the function may return + * STATUS_SUCCESS even if the buffer was too small to hold at least one + * directory entry. + */ + if (status == STATUS_SUCCESS && iosb.Information == 0) + status = STATUS_BUFFER_OVERFLOW; + } - dents[result++] = dent; - } while(FindNextFileW(dir, &ent)); + if (status != STATUS_NO_MORE_FILES) + goto nt_error; - FindClose(dir); + CloseHandle(dir_handle); - if (dents != NULL) + /* Store the result in the request object. */ + req->ptr = dirents; + if (dirents != NULL) req->flags |= UV_FS_FREE_PTR; - /* NOTE: nbufs will be used as index */ + SET_REQ_RESULT(req, dirents_used); + + /* `nbufs` will be used as index by uv_fs_scandir_next. */ req->nbufs = 0; - req->ptr = dents; - SET_REQ_RESULT(req, result); + return; -fatal: - /* Deallocate dents */ - for (result--; result >= 0; result--) - free(dents[result]); - free(dents); +nt_error: + SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status)); + goto cleanup; + +win32_error: + SET_REQ_WIN32_ERROR(req, GetLastError()); + goto cleanup; + +not_a_directory_error: + SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY); + goto cleanup; + +out_of_memory_error: + SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); + goto cleanup; + +cleanup: + if (dir_handle != INVALID_HANDLE_VALUE) + CloseHandle(dir_handle); + while (dirents_used > 0) + free(dirents[--dirents_used]); + if (dirents != NULL) + free(dirents); } diff --git a/deps/uv/src/win/getaddrinfo.c b/deps/uv/src/win/getaddrinfo.c index 53a6084efe5b..f103f5fbd341 100644 --- a/deps/uv/src/win/getaddrinfo.c +++ b/deps/uv/src/win/getaddrinfo.c @@ -77,10 +77,13 @@ int uv__getaddrinfo_translate_error(int sys_err) { static void uv__getaddrinfo_work(struct uv__work* w) { uv_getaddrinfo_t* req; + struct addrinfoW* hints; int err; req = container_of(w, uv_getaddrinfo_t, work_req); - err = GetAddrInfoW(req->node, req->service, req->hints, &req->res); + hints = req->addrinfow; + req->addrinfow = NULL; + err = GetAddrInfoW(req->node, req->service, hints, &req->addrinfow); req->retcode = uv__getaddrinfo_translate_error(err); } @@ -115,17 +118,13 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) { if (status == UV_ECANCELED) { assert(req->retcode == 0); req->retcode = UV_EAI_CANCELED; - if (req->res != NULL) { - FreeAddrInfoW(req->res); - req->res = NULL; - } goto complete; } if (req->retcode == 0) { /* convert addrinfoW to addrinfo */ /* first calculate required length */ - addrinfow_ptr = req->res; + addrinfow_ptr = req->addrinfow; while (addrinfow_ptr != NULL) { addrinfo_len += addrinfo_struct_len + ALIGNED_SIZE(addrinfow_ptr->ai_addrlen); @@ -146,7 +145,7 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) { /* do conversions */ if (alloc_ptr != NULL) { cur_ptr = alloc_ptr; - addrinfow_ptr = req->res; + addrinfow_ptr = req->addrinfow; while (addrinfow_ptr != NULL) { /* copy addrinfo struct data */ @@ -196,22 +195,24 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) { addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr; } } + req->addrinfo = (struct addrinfo*)alloc_ptr; } else { req->retcode = UV_EAI_MEMORY; } } /* return memory to system */ - if (req->res != NULL) { - FreeAddrInfoW(req->res); - req->res = NULL; + if (req->addrinfow != NULL) { + FreeAddrInfoW(req->addrinfow); + req->addrinfow = NULL; } complete: uv__req_unregister(req->loop, req); /* finally do callback with converted result */ - req->getaddrinfo_cb(req, req->retcode, (struct addrinfo*)alloc_ptr); + if (req->getaddrinfo_cb) + req->getaddrinfo_cb(req, req->retcode, req->addrinfo); } @@ -250,8 +251,7 @@ int uv_getaddrinfo(uv_loop_t* loop, char* alloc_ptr = NULL; int err; - if (req == NULL || getaddrinfo_cb == NULL || - (node == NULL && service == NULL)) { + if (req == NULL || (node == NULL && service == NULL)) { err = WSAEINVAL; goto error; } @@ -259,7 +259,7 @@ int uv_getaddrinfo(uv_loop_t* loop, uv_req_init(loop, (uv_req_t*)req); req->getaddrinfo_cb = getaddrinfo_cb; - req->res = NULL; + req->addrinfo = NULL; req->type = UV_GETADDRINFO; req->loop = loop; req->retcode = 0; @@ -327,27 +327,32 @@ int uv_getaddrinfo(uv_loop_t* loop, /* copy hints to allocated memory and save pointer in req */ if (hints != NULL) { - req->hints = (struct addrinfoW*)alloc_ptr; - req->hints->ai_family = hints->ai_family; - req->hints->ai_socktype = hints->ai_socktype; - req->hints->ai_protocol = hints->ai_protocol; - req->hints->ai_flags = hints->ai_flags; - req->hints->ai_addrlen = 0; - req->hints->ai_canonname = NULL; - req->hints->ai_addr = NULL; - req->hints->ai_next = NULL; + req->addrinfow = (struct addrinfoW*)alloc_ptr; + req->addrinfow->ai_family = hints->ai_family; + req->addrinfow->ai_socktype = hints->ai_socktype; + req->addrinfow->ai_protocol = hints->ai_protocol; + req->addrinfow->ai_flags = hints->ai_flags; + req->addrinfow->ai_addrlen = 0; + req->addrinfow->ai_canonname = NULL; + req->addrinfow->ai_addr = NULL; + req->addrinfow->ai_next = NULL; } else { - req->hints = NULL; + req->addrinfow = NULL; } - uv__work_submit(loop, - &req->work_req, - uv__getaddrinfo_work, - uv__getaddrinfo_done); - uv__req_register(loop, req); - return 0; + if (getaddrinfo_cb) { + uv__work_submit(loop, + &req->work_req, + uv__getaddrinfo_work, + uv__getaddrinfo_done); + return 0; + } else { + uv__getaddrinfo_work(&req->work_req); + uv__getaddrinfo_done(&req->work_req, 0); + return req->retcode; + } error: if (req != NULL && req->alloc != NULL) { diff --git a/deps/uv/src/win/getnameinfo.c b/deps/uv/src/win/getnameinfo.c index 52cc7908892c..b1d045c79bd9 100644 --- a/deps/uv/src/win/getnameinfo.c +++ b/deps/uv/src/win/getnameinfo.c @@ -98,7 +98,8 @@ static void uv__getnameinfo_done(struct uv__work* w, int status) { service = req->service; } - req->getnameinfo_cb(req, req->retcode, host, service); + if (req->getnameinfo_cb) + req->getnameinfo_cb(req, req->retcode, host, service); } @@ -112,7 +113,7 @@ int uv_getnameinfo(uv_loop_t* loop, uv_getnameinfo_cb getnameinfo_cb, const struct sockaddr* addr, int flags) { - if (req == NULL || getnameinfo_cb == NULL || addr == NULL) + if (req == NULL || addr == NULL) return UV_EINVAL; if (addr->sa_family == AF_INET) { @@ -136,10 +137,15 @@ int uv_getnameinfo(uv_loop_t* loop, req->loop = loop; req->retcode = 0; - uv__work_submit(loop, - &req->work_req, - uv__getnameinfo_work, - uv__getnameinfo_done); - - return 0; + if (getnameinfo_cb) { + uv__work_submit(loop, + &req->work_req, + uv__getnameinfo_work, + uv__getnameinfo_done); + return 0; + } else { + uv__getnameinfo_work(&req->work_req); + uv__getnameinfo_done(&req->work_req, 0); + return req->retcode; + } } diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index d87402b73a09..04b2a548ca88 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -136,6 +136,8 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb); int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); +int uv__tcp_try_write(uv_tcp_t* handle, const uv_buf_t bufs[], + unsigned int nbufs); void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req); void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, @@ -211,6 +213,8 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, int uv_tty_read_stop(uv_tty_t* handle); int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); +int uv__tty_try_write(uv_tty_t* handle, const uv_buf_t bufs[], + unsigned int nbufs); void uv_tty_close(uv_tty_t* handle); void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, @@ -364,8 +368,8 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, int* addr_len, WSAOVERLAPPED *overlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); -int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info, - OVERLAPPED* overlapped); +int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, + AFD_POLL_INFO* info_out, OVERLAPPED* overlapped); /* Whether there are any non-IFS LSPs stacked on TCP */ extern int uv_tcp_non_ifs_lsp_ipv4; diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index c78051db7c94..8039cac3c4f2 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -1347,7 +1347,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, } /* Request queued by the kernel. */ - req->queued_bytes = uv__count_bufs(bufs, nbufs); + req->queued_bytes = bufs[0].len; handle->write_queue_size += req->queued_bytes; } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) { /* Using overlapped IO, but wait for completion before returning */ @@ -1372,12 +1372,13 @@ static int uv_pipe_write_impl(uv_loop_t* loop, /* Request completed immediately. */ req->queued_bytes = 0; } else { - assert(ipc_header_req != NULL); /* Request queued by the kernel. */ - if (WaitForSingleObject(ipc_header_req->overlapped.hEvent, INFINITE) != + req->queued_bytes = bufs[0].len; + handle->write_queue_size += req->queued_bytes; + if (WaitForSingleObject(req->overlapped.hEvent, INFINITE) != WAIT_OBJECT_0) { err = GetLastError(); - CloseHandle(ipc_header_req->overlapped.hEvent); + CloseHandle(req->overlapped.hEvent); return uv_translate_sys_error(err); } } @@ -1386,7 +1387,6 @@ static int uv_pipe_write_impl(uv_loop_t* loop, REGISTER_HANDLE_REQ(loop, handle, req); handle->reqs_pending++; handle->write_reqs_pending++; - POST_COMPLETION_FOR_REQ(loop, req); return 0; } else { result = WriteFile(handle->handle, @@ -1404,7 +1404,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, req->queued_bytes = 0; } else { /* Request queued by the kernel. */ - req->queued_bytes = uv__count_bufs(bufs, nbufs); + req->queued_bytes = bufs[0].len; handle->write_queue_size += req->queued_bytes; } @@ -1848,7 +1848,7 @@ static void eof_timer_cb(uv_timer_t* timer) { static void eof_timer_destroy(uv_pipe_t* pipe) { - assert(pipe->flags && UV_HANDLE_CONNECTION); + assert(pipe->flags & UV_HANDLE_CONNECTION); if (pipe->eof_timer) { uv_close((uv_handle_t*) pipe->eof_timer, eof_timer_close_cb); @@ -1910,7 +1910,7 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { } -int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) { +static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) { NTSTATUS nt_status; IO_STATUS_BLOCK io_status; FILE_NAME_INFORMATION tmp_name_info; @@ -1924,7 +1924,7 @@ int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) { name_info = NULL; if (handle->handle == INVALID_HANDLE_VALUE) { - *len = 0; + *size = 0; return UV_EINVAL; } @@ -1939,7 +1939,7 @@ int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) { name_size = sizeof(*name_info) + tmp_name_info.FileNameLength; name_info = malloc(name_size); if (!name_info) { - *len = 0; + *size = 0; err = UV_ENOMEM; goto cleanup; } @@ -1952,7 +1952,7 @@ int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) { } if (nt_status != STATUS_SUCCESS) { - *len = 0; + *size = 0; err = uv_translate_sys_error(pRtlNtStatusToDosError(nt_status)); goto error; } @@ -1967,7 +1967,7 @@ int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) { } if (name_len == 0) { - *len = 0; + *size = 0; err = 0; goto error; } @@ -1984,34 +1984,33 @@ int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) { NULL, NULL); if (!addrlen) { - *len = 0; + *size = 0; err = uv_translate_sys_error(GetLastError()); goto error; - } else if (pipe_prefix_len + addrlen + 1 > *len) { - /* "\\\\.\\pipe" + name + '\0' */ - *len = pipe_prefix_len + addrlen + 1; + } else if (pipe_prefix_len + addrlen > *size) { + /* "\\\\.\\pipe" + name */ + *size = pipe_prefix_len + addrlen; err = UV_ENOBUFS; goto error; } - memcpy(buf, pipe_prefix, pipe_prefix_len); + memcpy(buffer, pipe_prefix, pipe_prefix_len); addrlen = WideCharToMultiByte(CP_UTF8, 0, name_buf, name_len, - buf+pipe_prefix_len, - *len-pipe_prefix_len, + buffer+pipe_prefix_len, + *size-pipe_prefix_len, NULL, NULL); if (!addrlen) { - *len = 0; + *size = 0; err = uv_translate_sys_error(GetLastError()); goto error; } addrlen += pipe_prefix_len; - buf[addrlen++] = '\0'; - *len = addrlen; + *size = addrlen; err = 0; goto cleanup; @@ -2032,6 +2031,32 @@ int uv_pipe_pending_count(uv_pipe_t* handle) { } +int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) { + if (handle->flags & UV_HANDLE_BOUND) + return uv__pipe_getname(handle, buffer, size); + + if (handle->flags & UV_HANDLE_CONNECTION || + handle->handle != INVALID_HANDLE_VALUE) { + *size = 0; + return 0; + } + + return UV_EBADF; +} + + +int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { + /* emulate unix behaviour */ + if (handle->flags & UV_HANDLE_BOUND) + return UV_ENOTCONN; + + if (handle->handle != INVALID_HANDLE_VALUE) + return uv__pipe_getname(handle, buffer, size); + + return UV_EBADF; +} + + uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) { if (!handle->ipc) return UV_UNKNOWN_HANDLE; diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c index 622cbabe399e..4d8e1f99f65c 100644 --- a/deps/uv/src/win/poll.c +++ b/deps/uv/src/win/poll.c @@ -46,6 +46,8 @@ typedef struct uv_single_fd_set_s { static OVERLAPPED overlapped_dummy_; static uv_once_t overlapped_dummy_init_guard_ = UV_ONCE_INIT; +static AFD_POLL_INFO afd_poll_info_dummy_; + static void uv__init_overlapped_dummy(void) { HANDLE event; @@ -65,6 +67,11 @@ static OVERLAPPED* uv__get_overlapped_dummy() { } +static AFD_POLL_INFO* uv__get_afd_poll_info_dummy() { + return &afd_poll_info_dummy_; +} + + static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { uv_req_t* req; AFD_POLL_INFO* afd_poll_info; @@ -79,7 +86,7 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { handle->mask_events_2 = handle->events; } else if (handle->submitted_events_2 == 0) { req = &handle->poll_req_2; - afd_poll_info = &handle->afd_poll_info_2.afd_poll_info_ptr[0]; + afd_poll_info = &handle->afd_poll_info_2; handle->submitted_events_2 = handle->events; handle->mask_events_1 = handle->events; handle->mask_events_2 = 0; @@ -108,6 +115,7 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { memset(&req->overlapped, 0, sizeof req->overlapped); result = uv_msafd_poll((SOCKET) handle->peer_socket, + afd_poll_info, afd_poll_info, &req->overlapped); if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) { @@ -119,26 +127,25 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) { - AFD_POLL_INFO* afd_poll_info; + AFD_POLL_INFO afd_poll_info; DWORD result; - afd_poll_info = &handle->afd_poll_info_2.afd_poll_info_ptr[1]; - afd_poll_info->Exclusive = TRUE; - afd_poll_info->NumberOfHandles = 1; - afd_poll_info->Timeout.QuadPart = INT64_MAX; - afd_poll_info->Handles[0].Handle = (HANDLE) handle->socket; - afd_poll_info->Handles[0].Status = 0; - afd_poll_info->Handles[0].Events = AFD_POLL_ALL; + afd_poll_info.Exclusive = TRUE; + afd_poll_info.NumberOfHandles = 1; + afd_poll_info.Timeout.QuadPart = INT64_MAX; + afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket; + afd_poll_info.Handles[0].Status = 0; + afd_poll_info.Handles[0].Events = AFD_POLL_ALL; result = uv_msafd_poll(handle->socket, - afd_poll_info, + &afd_poll_info, + uv__get_afd_poll_info_dummy(), uv__get_overlapped_dummy()); if (result == SOCKET_ERROR) { DWORD error = WSAGetLastError(); - if (error != WSA_IO_PENDING) { - return WSAGetLastError(); - } + if (error != WSA_IO_PENDING) + return error; } return 0; @@ -155,7 +162,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, handle->submitted_events_1 = 0; mask_events = handle->mask_events_1; } else if (req == &handle->poll_req_2) { - afd_poll_info = &handle->afd_poll_info_2.afd_poll_info_ptr[0]; + afd_poll_info = &handle->afd_poll_info_2; handle->submitted_events_2 = 0; mask_events = handle->mask_events_2; } else { @@ -498,6 +505,11 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, int len; SOCKET peer_socket, base_socket; DWORD bytes; + DWORD yes = 1; + + /* Set the socket to nonblocking mode */ + if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) + return uv_translate_sys_error(WSAGetLastError()); /* Try to obtain a base handle for the socket. This increases this chances */ /* that we find an AFD handle and are able to use the fast poll mechanism. */ @@ -558,11 +570,6 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, handle->poll_req_2.type = UV_POLL_REQ; handle->poll_req_2.data = handle; - handle->afd_poll_info_2.afd_poll_info_ptr = malloc(sizeof(*handle->afd_poll_info_2.afd_poll_info_ptr) * 2); - if (handle->afd_poll_info_2.afd_poll_info_ptr == NULL) { - return UV_ENOMEM; - } - return 0; } @@ -624,9 +631,5 @@ void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) { assert(handle->submitted_events_1 == 0); assert(handle->submitted_events_2 == 0); - if (handle->afd_poll_info_2.afd_poll_info_ptr) { - free(handle->afd_poll_info_2.afd_poll_info_ptr); - handle->afd_poll_info_2.afd_poll_info_ptr = NULL; - } uv__handle_close(handle); } diff --git a/deps/uv/src/win/req-inl.h b/deps/uv/src/win/req-inl.h index 97342e5c7e00..0c825a3cd344 100644 --- a/deps/uv/src/win/req-inl.h +++ b/deps/uv/src/win/req-inl.h @@ -93,6 +93,17 @@ INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) { INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) { req->next_req = NULL; if (loop->pending_reqs_tail) { +#ifdef _DEBUG + /* Ensure the request is not already in the queue, or the queue + * will get corrupted. + */ + uv_req_t* current = loop->pending_reqs_tail; + do { + assert(req != current); + current = current->next_req; + } while(current != loop->pending_reqs_tail); +#endif + req->next_req = loop->pending_reqs_tail->next_req; loop->pending_reqs_tail->next_req = req; loop->pending_reqs_tail = req; @@ -130,14 +141,13 @@ INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) { } while (0) -INLINE static void uv_process_reqs(uv_loop_t* loop) { +INLINE static int uv_process_reqs(uv_loop_t* loop) { uv_req_t* req; uv_req_t* first; uv_req_t* next; - if (loop->pending_reqs_tail == NULL) { - return; - } + if (loop->pending_reqs_tail == NULL) + return 0; first = loop->pending_reqs_tail->next_req; next = first; @@ -207,6 +217,8 @@ INLINE static void uv_process_reqs(uv_loop_t* loop) { assert(0); } } + + return 1; } #endif /* UV_WIN_REQ_INL_H_ */ diff --git a/deps/uv/src/win/stream.c b/deps/uv/src/win/stream.c index 057f72ecad84..36d88d00bd98 100644 --- a/deps/uv/src/win/stream.c +++ b/deps/uv/src/win/stream.c @@ -184,8 +184,22 @@ int uv_write2(uv_write_t* req, int uv_try_write(uv_stream_t* stream, const uv_buf_t bufs[], unsigned int nbufs) { - /* NOTE: Won't work with overlapped writes */ - return UV_ENOSYS; + if (stream->flags & UV__HANDLE_CLOSING) + return UV_EBADF; + if (!(stream->flags & UV_HANDLE_WRITABLE)) + return UV_EPIPE; + + switch (stream->type) { + case UV_TCP: + return uv__tcp_try_write((uv_tcp_t*) stream, bufs, nbufs); + case UV_TTY: + return uv__tty_try_write((uv_tty_t*) stream, bufs, nbufs); + case UV_NAMED_PIPE: + return UV_EAGAIN; + default: + assert(0); + return UV_ENOSYS; + } } diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index cff2929e4cc6..c5ddbed08f75 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -876,6 +876,30 @@ int uv_tcp_write(uv_loop_t* loop, } +int uv__tcp_try_write(uv_tcp_t* handle, + const uv_buf_t bufs[], + unsigned int nbufs) { + int result; + DWORD bytes; + + if (handle->write_reqs_pending > 0) + return UV_EAGAIN; + + result = WSASend(handle->socket, + (WSABUF*) bufs, + nbufs, + &bytes, + 0, + NULL, + NULL); + + if (result == SOCKET_ERROR) + return uv_translate_sys_error(WSAGetLastError()); + else + return bytes; +} + + void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req) { DWORD bytes, flags, err; diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c index a697d7ae7445..9d273a56e700 100644 --- a/deps/uv/src/win/thread.c +++ b/deps/uv/src/win/thread.c @@ -30,53 +30,43 @@ #define HAVE_SRWLOCK_API() (pTryAcquireSRWLockShared != NULL) #define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL) -#ifdef _MSC_VER /* msvc */ -# define inline __inline -# define NOINLINE __declspec (noinline) -#else /* gcc */ -# define inline inline -# define NOINLINE __attribute__ ((noinline)) -#endif - - -inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock); -inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock); -inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock); - -inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock); -inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock); -inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock); -inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock); - - -inline static int uv_cond_fallback_init(uv_cond_t* cond); -inline static void uv_cond_fallback_destroy(uv_cond_t* cond); -inline static void uv_cond_fallback_signal(uv_cond_t* cond); -inline static void uv_cond_fallback_broadcast(uv_cond_t* cond); -inline static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex); -inline static int uv_cond_fallback_timedwait(uv_cond_t* cond, +static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock); +static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock); +static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock); +static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock); +static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock); +static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock); +static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock); +static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock); + +static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock); +static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock); +static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock); +static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock); +static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock); +static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock); +static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock); +static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock); + + +static int uv_cond_fallback_init(uv_cond_t* cond); +static void uv_cond_fallback_destroy(uv_cond_t* cond); +static void uv_cond_fallback_signal(uv_cond_t* cond); +static void uv_cond_fallback_broadcast(uv_cond_t* cond); +static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex); +static int uv_cond_fallback_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout); -inline static int uv_cond_condvar_init(uv_cond_t* cond); -inline static void uv_cond_condvar_destroy(uv_cond_t* cond); -inline static void uv_cond_condvar_signal(uv_cond_t* cond); -inline static void uv_cond_condvar_broadcast(uv_cond_t* cond); -inline static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex); -inline static int uv_cond_condvar_timedwait(uv_cond_t* cond, +static int uv_cond_condvar_init(uv_cond_t* cond); +static void uv_cond_condvar_destroy(uv_cond_t* cond); +static void uv_cond_condvar_signal(uv_cond_t* cond); +static void uv_cond_condvar_broadcast(uv_cond_t* cond); +static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex); +static int uv_cond_condvar_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout); -static NOINLINE void uv__once_inner(uv_once_t* guard, - void (*callback)(void)) { +static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) { DWORD result; HANDLE existing_event, created_event; @@ -117,7 +107,19 @@ void uv_once(uv_once_t* guard, void (*callback)(void)) { uv__once_inner(guard, callback); } -static UV_THREAD_LOCAL uv_thread_t uv__current_thread = NULL; + +/* Verify that uv_thread_t can be stored in a TLS slot. */ +STATIC_ASSERT(sizeof(uv_thread_t) <= sizeof(void*)); + +static uv_key_t uv__current_thread_key; +static uv_once_t uv__current_thread_init_guard = UV_ONCE_INIT; + + +static void uv__init_current_thread_key(void) { + if (uv_key_create(&uv__current_thread_key)) + abort(); +} + struct thread_ctx { void (*entry)(void* arg); @@ -126,8 +128,7 @@ struct thread_ctx { }; -static UINT __stdcall uv__thread_start(void* arg) -{ +static UINT __stdcall uv__thread_start(void* arg) { struct thread_ctx *ctx_p; struct thread_ctx ctx; @@ -135,7 +136,9 @@ static UINT __stdcall uv__thread_start(void* arg) ctx = *ctx_p; free(ctx_p); - uv__current_thread = ctx.self; + uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key); + uv_key_set(&uv__current_thread_key, (void*) ctx.self); + ctx.entry(ctx.arg); return 0; @@ -172,14 +175,26 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { ResumeThread(thread); } - return err; + switch (err) { + case 0: + return 0; + case EACCES: + return UV_EACCES; + case EAGAIN: + return UV_EAGAIN; + case EINVAL: + return UV_EINVAL; + } + + return UV_EIO; } uv_thread_t uv_thread_self(void) { - return uv__current_thread; + return (uv_thread_t) uv_key_get(&uv__current_thread_key); } + int uv_thread_join(uv_thread_t *tid) { if (WaitForSingleObject(*tid, INFINITE)) return uv_translate_sys_error(GetLastError()); @@ -332,23 +347,23 @@ int uv_sem_trywait(uv_sem_t* sem) { } -inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock) { +static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock) { pInitializeSRWLock(&rwlock->srwlock_); return 0; } -inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock) { +static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock) { (void) rwlock; } -inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock) { pAcquireSRWLockShared(&rwlock->srwlock_); } -inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) { +static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) { if (pTryAcquireSRWLockShared(&rwlock->srwlock_)) return 0; else @@ -356,17 +371,17 @@ inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) { } -inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock) { pReleaseSRWLockShared(&rwlock->srwlock_); } -inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock) { pAcquireSRWLockExclusive(&rwlock->srwlock_); } -inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) { +static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) { if (pTryAcquireSRWLockExclusive(&rwlock->srwlock_)) return 0; else @@ -374,12 +389,12 @@ inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) { } -inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock) { pReleaseSRWLockExclusive(&rwlock->srwlock_); } -inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) { +static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) { int err; err = uv_mutex_init(&rwlock->fallback_.read_mutex_); @@ -398,13 +413,13 @@ inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) { } -inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock) { +static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock) { uv_mutex_destroy(&rwlock->fallback_.read_mutex_); uv_mutex_destroy(&rwlock->fallback_.write_mutex_); } -inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock) { uv_mutex_lock(&rwlock->fallback_.read_mutex_); if (++rwlock->fallback_.num_readers_ == 1) @@ -414,7 +429,7 @@ inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock) { } -inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) { +static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) { int err; err = uv_mutex_trylock(&rwlock->fallback_.read_mutex_); @@ -435,7 +450,7 @@ inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) { } -inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) { uv_mutex_lock(&rwlock->fallback_.read_mutex_); if (--rwlock->fallback_.num_readers_ == 0) @@ -445,17 +460,17 @@ inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) { } -inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock) { uv_mutex_lock(&rwlock->fallback_.write_mutex_); } -inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock) { +static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock) { return uv_mutex_trylock(&rwlock->fallback_.write_mutex_); } -inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) { +static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) { uv_mutex_unlock(&rwlock->fallback_.write_mutex_); } @@ -468,7 +483,7 @@ inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) { * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs. */ -inline static int uv_cond_fallback_init(uv_cond_t* cond) { +static int uv_cond_fallback_init(uv_cond_t* cond) { int err; /* Initialize the count to 0. */ @@ -506,7 +521,7 @@ inline static int uv_cond_fallback_init(uv_cond_t* cond) { } -inline static int uv_cond_condvar_init(uv_cond_t* cond) { +static int uv_cond_condvar_init(uv_cond_t* cond) { pInitializeConditionVariable(&cond->cond_var); return 0; } @@ -522,7 +537,7 @@ int uv_cond_init(uv_cond_t* cond) { } -inline static void uv_cond_fallback_destroy(uv_cond_t* cond) { +static void uv_cond_fallback_destroy(uv_cond_t* cond) { if (!CloseHandle(cond->fallback.broadcast_event)) abort(); if (!CloseHandle(cond->fallback.signal_event)) @@ -531,7 +546,7 @@ inline static void uv_cond_fallback_destroy(uv_cond_t* cond) { } -inline static void uv_cond_condvar_destroy(uv_cond_t* cond) { +static void uv_cond_condvar_destroy(uv_cond_t* cond) { /* nothing to do */ } @@ -544,7 +559,7 @@ void uv_cond_destroy(uv_cond_t* cond) { } -inline static void uv_cond_fallback_signal(uv_cond_t* cond) { +static void uv_cond_fallback_signal(uv_cond_t* cond) { int have_waiters; /* Avoid race conditions. */ @@ -557,7 +572,7 @@ inline static void uv_cond_fallback_signal(uv_cond_t* cond) { } -inline static void uv_cond_condvar_signal(uv_cond_t* cond) { +static void uv_cond_condvar_signal(uv_cond_t* cond) { pWakeConditionVariable(&cond->cond_var); } @@ -570,7 +585,7 @@ void uv_cond_signal(uv_cond_t* cond) { } -inline static void uv_cond_fallback_broadcast(uv_cond_t* cond) { +static void uv_cond_fallback_broadcast(uv_cond_t* cond) { int have_waiters; /* Avoid race conditions. */ @@ -583,7 +598,7 @@ inline static void uv_cond_fallback_broadcast(uv_cond_t* cond) { } -inline static void uv_cond_condvar_broadcast(uv_cond_t* cond) { +static void uv_cond_condvar_broadcast(uv_cond_t* cond) { pWakeAllConditionVariable(&cond->cond_var); } @@ -596,7 +611,7 @@ void uv_cond_broadcast(uv_cond_t* cond) { } -inline int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex, +static int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex, DWORD dwMilliseconds) { DWORD result; int last_waiter; @@ -646,13 +661,13 @@ inline int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex, } -inline static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) { +static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) { if (uv_cond_wait_helper(cond, mutex, INFINITE)) abort(); } -inline static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) { +static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) { if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE)) abort(); } @@ -666,13 +681,13 @@ void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) { } -inline static int uv_cond_fallback_timedwait(uv_cond_t* cond, +static int uv_cond_fallback_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6)); } -inline static int uv_cond_condvar_timedwait(uv_cond_t* cond, +static int uv_cond_condvar_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6))) return 0; diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index 6d6709f79e11..603421045cac 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -170,7 +170,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { } -int uv_tty_set_mode(uv_tty_t* tty, int mode) { +int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { DWORD flags; unsigned char was_reading; uv_alloc_cb alloc_cb; @@ -185,12 +185,15 @@ int uv_tty_set_mode(uv_tty_t* tty, int mode) { return 0; } - if (mode) { - /* Raw input */ - flags = ENABLE_WINDOW_INPUT; - } else { - /* Line-buffered mode. */ - flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; + switch (mode) { + case UV_TTY_MODE_NORMAL: + flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; + break; + case UV_TTY_MODE_RAW: + flags = ENABLE_WINDOW_INPUT; + break; + case UV_TTY_MODE_IO: + return UV_ENOTSUP; } if (!SetConsoleMode(tty->handle, flags)) { @@ -1875,6 +1878,21 @@ int uv_tty_write(uv_loop_t* loop, } +int uv__tty_try_write(uv_tty_t* handle, + const uv_buf_t bufs[], + unsigned int nbufs) { + DWORD error; + + if (handle->write_reqs_pending > 0) + return UV_EAGAIN; + + if (uv_tty_write_bufs(handle, bufs, nbufs, &error)) + return uv_translate_sys_error(error); + + return uv__count_bufs(bufs, nbufs); +} + + void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, uv_write_t* req) { int err; diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c index 84ce73e3a023..f3f27f77c15a 100644 --- a/deps/uv/src/win/winapi.c +++ b/deps/uv/src/win/winapi.c @@ -31,6 +31,7 @@ sNtDeviceIoControlFile pNtDeviceIoControlFile; sNtQueryInformationFile pNtQueryInformationFile; sNtSetInformationFile pNtSetInformationFile; sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; +sNtQueryDirectoryFile pNtQueryDirectoryFile; sNtQuerySystemInformation pNtQuerySystemInformation; @@ -97,6 +98,12 @@ void uv_winapi_init() { uv_fatal_error(GetLastError(), "GetProcAddress"); } + pNtQueryDirectoryFile = (sNtQueryDirectoryFile) + GetProcAddress(ntdll_module, "NtQueryDirectoryFile"); + if (pNtQueryVolumeInformationFile == NULL) { + uv_fatal_error(GetLastError(), "GetProcAddress"); + } + pNtQuerySystemInformation = (sNtQuerySystemInformation) GetProcAddress( ntdll_module, "NtQuerySystemInformation"); diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index 1bb0e9aae1ee..f4f9145b388f 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4104,12 +4104,23 @@ # define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x00002000 #endif +/* from winternl.h */ +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +typedef const UNICODE_STRING *PCUNICODE_STRING; + +/* from ntifs.h */ #ifndef DEVICE_TYPE # define DEVICE_TYPE DWORD #endif -/* from ntifs.h */ -/* MinGW already has it, mingw-w64 does not. */ +/* MinGW already has a definition for REPARSE_DATA_BUFFER, but mingw-w64 does + * not. + */ #if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) typedef struct _REPARSE_DATA_BUFFER { ULONG ReparseTag; @@ -4205,6 +4216,37 @@ typedef enum _FILE_INFORMATION_CLASS { FileMaximumInformation } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; +typedef struct _FILE_DIRECTORY_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; + +typedef struct _FILE_BOTH_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + CCHAR ShortNameLength; + WCHAR ShortName[12]; + WCHAR FileName[1]; +} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; + typedef struct _FILE_BASIC_INFORMATION { LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; @@ -4512,6 +4554,19 @@ typedef NTSTATUS (NTAPI *sNtQuerySystemInformation) ULONG SystemInformationLength, PULONG ReturnLength); +typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile) + (HANDLE FileHandle, + HANDLE Event, + PIO_APC_ROUTINE ApcRoutine, + PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + PVOID FileInformation, + ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass, + BOOLEAN ReturnSingleEntry, + PUNICODE_STRING FileName, + BOOLEAN RestartScan + ); /* * Kernel32 headers @@ -4555,6 +4610,30 @@ typedef NTSTATUS (NTAPI *sNtQuerySystemInformation) # define ERROR_SYMLINK_NOT_SUPPORTED 1464 #endif +#ifndef ERROR_MUI_FILE_NOT_FOUND +# define ERROR_MUI_FILE_NOT_FOUND 15100 +#endif + +#ifndef ERROR_MUI_INVALID_FILE +# define ERROR_MUI_INVALID_FILE 15101 +#endif + +#ifndef ERROR_MUI_INVALID_RC_CONFIG +# define ERROR_MUI_INVALID_RC_CONFIG 15102 +#endif + +#ifndef ERROR_MUI_INVALID_LOCALE_NAME +# define ERROR_MUI_INVALID_LOCALE_NAME 15103 +#endif + +#ifndef ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME +# define ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME 15104 +#endif + +#ifndef ERROR_MUI_FILE_NOT_LOADED +# define ERROR_MUI_FILE_NOT_LOADED 15105 +#endif + typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx) (HANDLE CompletionPort, LPOVERLAPPED_ENTRY lpCompletionPortEntries, @@ -4626,6 +4705,7 @@ extern sNtDeviceIoControlFile pNtDeviceIoControlFile; extern sNtQueryInformationFile pNtQueryInformationFile; extern sNtSetInformationFile pNtSetInformationFile; extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; +extern sNtQueryDirectoryFile pNtQueryDirectoryFile; extern sNtQuerySystemInformation pNtQuerySystemInformation; diff --git a/deps/uv/src/win/winsock.c b/deps/uv/src/win/winsock.c index 3711ee9cb673..d2e667e9f754 100644 --- a/deps/uv/src/win/winsock.c +++ b/deps/uv/src/win/winsock.c @@ -474,8 +474,8 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, } -int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info, - OVERLAPPED* overlapped) { +int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, + AFD_POLL_INFO* info_out, OVERLAPPED* overlapped) { IO_STATUS_BLOCK iosb; IO_STATUS_BLOCK* iosb_ptr; HANDLE event = NULL; @@ -513,10 +513,10 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info, apc_context, iosb_ptr, IOCTL_AFD_POLL, - info, - sizeof *info, - info, - sizeof *info); + info_in, + sizeof *info_in, + info_out, + sizeof *info_out); if (overlapped == NULL) { /* If this is a blocking operation, wait for the event to become */ diff --git a/deps/uv/test/runner-unix.c b/deps/uv/test/runner-unix.c index 1f12c6f12d91..5da720fad43a 100644 --- a/deps/uv/test/runner-unix.c +++ b/deps/uv/test/runner-unix.c @@ -68,6 +68,7 @@ int process_start(char* name, char* part, process_info_t* p, int is_helper) { const char* arg; char* args[16]; int n; + pid_t pid; stdout_file = tmpfile(); if (!stdout_file) { @@ -78,7 +79,7 @@ int process_start(char* name, char* part, process_info_t* p, int is_helper) { p->terminated = 0; p->status = 0; - pid_t pid = fork(); + pid = fork(); if (pid < 0) { perror("fork"); @@ -167,8 +168,14 @@ static void* dowait(void* data) { /* Return 0 if all processes are terminated, -1 on error, -2 on timeout. */ int process_wait(process_info_t* vec, int n, int timeout) { int i; + int r; + int retval; process_info_t* p; dowait_args args; + pthread_t tid; + struct timeval tv; + fd_set fds; + args.vec = vec; args.n = n; args.pipe[0] = -1; @@ -186,10 +193,7 @@ int process_wait(process_info_t* vec, int n, int timeout) { * we'd need to lock vec. */ - pthread_t tid; - int retval; - - int r = pipe((int*)&(args.pipe)); + r = pipe((int*)&(args.pipe)); if (r) { perror("pipe()"); return -1; @@ -202,11 +206,9 @@ int process_wait(process_info_t* vec, int n, int timeout) { goto terminate; } - struct timeval tv; tv.tv_sec = timeout / 1000; tv.tv_usec = 0; - fd_set fds; FD_ZERO(&fds); FD_SET(args.pipe[0], &fds); @@ -259,15 +261,16 @@ long int process_output_size(process_info_t *p) { /* Copy the contents of the stdio output buffer to `fd`. */ int process_copy_output(process_info_t *p, int fd) { - int r = fseek(p->stdout_file, 0, SEEK_SET); + ssize_t nwritten; + char buf[1024]; + int r; + + r = fseek(p->stdout_file, 0, SEEK_SET); if (r < 0) { perror("fseek"); return -1; } - ssize_t nwritten; - char buf[1024]; - /* TODO: what if the line is longer than buf */ while (fgets(buf, sizeof(buf), p->stdout_file) != NULL) { /* TODO: what if write doesn't write the whole buffer... */ diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index e890c77fe177..07584c52996f 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -39,6 +39,11 @@ # include /* setrlimit() */ #endif +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wvariadic-macros" +# pragma clang diagnostic ignored "-Wc99-extensions" +#endif + #define TEST_PORT 9123 #define TEST_PORT_2 9124 @@ -229,4 +234,21 @@ UNUSED static void close_loop(uv_loop_t* loop) { uv_run(loop, UV_RUN_DEFAULT); } +UNUSED static int can_ipv6(void) { + uv_interface_address_t* addr; + int supported; + int count; + int i; + + if (uv_interface_addresses(&addr, &count)) + return 1; /* Assume IPv6 support on failure. */ + + supported = 0; + for (i = 0; supported == 0 && i < count; i += 1) + supported = (AF_INET6 == addr[i].address.address6.sin6_family); + + uv_free_interface_addresses(addr, count); + return supported; +} + #endif /* TASK_H_ */ diff --git a/deps/uv/test/test-close-fd.c b/deps/uv/test/test-close-fd.c index 0d17f0766150..93a7bd7c0210 100644 --- a/deps/uv/test/test-close-fd.c +++ b/deps/uv/test/test-close-fd.c @@ -54,7 +54,6 @@ TEST_IMPL(close_fd) { int fd[2]; ASSERT(0 == pipe(fd)); - ASSERT(0 == fcntl(fd[0], F_SETFL, O_NONBLOCK)); ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0)); ASSERT(0 == uv_pipe_open(&pipe_handle, fd[0])); fd[0] = -1; /* uv_pipe_open() takes ownership of the file descriptor. */ diff --git a/deps/uv/test/test-cwd-and-chdir.c b/deps/uv/test/test-cwd-and-chdir.c index 6f6173192dbb..1e95043c1775 100644 --- a/deps/uv/test/test-cwd-and-chdir.c +++ b/deps/uv/test/test-cwd-and-chdir.c @@ -29,35 +29,22 @@ extern char executable_path[]; TEST_IMPL(cwd_and_chdir) { char buffer_orig[PATHMAX]; char buffer_new[PATHMAX]; - size_t size; - char* last_slash; + size_t size1; + size_t size2; int err; - size = sizeof(buffer_orig); - err = uv_cwd(buffer_orig, &size); + size1 = sizeof buffer_orig; + err = uv_cwd(buffer_orig, &size1); ASSERT(err == 0); - /* Remove trailing slash unless at a root directory. */ -#ifdef _WIN32 - last_slash = strrchr(buffer_orig, '\\'); - ASSERT(last_slash); - if (last_slash > buffer_orig && *(last_slash - 1) != ':') { - *last_slash = '\0'; - } -#else /* Unix */ - last_slash = strrchr(buffer_orig, '/'); - ASSERT(last_slash); - if (last_slash != buffer_orig) { - *last_slash = '\0'; - } -#endif - err = uv_chdir(buffer_orig); ASSERT(err == 0); - err = uv_cwd(buffer_new, &size); + size2 = sizeof buffer_new; + err = uv_cwd(buffer_new, &size2); ASSERT(err == 0); + ASSERT(size1 == size2); ASSERT(strcmp(buffer_orig, buffer_new) == 0); return 0; diff --git a/deps/uv/test/test-dlerror.c b/deps/uv/test/test-dlerror.c index 877ebf3712a2..091200edbed5 100644 --- a/deps/uv/test/test-dlerror.c +++ b/deps/uv/test/test-dlerror.c @@ -26,31 +26,28 @@ TEST_IMPL(dlerror) { const char* path = "test/fixtures/load_error.node"; + const char* dlerror_no_error = "no error"; const char* msg; uv_lib_t lib; int r; -#ifdef __linux__ - const char* dlerror_desc = "file too short"; -#elif defined (__sun__) - const char* dlerror_desc = "unknown file type"; -#elif defined (_WIN32) - const char* dlerror_desc = "%1 is not a valid Win32 application"; -#else - const char* dlerror_desc = ""; -#endif + lib.errmsg = NULL; + lib.handle = NULL; + msg = uv_dlerror(&lib); + ASSERT(msg != NULL); + ASSERT(strstr(msg, dlerror_no_error) != NULL); r = uv_dlopen(path, &lib); ASSERT(r == -1); msg = uv_dlerror(&lib); ASSERT(msg != NULL); - ASSERT(strstr(msg, dlerror_desc) != NULL); + ASSERT(strstr(msg, dlerror_no_error) == NULL); /* Should return the same error twice in a row. */ msg = uv_dlerror(&lib); ASSERT(msg != NULL); - ASSERT(strstr(msg, dlerror_desc) != NULL); + ASSERT(strstr(msg, dlerror_no_error) == NULL); uv_dlclose(&lib); diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index 5fd8da430b29..0a2ba331455d 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -642,6 +642,7 @@ TEST_IMPL(fs_event_getpath) { len = sizeof buf; r = uv_fs_event_getpath(&fs_event, buf, &len); ASSERT(r == 0); + ASSERT(buf[len - 1] != 0); ASSERT(memcmp(buf, "watch_dir", len) == 0); r = uv_fs_event_stop(&fs_event); ASSERT(r == 0); diff --git a/deps/uv/test/test-fs-poll.c b/deps/uv/test/test-fs-poll.c index f4eb08408fac..dbc1515b0b1b 100644 --- a/deps/uv/test/test-fs-poll.c +++ b/deps/uv/test/test-fs-poll.c @@ -172,6 +172,7 @@ TEST_IMPL(fs_poll_getpath) { ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100)); len = sizeof buf; ASSERT(0 == uv_fs_poll_getpath(&poll_handle, buf, &len)); + ASSERT(buf[len - 1] != 0); ASSERT(0 == memcmp(buf, FIXTURE, len)); uv_close((uv_handle_t*) &poll_handle, close_cb); diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 471860a76c4c..cc5dc744501e 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -436,7 +436,11 @@ static void scandir_cb(uv_fs_t* req) { while (UV_EOF != uv_fs_scandir_next(req, &dent)) { ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); - ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); +#ifdef HAVE_DIRENT_TYPES + ASSERT(dent.type == UV_DIRENT_FILE); +#else + ASSERT(dent.type == UV_DIRENT_UNKNOWN); +#endif } scandir_cb_count++; ASSERT(req->path); @@ -568,7 +572,17 @@ TEST_IMPL(fs_file_loop) { loop = uv_default_loop(); unlink("test_symlink"); - uv_fs_symlink(loop, &req, "test_symlink", "test_symlink", 0, NULL); + r = uv_fs_symlink(loop, &req, "test_symlink", "test_symlink", 0, NULL); +#ifdef _WIN32 + /* + * Windows XP and Server 2003 don't support symlinks; we'll get UV_ENOTSUP. + * Starting with vista they are supported, but only when elevated, otherwise + * we'll see UV_EPERM. + */ + if (r == UV_ENOTSUP || r == UV_EPERM) + return 0; +#endif + ASSERT(r == 0); uv_fs_req_cleanup(&req); r = uv_fs_open(loop, &req, "test_symlink", O_RDONLY, 0, NULL); @@ -865,7 +879,11 @@ TEST_IMPL(fs_async_dir) { ASSERT(scandir_req.ptr); while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); - ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); +#ifdef HAVE_DIRENT_TYPES + ASSERT(dent.type == UV_DIRENT_FILE); +#else + ASSERT(dent.type == UV_DIRENT_UNKNOWN); +#endif } uv_fs_req_cleanup(&scandir_req); ASSERT(!scandir_req.ptr); @@ -1685,7 +1703,11 @@ TEST_IMPL(fs_symlink_dir) { ASSERT(scandir_req.ptr); while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); - ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); +#ifdef HAVE_DIRENT_TYPES + ASSERT(dent.type == UV_DIRENT_FILE); +#else + ASSERT(dent.type == UV_DIRENT_UNKNOWN); +#endif } uv_fs_req_cleanup(&scandir_req); ASSERT(!scandir_req.ptr); @@ -1705,7 +1727,11 @@ TEST_IMPL(fs_symlink_dir) { ASSERT(scandir_req.ptr); while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) { ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); - ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); +#ifdef HAVE_DIRENT_TYPES + ASSERT(dent.type == UV_DIRENT_FILE); +#else + ASSERT(dent.type == UV_DIRENT_UNKNOWN); +#endif } uv_fs_req_cleanup(&scandir_req); ASSERT(!scandir_req.ptr); diff --git a/deps/uv/test/test-get-currentexe.c b/deps/uv/test/test-get-currentexe.c index be578db75d48..0e9d6965402d 100644 --- a/deps/uv/test/test-get-currentexe.c +++ b/deps/uv/test/test-get-currentexe.c @@ -61,5 +61,26 @@ TEST_IMPL(get_currentexe) { r = uv_exepath(buffer, NULL); ASSERT(r == UV_EINVAL); + size = 0; + r = uv_exepath(buffer, &size); + ASSERT(r == UV_EINVAL); + + memset(buffer, -1, sizeof(buffer)); + + size = 1; + r = uv_exepath(buffer, &size); + ASSERT(r == 0); + ASSERT(size == 0); + ASSERT(buffer[0] == '\0'); + + memset(buffer, -1, sizeof(buffer)); + + size = 2; + r = uv_exepath(buffer, &size); + ASSERT(r == 0); + ASSERT(size == 1); + ASSERT(buffer[0] != '\0'); + ASSERT(buffer[1] == '\0'); + return 0; } diff --git a/deps/uv/test/test-getaddrinfo.c b/deps/uv/test/test-getaddrinfo.c index 32ca91effa6e..45813c313af2 100644 --- a/deps/uv/test/test-getaddrinfo.c +++ b/deps/uv/test/test-getaddrinfo.c @@ -97,6 +97,22 @@ TEST_IMPL(getaddrinfo_fail) { } +TEST_IMPL(getaddrinfo_fail_sync) { + uv_getaddrinfo_t req; + + ASSERT(0 > uv_getaddrinfo(uv_default_loop(), + &req, + NULL, + "xyzzy.xyzzy.xyzzy", + NULL, + NULL)); + uv_freeaddrinfo(req.addrinfo); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(getaddrinfo_basic) { int r; getaddrinfo_handle = (uv_getaddrinfo_t*)malloc(sizeof(uv_getaddrinfo_t)); @@ -118,6 +134,22 @@ TEST_IMPL(getaddrinfo_basic) { } +TEST_IMPL(getaddrinfo_basic_sync) { + uv_getaddrinfo_t req; + + ASSERT(0 == uv_getaddrinfo(uv_default_loop(), + &req, + NULL, + name, + NULL, + NULL)); + uv_freeaddrinfo(req.addrinfo); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(getaddrinfo_concurrent) { int i, r; int* data; diff --git a/deps/uv/test/test-getnameinfo.c b/deps/uv/test/test-getnameinfo.c index 1ea0f3a43748..ebe9246699db 100644 --- a/deps/uv/test/test-getnameinfo.c +++ b/deps/uv/test/test-getnameinfo.c @@ -44,6 +44,7 @@ static void getnameinfo_req(uv_getnameinfo_t* handle, ASSERT(service != NULL); } + TEST_IMPL(getnameinfo_basic_ip4) { int r; @@ -63,6 +64,23 @@ TEST_IMPL(getnameinfo_basic_ip4) { return 0; } + +TEST_IMPL(getnameinfo_basic_ip4_sync) { + ASSERT(0 == uv_ip4_addr(address_ip4, port, &addr4)); + + ASSERT(0 == uv_getnameinfo(uv_default_loop(), + &req, + NULL, + (const struct sockaddr*)&addr4, + 0)); + ASSERT(req.host != NULL); + ASSERT(req.service != NULL); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(getnameinfo_basic_ip6) { int r; diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 85ddac82ae12..aac15e0d9df0 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -29,6 +29,7 @@ TEST_DECLARE (loop_close) TEST_DECLARE (loop_stop) TEST_DECLARE (loop_update_time) TEST_DECLARE (loop_backend_timeout) +TEST_DECLARE (loop_configure) TEST_DECLARE (default_loop_close) TEST_DECLARE (barrier_1) TEST_DECLARE (barrier_2) @@ -79,6 +80,7 @@ TEST_DECLARE (tcp_close_while_connecting) TEST_DECLARE (tcp_close) #ifndef _WIN32 TEST_DECLARE (tcp_close_accept) +TEST_DECLARE (tcp_oob) #endif TEST_DECLARE (tcp_flags) TEST_DECLARE (tcp_write_to_half_open_connection) @@ -103,6 +105,7 @@ TEST_DECLARE (udp_dgram_too_big) TEST_DECLARE (udp_dual_stack) TEST_DECLARE (udp_ipv6_only) TEST_DECLARE (udp_options) +TEST_DECLARE (udp_options6) TEST_DECLARE (udp_no_autobind) TEST_DECLARE (udp_open) TEST_DECLARE (udp_try_send) @@ -165,6 +168,7 @@ TEST_DECLARE (pipe_ref4) #ifndef _WIN32 TEST_DECLARE (pipe_close_stdout_read_stdin) #endif +TEST_DECLARE (pipe_set_non_blocking) TEST_DECLARE (process_ref) TEST_DECLARE (has_ref) TEST_DECLARE (active) @@ -178,9 +182,12 @@ TEST_DECLARE (get_memory) TEST_DECLARE (handle_fileno) TEST_DECLARE (hrtime) TEST_DECLARE (getaddrinfo_fail) +TEST_DECLARE (getaddrinfo_fail_sync) TEST_DECLARE (getaddrinfo_basic) +TEST_DECLARE (getaddrinfo_basic_sync) TEST_DECLARE (getaddrinfo_concurrent) TEST_DECLARE (getnameinfo_basic_ip4) +TEST_DECLARE (getnameinfo_basic_ip4_sync) TEST_DECLARE (getnameinfo_basic_ip6) TEST_DECLARE (getsockname_tcp) TEST_DECLARE (getsockname_udp) @@ -269,6 +276,7 @@ TEST_DECLARE (ip4_addr) TEST_DECLARE (ip6_addr_link_local) #ifdef _WIN32 +TEST_DECLARE (poll_close_doesnt_corrupt_stack) TEST_DECLARE (poll_closesocket) TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) TEST_DECLARE (argument_escaping) @@ -312,6 +320,7 @@ TASK_LIST_START TEST_ENTRY (loop_stop) TEST_ENTRY (loop_update_time) TEST_ENTRY (loop_backend_timeout) + TEST_ENTRY (loop_configure) TEST_ENTRY (default_loop_close) TEST_ENTRY (barrier_1) TEST_ENTRY (barrier_2) @@ -332,6 +341,7 @@ TASK_LIST_START #ifndef _WIN32 TEST_ENTRY (pipe_close_stdout_read_stdin) #endif + TEST_ENTRY (pipe_set_non_blocking) TEST_ENTRY (tty) TEST_ENTRY (stdio_over_pipes) TEST_ENTRY (ip6_pton) @@ -387,6 +397,7 @@ TASK_LIST_START TEST_ENTRY (tcp_close) #ifndef _WIN32 TEST_ENTRY (tcp_close_accept) + TEST_ENTRY (tcp_oob) #endif TEST_ENTRY (tcp_flags) TEST_ENTRY (tcp_write_to_half_open_connection) @@ -410,6 +421,7 @@ TASK_LIST_START TEST_ENTRY (udp_dual_stack) TEST_ENTRY (udp_ipv6_only) TEST_ENTRY (udp_options) + TEST_ENTRY (udp_options6) TEST_ENTRY (udp_no_autobind) TEST_ENTRY (udp_multicast_interface) TEST_ENTRY (udp_multicast_interface6) @@ -519,11 +531,14 @@ TASK_LIST_START TEST_ENTRY (hrtime) TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000) + TEST_ENTRY (getaddrinfo_fail_sync) TEST_ENTRY (getaddrinfo_basic) + TEST_ENTRY (getaddrinfo_basic_sync) TEST_ENTRY (getaddrinfo_concurrent) TEST_ENTRY (getnameinfo_basic_ip4) + TEST_ENTRY (getnameinfo_basic_ip4_sync) TEST_ENTRY (getnameinfo_basic_ip6) TEST_ENTRY (getsockname_tcp) @@ -558,6 +573,7 @@ TASK_LIST_START TEST_ENTRY (kill) #ifdef _WIN32 + TEST_ENTRY (poll_close_doesnt_corrupt_stack) TEST_ENTRY (poll_closesocket) TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows) TEST_ENTRY (argument_escaping) diff --git a/deps/uv/test/test-loop-configure.c b/deps/uv/test/test-loop-configure.c new file mode 100644 index 000000000000..d057c1ed8a7b --- /dev/null +++ b/deps/uv/test/test-loop-configure.c @@ -0,0 +1,38 @@ +/* Copyright (c) 2014, Ben Noordhuis + * + * 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.h" +#include "task.h" + +static void timer_cb(uv_timer_t* handle) { + uv_close((uv_handle_t*) handle, NULL); +} + + +TEST_IMPL(loop_configure) { + uv_timer_t timer_handle; + uv_loop_t loop; + ASSERT(0 == uv_loop_init(&loop)); +#ifdef _WIN32 + ASSERT(UV_ENOSYS == uv_loop_configure(&loop, UV_LOOP_BLOCK_SIGNAL, 0)); +#else + ASSERT(0 == uv_loop_configure(&loop, UV_LOOP_BLOCK_SIGNAL, SIGPROF)); +#endif + ASSERT(0 == uv_timer_init(&loop, &timer_handle)); + ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 10, 0)); + ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT)); + ASSERT(0 == uv_loop_close(&loop)); + return 0; +} diff --git a/deps/uv/test/test-osx-select.c b/deps/uv/test/test-osx-select.c index 49b1bb8229ae..6ccf60348348 100644 --- a/deps/uv/test/test-osx-select.c +++ b/deps/uv/test/test-osx-select.c @@ -54,8 +54,10 @@ TEST_IMPL(osx_select) { uv_tty_t tty; fd = open("/dev/tty", O_RDONLY); - - ASSERT(fd >= 0); + if (fd < 0) { + LOGF("Cannot open /dev/tty as read-only: %s\n", strerror(errno)); + return TEST_SKIP; + } r = uv_tty_init(uv_default_loop(), &tty, fd, 1); ASSERT(r == 0); @@ -90,7 +92,7 @@ TEST_IMPL(osx_select_many_fds) { uv_tty_t tty; uv_tcp_t tcps[1500]; - TEST_FILE_LIMIT(ARRAY_SIZE(tcps) + 2); + TEST_FILE_LIMIT(ARRAY_SIZE(tcps) + 100); r = uv_ip4_addr("127.0.0.1", 0, &addr); ASSERT(r == 0); @@ -104,7 +106,10 @@ TEST_IMPL(osx_select_many_fds) { } fd = open("/dev/tty", O_RDONLY); - ASSERT(fd >= 0); + if (fd < 0) { + LOGF("Cannot open /dev/tty as read-only: %s\n", strerror(errno)); + return TEST_SKIP; + } r = uv_tty_init(uv_default_loop(), &tty, fd, 1); ASSERT(r == 0); diff --git a/deps/uv/test/test-ping-pong.c b/deps/uv/test/test-ping-pong.c index 81941ab83db3..c074178541b0 100644 --- a/deps/uv/test/test-ping-pong.c +++ b/deps/uv/test/test-ping-pong.c @@ -246,6 +246,9 @@ TEST_IMPL(tcp_ping_pong) { TEST_IMPL(tcp_ping_pong_v6) { + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + tcp_pinger_v6_new(); uv_run(uv_default_loop(), UV_RUN_DEFAULT); diff --git a/deps/uv/test/test-pipe-close-stdout-read-stdin.c b/deps/uv/test/test-pipe-close-stdout-read-stdin.c index 3064babf98c0..ee8bb2a9a8bc 100644 --- a/deps/uv/test/test-pipe-close-stdout-read-stdin.c +++ b/deps/uv/test/test-pipe-close-stdout-read-stdin.c @@ -53,6 +53,7 @@ TEST_IMPL(pipe_close_stdout_read_stdin) { int pid; int fd[2]; int status; + uv_pipe_t stdin_pipe; r = pipe(fd); ASSERT(r == 0); @@ -68,8 +69,6 @@ TEST_IMPL(pipe_close_stdout_read_stdin) { ASSERT(r != -1); /* Create a stream that reads from the pipe. */ - uv_pipe_t stdin_pipe; - r = uv_pipe_init(uv_default_loop(), (uv_pipe_t *)&stdin_pipe, 0); ASSERT(r == 0); diff --git a/deps/uv/test/test-pipe-getsockname.c b/deps/uv/test/test-pipe-getsockname.c index d4010f3b5070..5e036f9d528a 100644 --- a/deps/uv/test/test-pipe-getsockname.c +++ b/deps/uv/test/test-pipe-getsockname.c @@ -36,38 +36,121 @@ # include #endif +static uv_pipe_t pipe_client; +static uv_pipe_t pipe_server; +static uv_connect_t connect_req; -static int close_cb_called = 0; +static int pipe_close_cb_called = 0; +static int pipe_client_connect_cb_called = 0; -static void close_cb(uv_handle_t* handle) { - ASSERT(handle != NULL); - close_cb_called++; +static void pipe_close_cb(uv_handle_t* handle) { + ASSERT(handle == (uv_handle_t*) &pipe_client || + handle == (uv_handle_t*) &pipe_server); + pipe_close_cb_called++; +} + + +static void pipe_client_connect_cb(uv_connect_t* req, int status) { + char buf[1024]; + size_t len; + int r; + + ASSERT(req == &connect_req); + ASSERT(status == 0); + + len = sizeof buf; + r = uv_pipe_getpeername(&pipe_client, buf, &len); + ASSERT(r == 0); + + ASSERT(buf[len - 1] != 0); + ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); + + len = sizeof buf; + r = uv_pipe_getsockname(&pipe_client, buf, &len); + ASSERT(r == 0 && len == 0); + + pipe_client_connect_cb_called++; + + + uv_close((uv_handle_t*) &pipe_client, pipe_close_cb); + uv_close((uv_handle_t*) &pipe_server, pipe_close_cb); +} + + +static void pipe_server_connection_cb(uv_stream_t* handle, int status) { + /* This function *may* be called, depending on whether accept or the + * connection callback is called first. + */ + ASSERT(status == 0); } TEST_IMPL(pipe_getsockname) { - uv_pipe_t server; + uv_loop_t* loop; char buf[1024]; size_t len; int r; - r = uv_pipe_init(uv_default_loop(), &server, 0); + loop = uv_default_loop(); + ASSERT(loop != NULL); + + r = uv_pipe_init(loop, &pipe_server, 0); ASSERT(r == 0); - r = uv_pipe_bind(&server, TEST_PIPENAME); + + len = sizeof buf; + r = uv_pipe_getsockname(&pipe_server, buf, &len); + ASSERT(r == UV_EBADF); + + len = sizeof buf; + r = uv_pipe_getpeername(&pipe_server, buf, &len); + ASSERT(r == UV_EBADF); + + r = uv_pipe_bind(&pipe_server, TEST_PIPENAME); ASSERT(r == 0); len = sizeof buf; - r = uv_pipe_getsockname(&server, buf, &len); + r = uv_pipe_getsockname(&pipe_server, buf, &len); ASSERT(r == 0); + ASSERT(buf[len - 1] != 0); ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); - uv_close((uv_handle_t*)&server, close_cb); + len = sizeof buf; + r = uv_pipe_getpeername(&pipe_server, buf, &len); + ASSERT(r == UV_ENOTCONN); - uv_run(uv_default_loop(), UV_RUN_DEFAULT); + r = uv_listen((uv_stream_t*) &pipe_server, 0, pipe_server_connection_cb); + ASSERT(r == 0); + + r = uv_pipe_init(loop, &pipe_client, 0); + ASSERT(r == 0); + + len = sizeof buf; + r = uv_pipe_getsockname(&pipe_client, buf, &len); + ASSERT(r == UV_EBADF); - ASSERT(close_cb_called == 1); + len = sizeof buf; + r = uv_pipe_getpeername(&pipe_client, buf, &len); + ASSERT(r == UV_EBADF); + + uv_pipe_connect(&connect_req, &pipe_client, TEST_PIPENAME, pipe_client_connect_cb); + + len = sizeof buf; + r = uv_pipe_getsockname(&pipe_client, buf, &len); + ASSERT(r == 0 && len == 0); + + len = sizeof buf; + r = uv_pipe_getpeername(&pipe_client, buf, &len); + ASSERT(r == 0); + + ASSERT(buf[len - 1] != 0); + ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0); + + r = uv_run(loop, UV_RUN_DEFAULT); + ASSERT(r == 0); + ASSERT(pipe_client_connect_cb_called == 1); + ASSERT(pipe_close_cb_called == 2); MAKE_VALGRIND_HAPPY(); return 0; @@ -76,7 +159,6 @@ TEST_IMPL(pipe_getsockname) { TEST_IMPL(pipe_getsockname_abstract) { #if defined(__linux__) - uv_pipe_t server; char buf[1024]; size_t len; int r; @@ -96,24 +178,24 @@ TEST_IMPL(pipe_getsockname_abstract) { r = bind(sock, (struct sockaddr*)&sun, sun_len); ASSERT(r == 0); - r = uv_pipe_init(uv_default_loop(), &server, 0); + r = uv_pipe_init(uv_default_loop(), &pipe_server, 0); ASSERT(r == 0); - r = uv_pipe_open(&server, sock); + r = uv_pipe_open(&pipe_server, sock); ASSERT(r == 0); len = sizeof buf; - r = uv_pipe_getsockname(&server, buf, &len); + r = uv_pipe_getsockname(&pipe_server, buf, &len); ASSERT(r == 0); ASSERT(memcmp(buf, abstract_pipe, sizeof abstract_pipe) == 0); - uv_close((uv_handle_t*)&server, close_cb); + uv_close((uv_handle_t*)&pipe_server, pipe_close_cb); uv_run(uv_default_loop(), UV_RUN_DEFAULT); close(sock); - ASSERT(close_cb_called == 1); + ASSERT(pipe_close_cb_called == 1); MAKE_VALGRIND_HAPPY(); return 0; #else @@ -124,7 +206,6 @@ TEST_IMPL(pipe_getsockname_abstract) { TEST_IMPL(pipe_getsockname_blocking) { #ifdef _WIN32 - uv_pipe_t reader; HANDLE readh, writeh; int readfd; char buf1[1024], buf2[1024]; @@ -134,42 +215,44 @@ TEST_IMPL(pipe_getsockname_blocking) { r = CreatePipe(&readh, &writeh, NULL, 65536); ASSERT(r != 0); - r = uv_pipe_init(uv_default_loop(), &reader, 0); + r = uv_pipe_init(uv_default_loop(), &pipe_client, 0); ASSERT(r == 0); readfd = _open_osfhandle((intptr_t)readh, _O_RDONLY); ASSERT(r != -1); - r = uv_pipe_open(&reader, readfd); + r = uv_pipe_open(&pipe_client, readfd); ASSERT(r == 0); - r = uv_read_start((uv_stream_t*)&reader, NULL, NULL); + r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL); ASSERT(r == 0); Sleep(100); - r = uv_read_stop((uv_stream_t*)&reader); + r = uv_read_stop((uv_stream_t*)&pipe_client); ASSERT(r == 0); len1 = sizeof buf1; - r = uv_pipe_getsockname(&reader, buf1, &len1); + r = uv_pipe_getsockname(&pipe_client, buf1, &len1); ASSERT(r == 0); + ASSERT(buf1[len1 - 1] != 0); - r = uv_read_start((uv_stream_t*)&reader, NULL, NULL); + r = uv_read_start((uv_stream_t*)&pipe_client, NULL, NULL); ASSERT(r == 0); Sleep(100); len2 = sizeof buf2; - r = uv_pipe_getsockname(&reader, buf2, &len2); + r = uv_pipe_getsockname(&pipe_client, buf2, &len2); ASSERT(r == 0); + ASSERT(buf2[len2 - 1] != 0); - r = uv_read_stop((uv_stream_t*)&reader); + r = uv_read_stop((uv_stream_t*)&pipe_client); ASSERT(r == 0); ASSERT(len1 == len2); ASSERT(memcmp(buf1, buf2, len1) == 0); - close_cb_called = 0; - uv_close((uv_handle_t*)&reader, close_cb); + pipe_close_cb_called = 0; + uv_close((uv_handle_t*)&pipe_client, pipe_close_cb); uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(close_cb_called == 1); + ASSERT(pipe_close_cb_called == 1); _close(readfd); CloseHandle(writeh); diff --git a/deps/uv/test/test-pipe-set-non-blocking.c b/deps/uv/test/test-pipe-set-non-blocking.c new file mode 100644 index 000000000000..5cf2c19e7fbd --- /dev/null +++ b/deps/uv/test/test-pipe-set-non-blocking.c @@ -0,0 +1,99 @@ +/* Copyright (c) 2015, Ben Noordhuis + * + * 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.h" +#include "task.h" + +#ifdef _WIN32 + +TEST_IMPL(pipe_set_non_blocking) { + RETURN_SKIP("Test not implemented on Windows."); +} + +#else /* !_WIN32 */ + +#include +#include +#include +#include +#include +#include + +struct thread_ctx { + uv_barrier_t barrier; + int fd; +}; + +static void thread_main(void* arg) { + struct thread_ctx* ctx; + char buf[4096]; + ssize_t n; + + ctx = arg; + uv_barrier_wait(&ctx->barrier); + + do + n = read(ctx->fd, buf, sizeof(buf)); + while (n > 0 || (n == -1 && errno == EINTR)); + + ASSERT(n == 0); +} + +TEST_IMPL(pipe_set_non_blocking) { + struct thread_ctx ctx; + uv_pipe_t pipe_handle; + uv_thread_t thread; + size_t nwritten; + char data[4096]; + uv_buf_t buf; + int fd[2]; + int n; + + ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0)); + ASSERT(0 == socketpair(AF_UNIX, SOCK_STREAM, 0, fd)); + ASSERT(0 == uv_pipe_open(&pipe_handle, fd[0])); + ASSERT(0 == uv_stream_set_blocking((uv_stream_t*) &pipe_handle, 1)); + + ctx.fd = fd[1]; + ASSERT(0 == uv_barrier_init(&ctx.barrier, 2)); + ASSERT(0 == uv_thread_create(&thread, thread_main, &ctx)); + uv_barrier_wait(&ctx.barrier); + + buf.len = sizeof(data); + buf.base = data; + memset(data, '.', sizeof(data)); + + nwritten = 0; + while (nwritten < 10 << 20) { + /* The stream is in blocking mode so uv_try_write() should always succeed + * with the exact number of bytes that we wanted written. + */ + n = uv_try_write((uv_stream_t*) &pipe_handle, &buf, 1); + ASSERT(n == sizeof(data)); + nwritten += n; + } + + uv_close((uv_handle_t*) &pipe_handle, NULL); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + ASSERT(0 == close(fd[1])); /* fd[0] is closed by uv_close(). */ + ASSERT(0 == uv_thread_join(&thread)); + uv_barrier_destroy(&ctx.barrier); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#endif /* !_WIN32 */ diff --git a/deps/uv/test/test-platform-output.c b/deps/uv/test/test-platform-output.c index 931311985bbd..dc6fa32b0d11 100644 --- a/deps/uv/test/test-platform-output.c +++ b/deps/uv/test/test-platform-output.c @@ -27,6 +27,7 @@ TEST_IMPL(platform_output) { char buffer[512]; size_t rss; + size_t size; double uptime; uv_rusage_t rusage; uv_cpu_info_t* cpus; @@ -39,6 +40,11 @@ TEST_IMPL(platform_output) { ASSERT(err == 0); printf("uv_get_process_title: %s\n", buffer); + size = sizeof(buffer); + err = uv_cwd(buffer, &size); + ASSERT(err == 0); + printf("uv_cwd: %s\n", buffer); + err = uv_resident_set_memory(&rss); ASSERT(err == 0); printf("uv_resident_set_memory: %llu\n", (unsigned long long) rss); diff --git a/deps/uv/test/test-poll-close-doesnt-corrupt-stack.c b/deps/uv/test/test-poll-close-doesnt-corrupt-stack.c new file mode 100644 index 000000000000..fc2cc004f16a --- /dev/null +++ b/deps/uv/test/test-poll-close-doesnt-corrupt-stack.c @@ -0,0 +1,114 @@ +/* Copyright Bert Belder, and other 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. + */ + +#ifdef _WIN32 + +#include +#include + +#include "uv.h" +#include "task.h" + +#ifdef _MSC_VER /* msvc */ +# define NO_INLINE __declspec(noinline) +#else /* gcc */ +# define NO_INLINE __attribute__ ((noinline)) +#endif + + +uv_os_sock_t sock; +uv_poll_t handle; + +static int close_cb_called = 0; + + +static void close_cb(uv_handle_t* h) { + close_cb_called++; +} + + +static void poll_cb(uv_poll_t* h, int status, int events) { + ASSERT(0 && "should never get here"); +} + + +static void NO_INLINE close_socket_and_verify_stack() { + const uint32_t MARKER = 0xDEADBEEF; + const int VERIFY_AFTER = 10; /* ms */ + int r; + + volatile uint32_t data[65536]; + size_t i; + + for (i = 0; i < ARRAY_SIZE(data); i++) + data[i] = MARKER; + + r = closesocket(sock); + ASSERT(r == 0); + + uv_sleep(VERIFY_AFTER); + + for (i = 0; i < ARRAY_SIZE(data); i++) + ASSERT(data[i] == MARKER); +} + + +TEST_IMPL(poll_close_doesnt_corrupt_stack) { + struct WSAData wsa_data; + int r; + unsigned long on; + struct sockaddr_in addr; + + r = WSAStartup(MAKEWORD(2, 2), &wsa_data); + ASSERT(r == 0); + + sock = socket(AF_INET, SOCK_STREAM, 0); + ASSERT(sock != INVALID_SOCKET); + on = 1; + r = ioctlsocket(sock, FIONBIO, &on); + ASSERT(r == 0); + + r = uv_ip4_addr("127.0.0.1", TEST_PORT, &addr); + ASSERT(r == 0); + + r = connect(sock, (const struct sockaddr*) &addr, sizeof addr); + ASSERT(r != 0); + ASSERT(WSAGetLastError() == WSAEWOULDBLOCK); + + r = uv_poll_init_socket(uv_default_loop(), &handle, sock); + ASSERT(r == 0); + r = uv_poll_start(&handle, UV_READABLE | UV_WRITABLE, poll_cb); + ASSERT(r == 0); + + uv_close((uv_handle_t*) &handle, close_cb); + + close_socket_and_verify_stack(); + + r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); + ASSERT(r == 0); + + ASSERT(close_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#endif /* _WIN32 */ diff --git a/deps/uv/test/test-poll-closesocket.c b/deps/uv/test/test-poll-closesocket.c index 28114de07a14..4db74a01f639 100644 --- a/deps/uv/test/test-poll-closesocket.c +++ b/deps/uv/test/test-poll-closesocket.c @@ -67,7 +67,8 @@ TEST_IMPL(poll_closesocket) { r = ioctlsocket(sock, FIONBIO, &on); ASSERT(r == 0); - addr = uv_ip4_addr("127.0.0.1", TEST_PORT); + r = uv_ip4_addr("127.0.0.1", TEST_PORT, &addr); + ASSERT(r == 0); r = connect(sock, (const struct sockaddr*) &addr, sizeof addr); ASSERT(r != 0); diff --git a/deps/uv/test/test-poll.c b/deps/uv/test/test-poll.c index 4658762379b5..be8b00c32ca9 100644 --- a/deps/uv/test/test-poll.c +++ b/deps/uv/test/test-poll.c @@ -22,7 +22,6 @@ #include #ifndef _WIN32 -# include # include # include #endif @@ -86,23 +85,7 @@ static int got_eagain(void) { } -static void set_nonblocking(uv_os_sock_t sock) { - int r; -#ifdef _WIN32 - unsigned long on = 1; - r = ioctlsocket(sock, FIONBIO, &on); - ASSERT(r == 0); -#else - int flags = fcntl(sock, F_GETFL, 0); - ASSERT(flags >= 0); - r = fcntl(sock, F_SETFL, flags | O_NONBLOCK); - ASSERT(r >= 0); -#endif -} - - -static uv_os_sock_t create_nonblocking_bound_socket( - struct sockaddr_in bind_addr) { +static uv_os_sock_t create_bound_socket (struct sockaddr_in bind_addr) { uv_os_sock_t sock; int r; @@ -113,8 +96,6 @@ static uv_os_sock_t create_nonblocking_bound_socket( ASSERT(sock >= 0); #endif - set_nonblocking(sock); - #ifndef _WIN32 { /* Allow reuse of the port. */ @@ -479,8 +460,6 @@ static void server_poll_cb(uv_poll_t* handle, int status, int events) { ASSERT(sock >= 0); #endif - set_nonblocking(sock); - connection_context = create_connection_context(sock, 1); connection_context->events = UV_READABLE | UV_WRITABLE; r = uv_poll_start(&connection_context->poll_handle, @@ -502,7 +481,7 @@ static void start_server(void) { int r; ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); - sock = create_nonblocking_bound_socket(addr); + sock = create_bound_socket(addr); context = create_server_context(sock); r = listen(sock, 100); @@ -523,7 +502,7 @@ static void start_client(void) { ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &server_addr)); ASSERT(0 == uv_ip4_addr("0.0.0.0", 0, &addr)); - sock = create_nonblocking_bound_socket(addr); + sock = create_bound_socket(addr); context = create_connection_context(sock, 0); context->events = UV_READABLE | UV_WRITABLE; diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index 11f43bdf1341..9b0030029c18 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -988,7 +988,8 @@ TEST_IMPL(environment_creation) { } } if (prev) { /* verify sort order -- requires Vista */ -#if _WIN32_WINNT >= 0x0600 +#if _WIN32_WINNT >= 0x0600 && \ + (!defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR)) ASSERT(CompareStringOrdinal(prev, -1, str, -1, TRUE) == 1); #endif } @@ -1014,7 +1015,7 @@ TEST_IMPL(spawn_with_an_odd_path) { char *path = getenv("PATH"); ASSERT(path != NULL); snprintf(newpath, 2048, ";.;%s", path); - SetEnvironmentVariable("PATH", path); + SetEnvironmentVariable("PATH", newpath); init_process_options("", exit_cb); options.file = options.args[0] = "program-that-had-better-not-exist"; @@ -1032,6 +1033,7 @@ TEST_IMPL(spawn_with_an_odd_path) { #ifndef _WIN32 TEST_IMPL(spawn_setuid_setgid) { int r; + struct passwd* pw; /* if not root, then this will fail. */ uv_uid_t uid = getuid(); @@ -1043,7 +1045,6 @@ TEST_IMPL(spawn_setuid_setgid) { init_process_options("spawn_helper1", exit_cb); /* become the "nobody" user. */ - struct passwd* pw; pw = getpwnam("nobody"); ASSERT(pw != NULL); options.uid = pw->pw_uid; @@ -1051,6 +1052,9 @@ TEST_IMPL(spawn_setuid_setgid) { options.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID; r = uv_spawn(uv_default_loop(), &process, &options); + if (r == UV_EACCES) + RETURN_SKIP("user 'nobody' cannot access the test runner"); + ASSERT(r == 0); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); @@ -1240,7 +1244,6 @@ TEST_IMPL(closed_fd_events) { /* create a pipe and share it with a child process */ ASSERT(0 == pipe(fd)); - ASSERT(0 == fcntl(fd[0], F_SETFL, O_NONBLOCK)); /* spawn_helper4 blocks indefinitely. */ init_process_options("spawn_helper4", exit_cb); @@ -1297,7 +1300,16 @@ TEST_IMPL(spawn_reads_child_path) { int len; char file[64]; char path[1024]; - char *env[2] = {path, NULL}; + char* env[3]; + + /* Need to carry over the dynamic linker path when the test runner is + * linked against libuv.so, see https://github.com/libuv/libuv/issues/85. + */ +#if defined(__APPLE__) + static const char dyld_path_var[] = "DYLD_LIBRARY_PATH"; +#else + static const char dyld_path_var[] = "LD_LIBRARY_PATH"; +#endif /* Set up the process, but make sure that the file to run is relative and */ /* requires a lookup into PATH */ @@ -1312,6 +1324,16 @@ TEST_IMPL(spawn_reads_child_path) { strcpy(path, "PATH="); strcpy(path + 5, exepath); + env[0] = path; + env[1] = getenv(dyld_path_var); + env[2] = NULL; + + if (env[1] != NULL) { + static char buf[1024 + sizeof(dyld_path_var)]; + snprintf(buf, sizeof(buf), "%s=%s", dyld_path_var, env[1]); + env[1] = buf; + } + options.file = file; options.args[0] = file; options.env = env; diff --git a/deps/uv/test/test-tcp-bind6-error.c b/deps/uv/test/test-tcp-bind6-error.c index 1d65f3de3e6e..b762bcb3d1b8 100644 --- a/deps/uv/test/test-tcp-bind6-error.c +++ b/deps/uv/test/test-tcp-bind6-error.c @@ -39,6 +39,9 @@ TEST_IMPL(tcp_bind6_error_addrinuse) { uv_tcp_t server1, server2; int r; + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + ASSERT(0 == uv_ip6_addr("::", TEST_PORT, &addr)); r = uv_tcp_init(uv_default_loop(), &server1); @@ -73,6 +76,9 @@ TEST_IMPL(tcp_bind6_error_addrnotavail) { uv_tcp_t server; int r; + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + ASSERT(0 == uv_ip6_addr("4:4:4:4:4:4:4:4", TEST_PORT, &addr)); r = uv_tcp_init(uv_default_loop(), &server); @@ -98,6 +104,9 @@ TEST_IMPL(tcp_bind6_error_fault) { uv_tcp_t server; int r; + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + garbage_addr = (struct sockaddr_in6*) &garbage; r = uv_tcp_init(uv_default_loop(), &server); @@ -123,6 +132,9 @@ TEST_IMPL(tcp_bind6_error_inval) { uv_tcp_t server; int r; + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + ASSERT(0 == uv_ip6_addr("::", TEST_PORT, &addr1)); ASSERT(0 == uv_ip6_addr("::", TEST_PORT_2, &addr2)); @@ -149,6 +161,9 @@ TEST_IMPL(tcp_bind6_localhost_ok) { uv_tcp_t server; int r; + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + ASSERT(0 == uv_ip6_addr("::1", TEST_PORT, &addr)); r = uv_tcp_init(uv_default_loop(), &server); diff --git a/deps/uv/test/test-tcp-oob.c b/deps/uv/test/test-tcp-oob.c new file mode 100644 index 000000000000..fc011ee495f1 --- /dev/null +++ b/deps/uv/test/test-tcp-oob.c @@ -0,0 +1,128 @@ +/* Copyright Fedor Indutny. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#if !defined(_WIN32) + +#include "uv.h" +#include "task.h" + +#include +#include +#include + +static uv_tcp_t server_handle; +static uv_tcp_t client_handle; +static uv_tcp_t peer_handle; +static uv_idle_t idle; +static uv_connect_t connect_req; +static int ticks; +static const int kMaxTicks = 10; + +static void alloc_cb(uv_handle_t* handle, + size_t suggested_size, + uv_buf_t* buf) { + static char storage[1024]; + *buf = uv_buf_init(storage, sizeof(storage)); +} + + +static void idle_cb(uv_idle_t* idle) { + if (++ticks < kMaxTicks) + return; + + uv_close((uv_handle_t*) &server_handle, NULL); + uv_close((uv_handle_t*) &client_handle, NULL); + uv_close((uv_handle_t*) &peer_handle, NULL); + uv_close((uv_handle_t*) idle, NULL); +} + + +static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { + ASSERT(nread > 0); + ASSERT(0 == uv_idle_start(&idle, idle_cb)); +} + + +static void connect_cb(uv_connect_t* req, int status) { + ASSERT(req->handle == (uv_stream_t*) &client_handle); + ASSERT(0 == status); +} + + +static void connection_cb(uv_stream_t* handle, int status) { + int r; + uv_os_fd_t fd; + + ASSERT(0 == status); + ASSERT(0 == uv_accept(handle, (uv_stream_t*) &peer_handle)); + ASSERT(0 == uv_read_start((uv_stream_t*) &peer_handle, alloc_cb, read_cb)); + + /* Send some OOB data */ + ASSERT(0 == uv_fileno((uv_handle_t*) &client_handle, &fd)); + + ASSERT(0 == uv_stream_set_blocking((uv_stream_t*) &client_handle, 1)); + + /* The problem triggers only on a second message, it seem that xnu is not + * triggering `kevent()` for the first one + */ + do { + r = send(fd, "hello", 5, MSG_OOB); + } while (r < 0 && errno == EINTR); + ASSERT(5 == r); + + do { + r = send(fd, "hello", 5, MSG_OOB); + } while (r < 0 && errno == EINTR); + ASSERT(5 == r); + + ASSERT(0 == uv_stream_set_blocking((uv_stream_t*) &client_handle, 0)); +} + + +TEST_IMPL(tcp_oob) { + struct sockaddr_in addr; + uv_loop_t* loop; + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + loop = uv_default_loop(); + + ASSERT(0 == uv_tcp_init(loop, &server_handle)); + ASSERT(0 == uv_tcp_init(loop, &client_handle)); + ASSERT(0 == uv_tcp_init(loop, &peer_handle)); + ASSERT(0 == uv_idle_init(loop, &idle)); + ASSERT(0 == uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr, 0)); + ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 1, connection_cb)); + + /* Ensure two separate packets */ + ASSERT(0 == uv_tcp_nodelay(&client_handle, 1)); + + ASSERT(0 == uv_tcp_connect(&connect_req, + &client_handle, + (const struct sockaddr*) &addr, + connect_cb)); + ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); + + ASSERT(ticks == kMaxTicks); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif diff --git a/deps/uv/test/test-tcp-try-write.c b/deps/uv/test/test-tcp-try-write.c index baff6cf36cc0..8a60136b64e9 100644 --- a/deps/uv/test/test-tcp-try-write.c +++ b/deps/uv/test/test-tcp-try-write.c @@ -28,16 +28,6 @@ #define MAX_BYTES 1024 * 1024 -#ifdef _WIN32 - -TEST_IMPL(tcp_try_write) { - - MAKE_VALGRIND_HAPPY(); - return 0; -} - -#else /* !_WIN32 */ - static uv_tcp_t server; static uv_tcp_t client; static uv_tcp_t incoming; @@ -138,5 +128,3 @@ TEST_IMPL(tcp_try_write) { MAKE_VALGRIND_HAPPY(); return 0; } - -#endif /* !_WIN32 */ diff --git a/deps/uv/test/test-udp-ipv6.c b/deps/uv/test/test-udp-ipv6.c index 0ca9f4dcff6a..1d5720ce7316 100644 --- a/deps/uv/test/test-udp-ipv6.c +++ b/deps/uv/test/test-udp-ipv6.c @@ -147,23 +147,22 @@ static void do_test(uv_udp_recv_cb recv_cb, int bind_flags) { TEST_IMPL(udp_dual_stack) { -#if defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ - defined(__NetBSD__) - RETURN_SKIP("dual stack not enabled by default in this OS."); -#else + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + do_test(ipv6_recv_ok, 0); ASSERT(recv_cb_called == 1); ASSERT(send_cb_called == 1); return 0; -#endif } TEST_IMPL(udp_ipv6_only) { + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + do_test(ipv6_recv_fail, UV_UDP_IPV6ONLY); ASSERT(recv_cb_called == 0); diff --git a/deps/uv/test/test-udp-multicast-interface6.c b/deps/uv/test/test-udp-multicast-interface6.c index e54e738b0be3..d3881e83bb15 100644 --- a/deps/uv/test/test-udp-multicast-interface6.c +++ b/deps/uv/test/test-udp-multicast-interface6.c @@ -60,6 +60,9 @@ TEST_IMPL(udp_multicast_interface6) { struct sockaddr_in6 addr; struct sockaddr_in6 baddr; + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + ASSERT(0 == uv_ip6_addr("::1", TEST_PORT, &addr)); r = uv_udp_init(uv_default_loop(), &server); diff --git a/deps/uv/test/test-udp-multicast-join6.c b/deps/uv/test/test-udp-multicast-join6.c index babf61e2bf7d..9ba201ab9eba 100644 --- a/deps/uv/test/test-udp-multicast-join6.c +++ b/deps/uv/test/test-udp-multicast-join6.c @@ -103,6 +103,9 @@ TEST_IMPL(udp_multicast_join6) { uv_buf_t buf; struct sockaddr_in6 addr; + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + ASSERT(0 == uv_ip6_addr("::1", TEST_PORT, &addr)); r = uv_udp_init(uv_default_loop(), &server); diff --git a/deps/uv/test/test-udp-options.c b/deps/uv/test/test-udp-options.c index 19c45c2e3197..0da1786f506f 100644 --- a/deps/uv/test/test-udp-options.c +++ b/deps/uv/test/test-udp-options.c @@ -27,15 +27,12 @@ #include -TEST_IMPL(udp_options) { +static int udp_options_test(const struct sockaddr* addr) { static int invalid_ttls[] = { -1, 0, 256 }; - struct sockaddr_in addr; uv_loop_t* loop; uv_udp_t h; int i, r; - ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); - loop = uv_default_loop(); r = uv_udp_init(loop, &h); @@ -43,7 +40,7 @@ TEST_IMPL(udp_options) { uv_unref((uv_handle_t*)&h); /* don't keep the loop alive */ - r = uv_udp_bind(&h, (const struct sockaddr*) &addr, 0); + r = uv_udp_bind(&h, addr, 0); ASSERT(r == 0); r = uv_udp_set_broadcast(&h, 1); @@ -88,6 +85,25 @@ TEST_IMPL(udp_options) { } +TEST_IMPL(udp_options) { + struct sockaddr_in addr; + + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + return udp_options_test((const struct sockaddr*) &addr); +} + + +TEST_IMPL(udp_options6) { + struct sockaddr_in6 addr; + + if (!can_ipv6()) + RETURN_SKIP("IPv6 not supported"); + + ASSERT(0 == uv_ip6_addr("::", TEST_PORT, &addr)); + return udp_options_test((const struct sockaddr*) &addr); +} + + TEST_IMPL(udp_no_autobind) { uv_loop_t* loop; uv_udp_t h; diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 880c641f18e0..203ae1169ac3 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -17,28 +17,8 @@ }], ], 'xcode_settings': { - 'conditions': [ - [ 'clang==1', { - 'WARNING_CFLAGS': [ - '-Wall', - '-Wextra', - '-Wno-unused-parameter', - '-Wno-dollar-in-identifier-extension' - ]}, { - 'WARNING_CFLAGS': [ - '-Wall', - '-Wextra', - '-Wno-unused-parameter' - ]} - ] - ], - 'OTHER_LDFLAGS': [ - ], - 'OTHER_CFLAGS': [ - '-g', - '--std=gnu89', - '-pedantic' - ], + 'WARNING_CFLAGS': [ '-Wall', '-Wextra', '-Wno-unused-parameter' ], + 'OTHER_CFLAGS': [ '-g', '--std=gnu89', '-pedantic' ], } }, @@ -221,6 +201,7 @@ 'cflags': [ '-Wstrict-aliasing' ], }], [ 'OS=="linux"', { + 'defines': [ '_GNU_SOURCE' ], 'sources': [ 'src/unix/linux-core.c', 'src/unix/linux-inotify.c', @@ -341,6 +322,7 @@ 'test/test-loop-close.c', 'test/test-loop-stop.c', 'test/test-loop-time.c', + 'test/test-loop-configure.c', 'test/test-walk-handles.c', 'test/test-watcher-cross-stop.c', 'test/test-multiple-listen.c', @@ -353,9 +335,11 @@ 'test/test-pipe-sendmsg.c', 'test/test-pipe-server-close.c', 'test/test-pipe-close-stdout-read-stdin.c', + 'test/test-pipe-set-non-blocking.c', 'test/test-platform-output.c', 'test/test-poll.c', 'test/test-poll-close.c', + 'test/test-poll-close-doesnt-corrupt-stack.c', 'test/test-poll-closesocket.c', 'test/test-process-title.c', 'test/test-ref.c', @@ -388,6 +372,7 @@ 'test/test-tcp-writealot.c', 'test/test-tcp-try-write.c', 'test/test-tcp-unexpected-read.c', + 'test/test-tcp-oob.c', 'test/test-tcp-read-stop.c', 'test/test-tcp-write-queue-order.c', 'test/test-threadpool.c', diff --git a/lib/child_process.js b/lib/child_process.js index b4a8894734b8..8b29132cb4ef 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -586,6 +586,13 @@ exports._forkChild = function(fd) { // set process.send() var p = createPipe(true); p.open(fd); + + // p.open() puts the file descriptor in non-blocking mode + // but it must be synchronous for backwards compatibility. + var err = p.setBlocking(true); + if (err) + throw errnoException(err, 'setBlocking'); + p.unref(); setupChannel(process, p); diff --git a/lib/net.js b/lib/net.js index 6d12a70aee02..70baab3bd378 100644 --- a/lib/net.js +++ b/lib/net.js @@ -155,9 +155,9 @@ function Socket(options) { } else if (!util.isUndefined(options.fd)) { this._handle = createHandle(options.fd); this._handle.open(options.fd); - if ((options.fd == 1 || options.fd == 2) && - (this._handle instanceof Pipe) && - process.platform === 'win32') { + // this._handle.open() puts the file descriptor in non-blocking + // mode but it must be synchronous for backwards compatibility. + if ((options.fd == 1 || options.fd == 2) && this._handle instanceof Pipe) { // Make stdout and stderr blocking on Windows var err = this._handle.setBlocking(true); if (err) diff --git a/test/simple/test-child-process-sync-process-send.js b/test/simple/test-child-process-sync-process-send.js new file mode 100644 index 000000000000..241364f0841e --- /dev/null +++ b/test/simple/test-child-process-sync-process-send.js @@ -0,0 +1,44 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +var common = require('../common'); +var assert = require('assert'); +var fork = require('child_process').fork; +var N = 4 << 20; // 4 MB + +for (var big = '*'; big.length < N; big += big); + +if (process.argv[2] === 'child') { + process.send(big); + process.exit(42); +} + +var proc = fork(__filename, ['child']); + +proc.on('message', common.mustCall(function(msg) { + assert.equal(typeof msg, 'string'); + assert.equal(msg.length, N); + assert.equal(msg, big); +})); + +proc.on('exit', common.mustCall(function(exitCode) { + assert.equal(exitCode, 42); +})); diff --git a/test/simple/test-net-sync-stdio.js b/test/simple/test-net-sync-stdio.js new file mode 100644 index 000000000000..4599c81a06cf --- /dev/null +++ b/test/simple/test-net-sync-stdio.js @@ -0,0 +1,44 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +var common = require('../common'); +var assert = require('assert'); +var spawn = require('child_process').spawn; +var N = 4 << 20; // 4 MB + +for (var big = '*'; big.length < N; big += big); + +if (process.argv[2] === 'child') { + process.stdout.write(big); + process.exit(42); +} + +var stdio = ['inherit', 'pipe', 'inherit']; +var proc = spawn(process.execPath, [__filename, 'child'], { stdio: stdio }); + +var chunks = []; +proc.stdout.setEncoding('utf8'); +proc.stdout.on('data', chunks.push.bind(chunks)); + +proc.on('exit', common.mustCall(function(exitCode) { + assert.equal(exitCode, 42); + assert.equal(chunks.join(''), big); +}));