Makefile
Makefile.in
-# Generated by dtrace(1) when doing an in-tree build.
-/include/uv-dtrace.h
-
# Generated by gyp for android
*.target.mk
/test/run-benchmarks.dSYM
*.sln
+*.sln.cache
+*.ncb
*.vcproj
+*.vcproj*.user
*.vcxproj
*.vcxproj.filters
*.vcxproj.user
Leonard Hecker <leonard.hecker91@gmail.com> <leonard@hecker.io>
Maciej Małecki <maciej.malecki@notimplemented.org> <me@mmalecki.com>
Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
-Rasmus Christian Pedersen <ruysch@outlook.com>
-Rasmus Christian Pedersen <ruysch@outlook.com>
-Rasmus Christian Pedersen <ruysch@outlook.com>
-Rasmus Christian Pedersen <ruysch@outlook.com>
+Rasmus Christian Pedersen <zerhacken@yahoo.com>
Rasmus Christian Pedersen <zerhacken@yahoo.com> <ruysch@outlook.com>
-Rasmus Pedersen <ruysch@outlook.com> <zerhacken@yahoo.com>
Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
Ryan Dahl <ryan@joyent.com> <ry@tinyclouds.org>
Ryan Emery <seebees@gmail.com>
Helge Deller <deller@gmx.de>
Joey Geralnik <jgeralnik@gmail.com>
Tim Caswell <tim@creationix.com>
+Logan Rosen <loganrosen@gmail.com>
+Kenneth Perry <thothonegan@gmail.com>
+John Marino <marino@FreeBSD.org>
+Alexey Melnichuk <mimir@newmail.ru>
+2015.01.06, Version 1.2.0 (Stable)
+
+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:
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
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 \
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 \
test/test-pipe-close-stdout-read-stdin.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 \
if DRAGONFLY
include_HEADERS += include/uv-bsd.h
-libuv_la_SOURCES += src/unix/kqueue.c src/unix/freebsd.c
endif
if FREEBSD
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])" \
'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': {
'cflags': [ '-pthread' ],
'ldflags': [ '-pthread' ],
}],
- [ 'visibility=="hidden" and (clang==1 or gcc_version >= 40)', {
+ [ 'visibility=="hidden"', {
'cflags': [ '-fvisibility=hidden' ],
}],
],
# 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.2.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])
AC_ENABLE_STATIC
AC_PROG_CC
AM_PROG_CC_C_O
-CC_CHECK_CFLAGS_APPEND([-Wno-dollar-in-identifier-extension])
+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
-@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 ^<target^>` where ^<target^> 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\r
+\r
+REM Command file for Sphinx documentation\r
+\r
+if "%SPHINXBUILD%" == "" (\r
+ set SPHINXBUILD=sphinx-build\r
+)\r
+set BUILDDIR=build\r
+set SRCDIR=src\r
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% %SRCDIR%\r
+set I18NSPHINXOPTS=%SPHINXOPTS% %SRCDIR%\r
+if NOT "%PAPER%" == "" (\r
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%\r
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%\r
+)\r
+\r
+if "%1" == "" goto help\r
+\r
+if "%1" == "help" (\r
+ :help\r
+ echo.Please use `make ^<target^>` where ^<target^> is one of\r
+ echo. html to make standalone HTML files\r
+ echo. dirhtml to make HTML files named index.html in directories\r
+ echo. singlehtml to make a single large HTML file\r
+ echo. pickle to make pickle files\r
+ echo. json to make JSON files\r
+ echo. htmlhelp to make HTML files and a HTML help project\r
+ echo. qthelp to make HTML files and a qthelp project\r
+ echo. devhelp to make HTML files and a Devhelp project\r
+ echo. epub to make an epub\r
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter\r
+ echo. text to make text files\r
+ echo. man to make manual pages\r
+ echo. texinfo to make Texinfo files\r
+ echo. gettext to make PO message catalogs\r
+ echo. changes to make an overview over all changed/added/deprecated items\r
+ echo. xml to make Docutils-native XML files\r
+ echo. pseudoxml to make pseudoxml-XML files for display purposes\r
+ echo. linkcheck to check all external links for integrity\r
+ echo. doctest to run all doctests embedded in the documentation if enabled\r
+ goto end\r
+)\r
+\r
+if "%1" == "clean" (\r
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i\r
+ del /q /s %BUILDDIR%\*\r
+ goto end\r
+)\r
+\r
+\r
+%SPHINXBUILD% 2> nul\r
+if errorlevel 9009 (\r
+ echo.\r
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx\r
+ echo.installed, then set the SPHINXBUILD environment variable to point\r
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you\r
+ echo.may add the Sphinx directory to PATH.\r
+ echo.\r
+ echo.If you don't have Sphinx installed, grab it from\r
+ echo.http://sphinx-doc.org/\r
+ exit /b 1\r
+)\r
+\r
+if "%1" == "html" (\r
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.\r
+ goto end\r
+)\r
+\r
+if "%1" == "dirhtml" (\r
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.\r
+ goto end\r
+)\r
+\r
+if "%1" == "singlehtml" (\r
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.\r
+ goto end\r
+)\r
+\r
+if "%1" == "pickle" (\r
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished; now you can process the pickle files.\r
+ goto end\r
+)\r
+\r
+if "%1" == "json" (\r
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished; now you can process the JSON files.\r
+ goto end\r
+)\r
+\r
+if "%1" == "htmlhelp" (\r
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished; now you can run HTML Help Workshop with the ^\r
+.hhp project file in %BUILDDIR%/htmlhelp.\r
+ goto end\r
+)\r
+\r
+if "%1" == "qthelp" (\r
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^\r
+.qhcp project file in %BUILDDIR%/qthelp, like this:\r
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\libuv.qhcp\r
+ echo.To view the help file:\r
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\libuv.ghc\r
+ goto end\r
+)\r
+\r
+if "%1" == "devhelp" (\r
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished.\r
+ goto end\r
+)\r
+\r
+if "%1" == "epub" (\r
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.\r
+ goto end\r
+)\r
+\r
+if "%1" == "latex" (\r
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.\r
+ goto end\r
+)\r
+\r
+if "%1" == "latexpdf" (\r
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r
+ cd %BUILDDIR%/latex\r
+ make all-pdf\r
+ cd %BUILDDIR%/..\r
+ echo.\r
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.\r
+ goto end\r
+)\r
+\r
+if "%1" == "latexpdfja" (\r
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r
+ cd %BUILDDIR%/latex\r
+ make all-pdf-ja\r
+ cd %BUILDDIR%/..\r
+ echo.\r
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.\r
+ goto end\r
+)\r
+\r
+if "%1" == "text" (\r
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The text files are in %BUILDDIR%/text.\r
+ goto end\r
+)\r
+\r
+if "%1" == "man" (\r
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.\r
+ goto end\r
+)\r
+\r
+if "%1" == "texinfo" (\r
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.\r
+ goto end\r
+)\r
+\r
+if "%1" == "gettext" (\r
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.\r
+ goto end\r
+)\r
+\r
+if "%1" == "changes" (\r
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.The overview file is in %BUILDDIR%/changes.\r
+ goto end\r
+)\r
+\r
+if "%1" == "linkcheck" (\r
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Link check complete; look for any errors in the above output ^\r
+or in %BUILDDIR%/linkcheck/output.txt.\r
+ goto end\r
+)\r
+\r
+if "%1" == "doctest" (\r
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Testing of doctests in the sources finished, look at the ^\r
+results in %BUILDDIR%/doctest/output.txt.\r
+ goto end\r
+)\r
+\r
+if "%1" == "xml" (\r
+ %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The XML files are in %BUILDDIR%/xml.\r
+ goto end\r
+)\r
+\r
+if "%1" == "pseudoxml" (\r
+ %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.\r
+ goto end\r
+)\r
+\r
+:end\r
.. 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.
.. _misc:
Miscellaneous utilities
-======================
+=======================
This section contains miscellaneous functions that don't really belong in any
other section.
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.
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
^^^^^^^^^^^^^^
.. note::
TTY streams which are not readable have blocking writes.
-.. c:function:: int uv_tty_set_mode(uv_tty_t*, int mode)
+.. c:function:: int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode)
+
+ .. versionchanged:: 1.2.0: the mode is specified as a :c:type:`uv_tty_mode_t`
+ value.
- 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)
#!/usr/bin/env python
-import glob
-import platform
import os
-import subprocess
+import platform
import sys
try:
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:
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())
*/
#define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 0
-#define UV_VERSION_PATCH 2
+#define UV_VERSION_MINOR 2
+#define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""
/* 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; \
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<uv_tty_mode_t>(mode));
+}
+
+extern "C" {
+#endif
+
UV_EXTERN uv_handle_type uv_guess_handle(uv_file file);
/*
+++ /dev/null
-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 ---------------------------------------------------------------------------
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());
#include <sys/ioctl.h>
#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));
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)
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);
}
r = uv__loop_alive(loop);
-
- if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT))
+ if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
break;
}
return -errno;
*size = strlen(buffer);
+ if (*size > 1 && buffer[*size - 1] == '/') {
+ buffer[*size-1] = '\0';
+ (*size)--;
+ }
+
return 0;
}
}
-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);
w = QUEUE_DATA(q, uv__io_t, pending_queue);
w->cb(loop, w, UV__POLLOUT);
}
+
+ return 1;
}
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;
}
int mib[4];
size_t cb;
- if (buffer == NULL || size == NULL)
+ if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
#ifdef __DragonFly__
#include <string.h>
#include <sys/types.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/uio.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
defined(__OpenBSD__) || \
defined(__NetBSD__)
# define HAVE_PREADV 1
-#elif defined(__linux__)
-# include <linux/version.h>
-# 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 <sys/sendfile.h>
-#elif defined(__APPLE__) || defined(__FreeBSD__)
-# include <sys/socket.h>
-#endif
-
-#if HAVE_PREADV || defined(__APPLE__)
-# include <sys/uio.h>
#endif
#define INIT(type) \
static ssize_t uv__fs_read(uv_fs_t* req) {
+#if defined(__linux__)
+ static int no_preadv;
+#endif
ssize_t result;
#if defined(_AIX)
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;
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
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;
# include <CoreServices/CoreServices.h>
#endif
-#define STATIC_ASSERT(expr) \
- void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)])
-
#define ACCESS_ONCE(type, var) \
(*(volatile type*) &(var))
#include <sys/prctl.h>
#include <sys/sysinfo.h>
#include <unistd.h>
-#include <signal.h>
#include <fcntl.h>
#include <time.h>
struct uv__epoll_event e;
QUEUE* q;
uv__io_t* w;
- sigset_t* pset;
- sigset_t set;
+ uint64_t sigmask;
uint64_t base;
uint64_t diff;
int nevents;
w->events = w->pevents;
}
- pset = NULL;
- if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
- pset = &set;
- sigemptyset(pset);
- sigaddset(pset, SIGPROF);
- }
+ sigmask = 0;
+ if (loop->flags & UV_LOOP_BLOCK_SIGPROF)
+ sigmask |= 1 << (SIGPROF - 1);
assert(timeout >= -1);
base = loop->time;
count = 48; /* Benchmarks suggest this gives the best throughput. */
for (;;) {
- if (no_epoll_wait || pset != NULL) {
+ if (no_epoll_wait || sigmask) {
nfds = uv__epoll_pwait(loop->backend_fd,
events,
ARRAY_SIZE(events),
timeout,
- pset);
+ sigmask);
} else {
nfds = uv__epoll_wait(loop->backend_fd,
events,
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;
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
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);
size_t cb;
pid_t mypid;
- if (buffer == NULL || size == NULL)
+ if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
mypid = getpid();
pid_t mypid;
int err;
- if (buffer == NULL || size == NULL)
+ if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
mypid = getpid();
}
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:
/* 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);
/* Convert ENOENT to EACCES for compatibility with Windows. */
if (err == -ENOENT)
err = -EACCES;
- goto out;
+ goto err_bind;
}
/* Success. */
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;
}
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;
uv__nonblock(fd, 1);
uv__stream_open((uv_stream_t*) tty, fd, flags);
- tty->mode = 0;
+ tty->mode = UV_TTY_MODE_NORMAL;
return 0;
}
-int uv_tty_set_mode(uv_tty_t* tty, int mode) {
- struct termios raw;
+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 (mode && tty->mode == 0) { /* on */
+ if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) {
if (tcgetattr(fd, &tty->orig_termios))
return -errno;
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:
+ cfmakeraw(&tmp);
+ break;
}
+ /* Apply changes after draining */
+ if (tcsetattr(fd, TCSADRAIN, &tmp))
+ return -errno;
+
+ tty->mode = mode;
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) {
+ int r;
#if defined(__sun) || defined(_AIX)
char arg = val;
#else
if (val < 0 || val > 255)
return -EINVAL;
- if (setsockopt(handle->io_watcher.fd, IPPROTO_IP, option, &arg, sizeof(arg)))
+ if (handle->flags & UV_HANDLE_IPV6)
+ r = setsockopt(handle->io_watcher.fd,
+ IPPROTO_IPV6,
+ option6,
+ &arg,
+ sizeof(arg));
+ else
+ r = setsockopt(handle->io_watcher.fd,
+ IPPROTO_IP,
+ option4,
+ &arg,
+ sizeof(arg));
+
+ if (r)
return -errno;
return 0;
if (ttl < 1 || ttl > 255)
return -EINVAL;
- if (setsockopt(handle->io_watcher.fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)))
- return -errno;
-
- return 0;
+ 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);
+ 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);
+ 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) {
#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,
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)
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);
}
r = uv__loop_alive(loop);
- if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT))
+ if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
break;
}
}
+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;
#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 { \
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);
}
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;
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;
}
+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;
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;
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) {
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;
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 {
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;
}
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);
}
} 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;
assert(0);
}
}
+
+ return 1;
}
#endif /* UV_WIN_REQ_INL_H_ */
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);
};
-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;
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;
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());
}
-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;
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)) {
sNtQueryInformationFile pNtQueryInformationFile;
sNtSetInformationFile pNtSetInformationFile;
sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
+sNtQueryDirectoryFile pNtQueryDirectoryFile;
sNtQuerySystemInformation pNtQuerySystemInformation;
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");
# 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;
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;
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
# 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,
extern sNtQueryInformationFile pNtQueryInformationFile;
extern sNtSetInformationFile pNtSetInformationFile;
extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
+extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
extern sNtQuerySystemInformation pNtQuerySystemInformation;
}
-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;
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 */
const char* arg;
char* args[16];
int n;
+ pid_t pid;
stdout_file = tmpfile();
if (!stdout_file) {
p->terminated = 0;
p->status = 0;
- pid_t pid = fork();
+ pid = fork();
if (pid < 0) {
perror("fork");
/* 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;
* 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;
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);
/* 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... */
# include <sys/resource.h> /* 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
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_ */
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;
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);
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);
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;
}
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)
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)
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)
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)
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)
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)
--- /dev/null
+/* Copyright (c) 2014, Ben Noordhuis <info@bnoordhuis.nl>
+ *
+ * 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;
+}
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);
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);
int pid;
int fd[2];
int status;
+ uv_pipe_t stdin_pipe;
r = pipe(fd);
ASSERT(r == 0);
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);
TEST_IMPL(platform_output) {
char buffer[512];
size_t rss;
+ size_t size;
double uptime;
uv_rusage_t rusage;
uv_cpu_info_t* cpus;
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);
--- /dev/null
+/* 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 <errno.h>
+#include <stdio.h>
+
+#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 */
#ifndef _WIN32
TEST_IMPL(spawn_setuid_setgid) {
int r;
+ struct passwd* pw;
/* if not root, then this will fail. */
uv_uid_t uid = getuid();
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;
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);
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 */
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;
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);
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);
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);
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));
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);
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);
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);
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);
#include <string.h>
-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);
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);
}
+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;
}],
],
'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' ],
}
},
'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',
'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',