Commit 194c3c77 authored by Jason Madden's avatar Jason Madden

Update to libuv 1.34

Fixes #1506.

We don't use the uv_random interfaces so exclude those files.

we don't support haiku so exclude that file.

The binary mode patch for #1282 is no longer needed after https://github.com/libuv/libuv/pull/2324
parent 2ba4f655
......@@ -81,7 +81,9 @@ Updating libuv
rm -rf libuv/test/*.[ch] libuv/test/test.gyp # must leave the fixtures/ dir
rm -rf libuv/tools
rm -f libuv/android-configure*
git apply libuv-win-binary.patch
rm -f libuv/src/unix/haiku.c # We don't support Haiku
rm -f libuv/src/unix/random-*.c # We don't use the uv_random interfaces
rm -f libuv/src/random.c
At this point there might be new files in libuv that need added to git
and the build process. Evaluate those and add them to git and to
......
diff --git a/deps/libuv/src/win/fs.c b/deps/libuv/src/win/fs.c
index 812c1a6d..f4d66628 100644
--- a/deps/libuv/src/win/fs.c
+++ b/deps/libuv/src/win/fs.c
@@ -135,5 +135,12 @@ const WCHAR UNC_PATH_PREFIX_LEN = 8;
static int uv__file_symlink_usermode_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
void uv_fs_init(void) {
- _fmode = _O_BINARY;
+/* gevent: This breaks `open()` on CPython 2 by changing
+ * the default mode for file operations. Python 3 and PyPy
+ * ar unaffected. It was removed for the (unreleased) libuv 2.
+ * See https://github.com/gevent/gevent/issues/1282
+ */
+/*
+ * _fmode = _O_BINARY;
+ */
}
test/fixtures/lorem_ipsum.txt text eol=lf
......@@ -51,6 +51,7 @@ Makefile.in
/test/run-benchmarks
/test/run-benchmarks.exe
/test/run-benchmarks.dSYM
test_file_*
*.sln
*.sln.cache
......
......@@ -38,6 +38,7 @@ Sam Roberts <vieuxtech@gmail.com> <sam@strongloop.com>
San-Tai Hsu <vanilla@fatpipi.com>
Santiago Gimeno <santiago.gimeno@quantion.es> <santiago.gimeno@gmail.com>
Saúl Ibarra Corretgé <saghul@gmail.com>
Saúl Ibarra Corretgé <saghul@gmail.com> <s@saghul.net>
Shigeki Ohtsu <ohtsu@iij.ad.jp> <ohtsu@ohtsu.org>
Timothy J. Fontaine <tjfontaine@gmail.com>
Yasuhiro Matsumoto <mattn.jp@gmail.com>
......@@ -46,3 +47,4 @@ Yuki Okumura <mjt@cltn.org>
jBarz <jBarz@users.noreply.github.com> <jbarboza@ca.ibm.com>
jBarz <jBarz@users.noreply.github.com> <jbarz@users.noreply.github.com>
ptlomholt <pt@lomholt.com>
zlargon <zlargon1988@gmail.com>
......@@ -371,3 +371,44 @@ yeyuanfeng <yeyuanfeng@bytedance.com>
erw7 <erw7.github@gmail.com>
Thomas Karl Pietrowski <thopiekar@gmail.com>
evgley <evgley@gmail.com>
Andreas Rohner <andreas.rohner@gmx.net>
Rich Trott <rtrott@gmail.com>
Milad Farazmand <miladfar@ca.ibm.com>
zlargon <zlargon1988@gmail.com>
Yury Selivanov <yury@magic.io>
Oscar Waddell <owaddell@beckman.com>
FX Coudert <fxcoudert@gmail.com>
George Zhao <zhaozg@gmail.com>
Kyle Edwards <kyle.edwards@kitware.com>
ken-cunningham-webuse <ken.cunningham.webuse@gmail.com>
Kelvin Jin <kelvinjin@google.com>
Leorize <leorize+oss@disroot.org>
Vlad A <vladmore@gmail.com>
Niels Lohmann <mail@nlohmann.me>
Jenil Christo <jenilchristo5@gmail.com>
Evgeny Ermakov <evgeny.v.ermakov@gmail.com>
gengjiawen <technicalcute@gmail.com>
Leo Chung <gewalalb@gmail.com>
Javier Blazquez <jblazquez@riotgames.com>
Mustafa M <mus-m@outlook.com>
Zach Bjornson <zbbjornson@gmail.com>
Nan Xiao <nan@chinadtrace.org>
Ben Davies <kaiepi@outlook.com>
Nhan Khong <knhana7@gmail.com>
Crunkle <justcrunkle@hotmail.co.uk>
Tomas Krizek <tomas.krizek@nic.cz>
Konstantin Podsvirov <konstantin@podsvirov.pro>
seny <arseny.vakhrushev@gmail.com>
Vladimir Karnushin <v.karnushin@mail.ru>
MaYuming <maym@appexnetworks.com>
Eneas U de Queiroz <cotequeiroz@gmail.com>
Daniel Hahler <git@thequod.de>
Yang Yu <yang.yu@disigma.org>
David Carlier <devnexen@gmail.com>
Calvin Hill <calvin@hakobaito.co.uk>
Isabella Muerte <63051+slurps-mad-rips@users.noreply.github.com>
Ouyang Yadong <oyydoibh@gmail.com>
ZYSzys <zyszys98@gmail.com>
Carl Lei <xecycle@gmail.com>
Stefan Bender <stefan.bender@ntnu.no>
nia <nia@NetBSD.org>
# TODO: determine CMAKE_SYSTEM_NAME on OS/390. Currently assumes "OS/390".
cmake_minimum_required(VERSION 3.0)
project(libuv)
enable_testing()
cmake_minimum_required(VERSION 3.4)
project(libuv LANGUAGES C)
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
include(GNUInstallDirs)
include(CTest)
cmake_dependent_option(LIBUV_BUILD_TESTS
"Build the unit tests when BUILD_TESTING is enabled and we are the root project" ON
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
if(MSVC)
list(APPEND uv_cflags /W4)
......@@ -15,6 +23,7 @@ set(uv_sources
src/fs-poll.c
src/idna.c
src/inet.c
src/random.c
src/strscpy.c
src/threadpool.c
src/timer.c
......@@ -53,6 +62,9 @@ set(uv_test_sources
test/test-fs-event.c
test/test-fs-poll.c
test/test-fs.c
test/test-fs-readdir.c
test/test-fs-fd-hash.c
test/test-fs-open-flags.c
test/test-get-currentexe.c
test/test-get-loadavg.c
test/test-get-memory.c
......@@ -62,6 +74,7 @@ set(uv_test_sources
test/test-getnameinfo.c
test/test-getsockname.c
test/test-getters-setters.c
test/test-gettimeofday.c
test/test-handle-fileno.c
test/test-homedir.c
test/test-hrtime.c
......@@ -69,7 +82,6 @@ set(uv_test_sources
test/test-idna.c
test/test-ip4-addr.c
test/test-ip6-addr.c
test/test-ip6-addr.c
test/test-ipc-heavy-traffic-deadlock-bug.c
test/test-ipc-send-recv.c
test/test-ipc.c
......@@ -105,6 +117,7 @@ set(uv_test_sources
test/test-process-title-threadsafe.c
test/test-process-title.c
test/test-queue-foreach-delete.c
test/test-random.c
test/test-ref.c
test/test-run-nowait.c
test/test-run-once.c
......@@ -113,6 +126,7 @@ set(uv_test_sources
test/test-shutdown-eof.c
test/test-shutdown-twice.c
test/test-signal-multiple-loops.c
test/test-signal-pending-on-close.c
test/test-signal.c
test/test-socket-buffer-size.c
test/test-spawn.c
......@@ -124,6 +138,7 @@ set(uv_test_sources
test/test-tcp-close-accept.c
test/test-tcp-close-while-connecting.c
test/test-tcp-close.c
test/test-tcp-close-reset.c
test/test-tcp-connect-error-after-write.c
test/test-tcp-connect-error.c
test/test-tcp-connect-timeout.c
......@@ -135,6 +150,7 @@ set(uv_test_sources
test/test-tcp-read-stop.c
test/test-tcp-shutdown-after-write.c
test/test-tcp-try-write.c
test/test-tcp-try-write-error.c
test/test-tcp-unexpected-read.c
test/test-tcp-write-after-connect.c
test/test-tcp-write-fail.c
......@@ -230,6 +246,7 @@ else()
src/unix/pipe.c
src/unix/poll.c
src/unix/process.c
src/unix/random-devurandom.c
src/unix/signal.c
src/unix/stream.c
src/unix/tcp.c
......@@ -258,11 +275,12 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android")
src/unix/linux-syscalls.c
src/unix/procfs-exepath.c
src/unix/pthread-fixes.c
src/unix/sysinfo-loadavg.c
src/unix/sysinfo-memory.c)
src/unix/random-getrandom.c
src/unix/random-sysctl-linux.c
src/unix/sysinfo-loadavg.c)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|Linux|OS/390")
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux|OS/390")
list(APPEND uv_sources src/unix/proctitle.c)
endif()
......@@ -275,11 +293,19 @@ if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD")
list(APPEND uv_libraries kvm)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Darwin|DragonFly|FreeBSD|NetBSD|OpenBSD")
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD")
list(APPEND uv_sources src/unix/bsd-ifaddrs.c src/unix/kqueue.c)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
list(APPEND uv_sources src/unix/random-getrandom.c)
endif()
if(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
list(APPEND uv_sources src/unix/random-getentropy.c)
endif()
if(APPLE)
list(APPEND uv_defines _DARWIN_UNLIMITED_SELECT=1 _DARWIN_USE_64_BIT_INODE=1)
list(APPEND uv_sources
src/unix/darwin-proctitle.c
......@@ -295,8 +321,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
src/unix/linux-inotify.c
src/unix/linux-syscalls.c
src/unix/procfs-exepath.c
src/unix/sysinfo-loadavg.c
src/unix/sysinfo-memory.c)
src/unix/random-getrandom.c
src/unix/random-sysctl-linux.c
src/unix/sysinfo-loadavg.c)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
......@@ -315,6 +342,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS/390")
list(APPEND uv_defines _OPEN_MSGQ_EXT)
list(APPEND uv_defines _OPEN_SYS_FILE_EXT)
list(APPEND uv_defines _OPEN_SYS_IF_EXT)
list(APPEND uv_defines _OPEN_SYS_SOCK_EXT3)
list(APPEND uv_defines _OPEN_SYS_SOCK_IPV6)
list(APPEND uv_defines _UNIX03_SOURCE)
list(APPEND uv_defines _UNIX03_THREADS)
......@@ -333,29 +361,29 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
list(APPEND uv_sources src/unix/no-proctitle.c src/unix/sunos.c)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "Darwin|DragonFly|FreeBSD|Linux|NetBSD|OpenBSD")
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|Linux|NetBSD|OpenBSD")
list(APPEND uv_test_libraries util)
endif()
add_library(uv SHARED ${uv_sources})
target_compile_definitions(uv PRIVATE ${uv_defines} BUILDING_UV_SHARED=1)
target_compile_definitions(uv
INTERFACE USING_UV_SHARED=1
PRIVATE ${uv_defines} BUILDING_UV_SHARED=1)
target_compile_options(uv PRIVATE ${uv_cflags})
target_include_directories(uv PRIVATE include src)
target_include_directories(uv PUBLIC include PRIVATE src)
target_link_libraries(uv ${uv_libraries})
add_library(uv_a STATIC ${uv_sources})
target_compile_definitions(uv_a PRIVATE ${uv_defines})
target_compile_options(uv_a PRIVATE ${uv_cflags})
target_include_directories(uv_a PRIVATE include src)
target_include_directories(uv_a PUBLIC include PRIVATE src)
target_link_libraries(uv_a ${uv_libraries})
if(BUILD_TESTING)
include(CTest)
if(LIBUV_BUILD_TESTS)
add_executable(uv_run_tests ${uv_test_sources})
target_compile_definitions(uv_run_tests
PRIVATE ${uv_defines} USING_UV_SHARED=1)
target_compile_options(uv_run_tests PRIVATE ${uv_cflags})
target_include_directories(uv_run_tests PRIVATE include)
target_link_libraries(uv_run_tests uv ${uv_test_libraries})
add_test(NAME uv_test
COMMAND uv_run_tests
......@@ -363,7 +391,6 @@ if(BUILD_TESTING)
add_executable(uv_run_tests_a ${uv_test_sources})
target_compile_definitions(uv_run_tests_a PRIVATE ${uv_defines})
target_compile_options(uv_run_tests_a PRIVATE ${uv_cflags})
target_include_directories(uv_run_tests_a PRIVATE include)
target_link_libraries(uv_run_tests_a uv_a ${uv_test_libraries})
add_test(NAME uv_test_a
COMMAND uv_run_tests_a
......@@ -372,12 +399,15 @@ endif()
if(UNIX)
# Now for some gibbering horrors from beyond the stars...
include(GNUInstallDirs)
foreach(x ${uv_libraries})
set(LIBS "${LIBS} -l${x}")
endforeach(x)
file(STRINGS configure.ac configure_ac REGEX ^AC_INIT)
string(REGEX MATCH [0-9]+[.][0-9]+[.][0-9]+ PACKAGE_VERSION "${configure_ac}")
string(REGEX MATCH ^[0-9]+ UV_VERSION_MAJOR "${PACKAGE_VERSION}")
# The version in the filename is mirroring the behaviour of autotools.
set_target_properties(uv PROPERTIES VERSION ${UV_VERSION_MAJOR}.0.0
SOVERSION ${UV_VERSION_MAJOR})
set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
set(prefix ${CMAKE_INSTALL_PREFIX})
......@@ -390,3 +420,11 @@ if(UNIX)
install(TARGETS uv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
if(WIN32)
install(DIRECTORY include/ DESTINATION include)
install(FILES LICENSE DESTINATION .)
install(TARGETS uv uv_a
RUNTIME DESTINATION lib/$<CONFIG>
ARCHIVE DESTINATION lib/$<CONFIG>)
endif()
This diff is collapsed.
......@@ -17,6 +17,8 @@ libuv is currently managed by the following individuals:
- GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere)
* **Jameson Nash** ([@vtjnash](https://github.com/vtjnash))
* **John Barboza** ([@jbarz](https://github.com/jbarz))
* **Richard Lau** ([@richardlau](https://github.com/richardlau))
- GPG key: C82F A3AE 1CBE DC6B E46B 9360 C43C EC45 C17A B93C (pubkey-richardlau)
* **Santiago Gimeno** ([@santigimeno](https://github.com/santigimeno))
- GPG key: 612F 0EAD 9401 6223 79DF 4402 F28C 3C8D A33C 03BE (pubkey-santigimeno)
* **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul))
......
......@@ -35,6 +35,7 @@ libuv_la_SOURCES = src/fs-poll.c \
src/idna.h \
src/inet.c \
src/queue.h \
src/random.c \
src/strscpy.c \
src/strscpy.h \
src/threadpool.c \
......@@ -45,12 +46,10 @@ libuv_la_SOURCES = src/fs-poll.c \
src/version.c
if SUNOS
if GCC
# 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 += -pthreads
endif
endif
if WINNT
......@@ -107,6 +106,7 @@ libuv_la_SOURCES += src/unix/async.c \
src/unix/pipe.c \
src/unix/poll.c \
src/unix/process.c \
src/unix/random-devurandom.c \
src/unix/signal.c \
src/unix/spinlock.h \
src/unix/stream.c \
......@@ -119,8 +119,8 @@ endif # WINNT
EXTRA_DIST = test/fixtures/empty_file \
test/fixtures/load_error.node \
test/fixtures/lorem_ipsum.txt \
include \
test \
docs \
img \
samples \
......@@ -140,23 +140,13 @@ EXTRA_DIST = test/fixtures/empty_file \
TESTS = test/run-tests
check_PROGRAMS = test/run-tests
if OS390
test_run_tests_CFLAGS =
else
if GCC
test_run_tests_CFLAGS = -Wno-long-long
else
test_run_tests_CFLAGS =
endif
endif
if SUNOS
if GCC
# 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.
test_run_tests_CFLAGS += -pthreads
endif
endif
test_run_tests_LDFLAGS =
test_run_tests_SOURCES = test/blackhole-server.c \
......@@ -191,6 +181,9 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-fs-event.c \
test/test-fs-poll.c \
test/test-fs.c \
test/test-fs-readdir.c \
test/test-fs-fd-hash.c \
test/test-fs-open-flags.c \
test/test-fork.c \
test/test-getters-setters.c \
test/test-get-currentexe.c \
......@@ -201,6 +194,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-gethostname.c \
test/test-getnameinfo.c \
test/test-getsockname.c \
test/test-gettimeofday.c \
test/test-handle-fileno.c \
test/test-homedir.c \
test/test-hrtime.c \
......@@ -244,6 +238,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-process-title.c \
test/test-process-title-threadsafe.c \
test/test-queue-foreach-delete.c \
test/test-random.c \
test/test-ref.c \
test/test-run-nowait.c \
test/test-run-once.c \
......@@ -252,6 +247,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-shutdown-eof.c \
test/test-shutdown-twice.c \
test/test-signal-multiple-loops.c \
test/test-signal-pending-on-close.c \
test/test-signal.c \
test/test-socket-buffer-size.c \
test/test-spawn.c \
......@@ -263,6 +259,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-tcp-close-accept.c \
test/test-tcp-close-while-connecting.c \
test/test-tcp-close.c \
test/test-tcp-close-reset.c \
test/test-tcp-create-socket-early.c \
test/test-tcp-connect-error-after-write.c \
test/test-tcp-connect-error.c \
......@@ -279,6 +276,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-tcp-writealot.c \
test/test-tcp-write-fail.c \
test/test-tcp-try-write.c \
test/test-tcp-try-write-error.c \
test/test-tcp-write-queue-order.c \
test/test-thread-equal.c \
test/test-thread.c \
......@@ -327,6 +325,16 @@ test_run_tests_CFLAGS += -D_ALL_SOURCE \
-D_LINUX_SOURCE_COMPAT
endif
if OS400
test_run_tests_CFLAGS += -D_ALL_SOURCE \
-D_XOPEN_SOURCE=500 \
-D_LINUX_SOURCE_COMPAT
endif
if HAIKU
test_run_tests_CFLAGS += -D_BSD_SOURCE
endif
if LINUX
test_run_tests_CFLAGS += -D_GNU_SOURCE
endif
......@@ -363,10 +371,30 @@ uvinclude_HEADERS += include/uv/aix.h
libuv_la_SOURCES += src/unix/aix.c src/unix/aix-common.c
endif
if OS400
libuv_la_CFLAGS += -D_ALL_SOURCE \
-D_XOPEN_SOURCE=500 \
-D_LINUX_SOURCE_COMPAT \
-D_THREAD_SAFE
uvinclude_HEADERS += include/uv/posix.h
libuv_la_SOURCES += src/unix/aix-common.c \
src/unix/ibmi.c \
src/unix/posix-poll.c \
src/unix/no-fsevents.c \
src/unix/no-proctitle.c
endif
if ANDROID
uvinclude_HEADERS += include/uv/android-ifaddrs.h
libuv_la_SOURCES += src/unix/android-ifaddrs.c \
src/unix/pthread-fixes.c
src/unix/linux-core.c \
src/unix/linux-inotify.c \
src/unix/linux-syscalls.c \
src/unix/procfs-exepath.c \
src/unix/pthread-fixes.c \
src/unix/random-getrandom.c \
src/unix/random-sysctl-linux.c \
src/unix/sysinfo-loadavg.c
endif
if CYGWIN
......@@ -392,7 +420,8 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/darwin-proctitle.c \
src/unix/fsevents.c \
src/unix/kqueue.c \
src/unix/proctitle.c
src/unix/proctitle.c \
src/unix/random-getentropy.c
test_run_tests_LDFLAGS += -lutil
endif
......@@ -412,10 +441,22 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/bsd-proctitle.c \
src/unix/freebsd.c \
src/unix/kqueue.c \
src/unix/posix-hrtime.c
src/unix/posix-hrtime.c \
src/unix/random-getrandom.c
test_run_tests_LDFLAGS += -lutil
endif
if HAIKU
uvinclude_HEADERS += include/uv/posix.h
libuv_la_CFLAGS += -D_BSD_SOURCE
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/haiku.c \
src/unix/no-fsevents.c \
src/unix/no-proctitle.c \
src/unix/posix-hrtime.c \
src/unix/posix-poll.c
endif
if HURD
uvinclude_HEADERS += include/uv/posix.h
libuv_la_SOURCES += src/unix/no-fsevents.c \
......@@ -432,8 +473,9 @@ libuv_la_SOURCES += src/unix/linux-core.c \
src/unix/linux-syscalls.h \
src/unix/procfs-exepath.c \
src/unix/proctitle.c \
src/unix/sysinfo-loadavg.c \
src/unix/sysinfo-memory.c
src/unix/random-getrandom.c \
src/unix/random-sysctl-linux.c \
src/unix/sysinfo-loadavg.c
test_run_tests_LDFLAGS += -lutil
endif
......@@ -466,7 +508,8 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/bsd-proctitle.c \
src/unix/kqueue.c \
src/unix/openbsd.c \
src/unix/posix-hrtime.c
src/unix/posix-hrtime.c \
src/unix/random-getentropy.c
test_run_tests_LDFLAGS += -lutil
endif
......@@ -487,6 +530,7 @@ libuv_la_CFLAGS += -D_UNIX03_THREADS \
-D_XOPEN_SOURCE_EXTENDED \
-D_ALL_SOURCE \
-D_LARGE_TIME_API \
-D_OPEN_SYS_SOCK_EXT3 \
-D_OPEN_SYS_SOCK_IPV6 \
-D_OPEN_SYS_FILE_EXT \
-DUV_PLATFORM_SEM_T=int \
......
......@@ -172,11 +172,14 @@ $ make install
To build with [CMake](https://cmake.org/):
```bash
$ mkdir -p out/cmake ; cd out/cmake ; cmake -DBUILD_TESTING=ON ../..
$ make all test
# Or manually:
$ ./uv_run_tests # shared library build
$ ./uv_run_tests_a # static library build
$ mkdir -p out/cmake ; cd out/cmake # create build directory
$ cmake ../.. -DBUILD_TESTING=ON # generate project with test
$ cmake --build . # build
$ ctest -C Debug --output-on-failure # run tests
# Or manually run tests:
$ ./out/cmake/uv_run_tests # shared library build
$ ./out/cmake/uv_run_tests_a # static library build
```
To build with GYP, first run:
......@@ -384,7 +387,7 @@ $ gdb --args out/Debug/run-tests TEST_NAME
Use the `--trace-children=yes` parameter:
```bash
$ valgrind --trace-children=yes -v --tool=memcheck --leak-check=full --track-origins=yes --leak-resolution=high --show-reachable=yes --log-file=memcheck.log out/Debug/run-tests TEST_NAME
$ valgrind --trace-children=yes -v --tool=memcheck --leak-check=full --track-origins=yes --leak-resolution=high --show-reachable=yes --log-file=memcheck-%p.log out/Debug/run-tests TEST_NAME
```
### Running benchmarks
......@@ -398,6 +401,8 @@ Check the [SUPPORTED_PLATFORMS file](SUPPORTED_PLATFORMS.md).
### AIX Notes
AIX compilation using IBM XL C/C++ requires version 12.1 or greater.
AIX support for filesystem events requires the non-default IBM `bos.ahafs`
package to be installed. This package provides the AIX Event Infrastructure
that is detected by `autoconf`.
......
......@@ -5,7 +5,7 @@
| GNU/Linux | Tier 1 | Linux >= 2.6.32 with glibc >= 2.12 | |
| macOS | Tier 1 | macOS >= 10.7 | |
| Windows | Tier 1 | >= Windows 7 | MSVC 2008 and later are supported |
| FreeBSD | Tier 1 | >= 9 (see note) | |
| FreeBSD | Tier 1 | >= 10 | |
| AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix |
| z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos |
| Linux with musl | Tier 2 | musl >= 1.0 | |
......@@ -16,11 +16,6 @@
| SunOS | Tier 3 | Solaris 121 and later | |
| Other | Tier 3 | N/A | |
#### Note on FreeBSD 9
While FreeBSD is supported as Tier 1, FreeBSD 9 will get Tier 2 support until
it reaches end of life, in December 2016.
## Support types
* **Tier 1**: Officially supported and tested with CI. Any contributed patch
......
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright 1992-2019 Free Software Foundation, Inc.
# Copyright 1992-2020 Free Software Foundation, Inc.
timestamp='2019-03-04'
timestamp='2020-01-01'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
......@@ -50,7 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
Copyright 1992-2019 Free Software Foundation, Inc.
Copyright 1992-2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
......@@ -99,6 +99,8 @@ tmp=
trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
set_cc_for_build() {
# prevent multiple calls if $tmp is already set
test "$tmp" && return 0
: "${TMPDIR=/tmp}"
# shellcheck disable=SC2039
{ tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
......@@ -262,6 +264,9 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
*:SolidBSD:*:*)
echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
exit ;;
*:OS108:*:*)
echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE"
exit ;;
macppc:MirBSD:*:*)
echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
exit ;;
......@@ -271,12 +276,15 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
*:Sortix:*:*)
echo "$UNAME_MACHINE"-unknown-sortix
exit ;;
*:Twizzler:*:*)
echo "$UNAME_MACHINE"-unknown-twizzler
exit ;;
*:Redox:*:*)
echo "$UNAME_MACHINE"-unknown-redox
exit ;;
mips:OSF1:*.*)
echo mips-dec-osf1
exit ;;
echo mips-dec-osf1
exit ;;
alpha:OSF1:*:*)
case $UNAME_RELEASE in
*4.0)
......@@ -918,7 +926,7 @@ EOF
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
......@@ -1325,38 +1333,39 @@ EOF
echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
set_cc_for_build
if test "$UNAME_PROCESSOR" = unknown ; then
UNAME_PROCESSOR=powerpc
UNAME_PROCESSOR=`uname -p`
case $UNAME_PROCESSOR in
unknown) UNAME_PROCESSOR=powerpc ;;
esac
if command -v xcode-select > /dev/null 2> /dev/null && \
! xcode-select --print-path > /dev/null 2> /dev/null ; then
# Avoid executing cc if there is no toolchain installed as
# cc will be a stub that puts up a graphical alert
# prompting the user to install developer tools.
CC_FOR_BUILD=no_compiler_found
else
set_cc_for_build
fi
if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
i386) UNAME_PROCESSOR=x86_64 ;;
powerpc) UNAME_PROCESSOR=powerpc64 ;;
esac
fi
# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_PPC >/dev/null
then
UNAME_PROCESSOR=powerpc
fi
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
i386) UNAME_PROCESSOR=x86_64 ;;
powerpc) UNAME_PROCESSOR=powerpc64 ;;
esac
fi
# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_PPC >/dev/null
then
UNAME_PROCESSOR=powerpc
fi
elif test "$UNAME_PROCESSOR" = i386 ; then
# Avoid executing cc on OS X 10.9, as it ships with a stub
# that puts up a graphical alert prompting to install
# developer tools. Any system running Mac OS X 10.7 or
# later (Darwin 11 and later) is required to have a 64-bit
# processor. This is not true of the ARM version of Darwin
# that Apple uses in portable devices.
UNAME_PROCESSOR=x86_64
# uname -m returns i386 or x86_64
UNAME_PROCESSOR=$UNAME_MACHINE
fi
echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
exit ;;
......@@ -1468,6 +1477,14 @@ cat > "$dummy.c" <<EOF
#include <sys/types.h>
#include <sys/utsname.h>
#endif
#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
#include <signal.h>
#if defined(_SIZE_T_) || defined(SIGLOST)
#include <sys/utsname.h>
#endif
#endif
#endif
main ()
{
#if defined (sony)
......@@ -1554,19 +1571,24 @@ main ()
#else
printf ("vax-dec-bsd\n"); exit (0);
#endif
#else
#if defined(_SIZE_T_) || defined(SIGLOST)
struct utsname un;
uname (&un);
printf ("vax-dec-ultrix%s\n", un.release); exit (0);
#else
printf ("vax-dec-ultrix\n"); exit (0);
#endif
#endif
#endif
#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
#include <signal.h>
#if defined(_SIZE_T_) /* >= ULTRIX4 */
printf ("mips-dec-ultrix4\n"); exit (0);
#if defined(_SIZE_T_) || defined(SIGLOST)
struct utsname *un;
uname (&un);
printf ("mips-dec-ultrix%s\n", un.release); exit (0);
#else
#if defined(ULTRIX3) || defined(ultrix3) || defined(SIGLOST)
printf ("mips-dec-ultrix3\n"); exit (0);
#endif
printf ("mips-dec-ultrix\n"); exit (0);
#endif
#endif
#endif
......
#! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2019 Free Software Foundation, Inc.
# Copyright 1992-2020 Free Software Foundation, Inc.
timestamp='2019-01-05'
timestamp='2020-01-01'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
......@@ -67,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright 1992-2019 Free Software Foundation, Inc.
Copyright 1992-2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
......@@ -337,17 +337,14 @@ case $1 in
basic_machine=m88k-harris
os=sysv3
;;
hp300)
hp300 | hp300hpux)
basic_machine=m68k-hp
os=hpux
;;
hp300bsd)
basic_machine=m68k-hp
os=bsd
;;
hp300hpux)
basic_machine=m68k-hp
os=hpux
;;
hppaosf)
basic_machine=hppa1.1-hp
os=osf
......@@ -360,10 +357,6 @@ case $1 in
basic_machine=i386-mach
os=mach
;;
vsta)
basic_machine=i386-pc
os=vsta
;;
isi68 | isi)
basic_machine=m68k-isi
os=sysv
......@@ -612,6 +605,10 @@ case $1 in
basic_machine=vax-dec
os=vms
;;
vsta)
basic_machine=i386-pc
os=vsta
;;
vxworks960)
basic_machine=i960-wrs
os=vxworks
......@@ -1172,7 +1169,7 @@ case $cpu-$vendor in
| asmjs \
| ba \
| be32 | be64 \
| bfin | bs2000 \
| bfin | bpf | bs2000 \
| c[123]* | c30 | [cjt]90 | c4x \
| c8051 | clipper | craynv | csky | cydra \
| d10v | d30v | dlx | dsp16xx \
......@@ -1346,11 +1343,11 @@ case $os in
| hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
| sym* | kopensolaris* | plan9* \
| amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
| aos* | aros* | cloudabi* | sortix* \
| aos* | aros* | cloudabi* | sortix* | twizzler* \
| nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
| clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
| knetbsd* | mirbsd* | netbsd* \
| bitrig* | openbsd* | solidbsd* | libertybsd* \
| bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \
| ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \
| bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
| ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
......@@ -1368,7 +1365,8 @@ case $os in
| powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
| skyos* | haiku* | rdos* | toppers* | drops* | es* \
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi*)
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix)
# Remember, each alternative MUST END IN *, to match a version number.
;;
qnx*)
......@@ -1452,9 +1450,6 @@ case $os in
ns2)
os=nextstep2
;;
nsk*)
os=nsk
;;
# Preserve the version number of sinix5.
sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
......
......@@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
AC_INIT([libuv], [1.27.0], [https://github.com/libuv/libuv/issues])
AC_INIT([libuv], [1.34.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])
......@@ -24,18 +24,17 @@ AC_ENABLE_SHARED
AC_ENABLE_STATIC
AC_PROG_CC
AM_PROG_CC_C_O
AS_IF([AS_CASE([$host_os],[openedition*], [false], [true])], [
CC_CHECK_CFLAGS_APPEND([-pedantic])
])
CC_FLAG_VISIBILITY #[-fvisibility=hidden]
CC_CHECK_CFLAGS_APPEND([-g])
AS_IF([test "x$GCC" = xyes], [
AS_IF([AS_CASE([$host_os], [openedition*], [false], [true])], [
CC_CHECK_CFLAGS_APPEND([-pedantic])
])
CC_CHECK_CFLAGS_APPEND([-std=gnu89])
CC_CHECK_CFLAGS_APPEND([-Wall])
CC_CHECK_CFLAGS_APPEND([-Wextra])
CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter])
CC_CHECK_CFLAGS_APPEND([-Wstrict-prototypes])
])
CC_CHECK_CFLAGS_APPEND([-std=gnu89])
CC_CHECK_CFLAGS_APPEND([-Wall])
CC_CHECK_CFLAGS_APPEND([-Wextra])
CC_CHECK_CFLAGS_APPEND([-Wno-long-long])
CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter])
CC_CHECK_CFLAGS_APPEND([-Wstrict-prototypes])
# 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.
......@@ -52,19 +51,20 @@ AC_CHECK_LIB([rt], [clock_gettime])
AC_CHECK_LIB([sendfile], [sendfile])
AC_CHECK_LIB([socket], [socket])
AC_SYS_LARGEFILE
AM_CONDITIONAL([GCC], [AS_IF([test "x$GCC" = xyes], [true], [false])])
AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])])
AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])])
AM_CONDITIONAL([CYGWIN], [AS_CASE([$host_os],[cygwin*], [true], [false])])
AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])])
AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])])
AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[*freebsd*], [true], [false])])
AM_CONDITIONAL([HAIKU], [AS_CASE([$host_os],[haiku], [true], [false])])
AM_CONDITIONAL([HURD], [AS_CASE([$host_os],[gnu*], [true], [false])])
AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])])
AM_CONDITIONAL([MSYS], [AS_CASE([$host_os],[msys*], [true], [false])])
AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])])
AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])])
AM_CONDITIONAL([OS390], [AS_CASE([$host_os],[openedition*], [true], [false])])
AM_CONDITIONAL([OS400], [AS_CASE([$host_os],[os400], [true], [false])])
AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])])
AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])])
AS_CASE([$host_os],[mingw*], [
......@@ -74,8 +74,12 @@ AS_CASE([$host_os], [netbsd*], [AC_CHECK_LIB([kvm], [kvm_open])])
AS_CASE([$host_os], [kfreebsd*], [
LIBS="$LIBS -lfreebsd-glue"
])
AS_CASE([$host_os], [haiku], [
LIBS="$LIBS -lnetwork"
])
AC_CHECK_HEADERS([sys/ahafs_evProds.h])
AC_CONFIG_FILES([Makefile libuv.pc])
AC_CONFIG_LINKS([test/fixtures/empty_file:test/fixtures/empty_file])
AC_CONFIG_LINKS([test/fixtures/load_error.node:test/fixtures/load_error.node])
AC_CONFIG_LINKS([test/fixtures/lorem_ipsum.txt:test/fixtures/lorem_ipsum.txt])
AC_OUTPUT
......@@ -27,6 +27,10 @@
extern "C" {
#endif
#if defined(BUILDING_UV_SHARED) && defined(USING_UV_SHARED)
#error "Define either BUILDING_UV_SHARED or USING_UV_SHARED, not both."
#endif
#ifdef _WIN32
/* Windows - set up dll import/export decorators. */
# if defined(BUILDING_UV_SHARED)
......@@ -143,6 +147,7 @@ extern "C" {
XX(EREMOTEIO, "remote I/O error") \
XX(ENOTTY, "inappropriate ioctl for device") \
XX(EFTYPE, "inappropriate file type or format") \
XX(EILSEQ, "illegal byte sequence") \
#define UV_HANDLE_TYPE_MAP(XX) \
XX(ASYNC, async) \
......@@ -172,6 +177,7 @@ extern "C" {
XX(WORK, work) \
XX(GETADDRINFO, getaddrinfo) \
XX(GETNAMEINFO, getnameinfo) \
XX(RANDOM, random) \
typedef enum {
#define XX(code, _) UV_ ## code = UV__ ## code,
......@@ -202,6 +208,7 @@ typedef enum {
/* Handle types. */
typedef struct uv_loop_s uv_loop_t;
typedef struct uv_handle_s uv_handle_t;
typedef struct uv_dir_s uv_dir_t;
typedef struct uv_stream_s uv_stream_t;
typedef struct uv_tcp_s uv_tcp_t;
typedef struct uv_udp_s uv_udp_t;
......@@ -228,13 +235,16 @@ typedef struct uv_connect_s uv_connect_t;
typedef struct uv_udp_send_s uv_udp_send_t;
typedef struct uv_fs_s uv_fs_t;
typedef struct uv_work_s uv_work_t;
typedef struct uv_random_s uv_random_t;
/* None of the above. */
typedef struct uv_env_item_s uv_env_item_t;
typedef struct uv_cpu_info_s uv_cpu_info_t;
typedef struct uv_interface_address_s uv_interface_address_t;
typedef struct uv_dirent_s uv_dirent_t;
typedef struct uv_passwd_s uv_passwd_t;
typedef struct uv_utsname_s uv_utsname_t;
typedef struct uv_statfs_s uv_statfs_t;
typedef enum {
UV_LOOP_BLOCK_SIGNAL
......@@ -322,6 +332,10 @@ typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req,
int status,
const char* hostname,
const char* service);
typedef void (*uv_random_cb)(uv_random_t* req,
int status,
void* buf,
size_t buflen);
typedef struct {
long tv_sec;
......@@ -556,6 +570,7 @@ UV_EXTERN int uv_tcp_getsockname(const uv_tcp_t* handle,
UV_EXTERN int uv_tcp_getpeername(const uv_tcp_t* handle,
struct sockaddr* name,
int* namelen);
UV_EXTERN int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb);
UV_EXTERN int uv_tcp_connect(uv_connect_t* req,
uv_tcp_t* handle,
const struct sockaddr* addr,
......@@ -642,6 +657,11 @@ UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle,
const char* multicast_addr,
const char* interface_addr,
uv_membership membership);
UV_EXTERN int uv_udp_set_source_membership(uv_udp_t* handle,
const char* multicast_addr,
const char* interface_addr,
const char* source_addr,
uv_membership membership);
UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t* handle, int on);
UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl);
UV_EXTERN int uv_udp_set_multicast_interface(uv_udp_t* handle,
......@@ -686,10 +706,25 @@ typedef enum {
UV_TTY_MODE_IO
} uv_tty_mode_t;
typedef enum {
/*
* The console supports handling of virtual terminal sequences
* (Windows10 new console, ConEmu)
*/
UV_TTY_SUPPORTED,
/* The console cannot process the virtual terminal sequence. (Legacy
* console)
*/
UV_TTY_UNSUPPORTED
} uv_tty_vtermstate_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*, 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);
UV_EXTERN void uv_tty_set_vterm_state(uv_tty_vtermstate_t state);
UV_EXTERN int uv_tty_get_vterm_state(uv_tty_vtermstate_t* state);
#ifdef __cplusplus
extern "C++" {
......@@ -1069,6 +1104,17 @@ struct uv_utsname_s {
to as meaningless in the docs. */
};
struct uv_statfs_s {
uint64_t f_type;
uint64_t f_bsize;
uint64_t f_blocks;
uint64_t f_bfree;
uint64_t f_bavail;
uint64_t f_files;
uint64_t f_ffree;
uint64_t f_spare[4];
};
typedef enum {
UV_DIRENT_UNKNOWN,
UV_DIRENT_FILE,
......@@ -1098,6 +1144,11 @@ typedef struct {
long tv_usec;
} uv_timeval_t;
typedef struct {
int64_t tv_sec;
int32_t tv_usec;
} uv_timeval64_t;
typedef struct {
uv_timeval_t ru_utime; /* user CPU time used */
uv_timeval_t ru_stime; /* system CPU time used */
......@@ -1144,6 +1195,13 @@ UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count);
struct uv_env_item_s {
char* name;
char* value;
};
UV_EXTERN int uv_os_environ(uv_env_item_t** envitems, int* count);
UV_EXTERN void uv_os_free_environ(uv_env_item_t* envitems, int count);
UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size);
UV_EXTERN int uv_os_setenv(const char* name, const char* value);
UV_EXTERN int uv_os_unsetenv(const char* name);
......@@ -1196,9 +1254,21 @@ typedef enum {
UV_FS_FCHOWN,
UV_FS_REALPATH,
UV_FS_COPYFILE,
UV_FS_LCHOWN
UV_FS_LCHOWN,
UV_FS_OPENDIR,
UV_FS_READDIR,
UV_FS_CLOSEDIR,
UV_FS_STATFS,
UV_FS_MKSTEMP
} uv_fs_type;
struct uv_dir_s {
uv_dirent_t* dirents;
size_t nentries;
void* reserved[4];
UV_DIR_PRIVATE_FIELDS
};
/* uv_fs_t is a subclass of uv_req_t. */
struct uv_fs_s {
UV_REQ_FIELDS
......@@ -1280,6 +1350,10 @@ UV_EXTERN int uv_fs_mkdtemp(uv_loop_t* loop,
uv_fs_t* req,
const char* tpl,
uv_fs_cb cb);
UV_EXTERN int uv_fs_mkstemp(uv_loop_t* loop,
uv_fs_t* req,
const char* tpl,
uv_fs_cb cb);
UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
......@@ -1291,6 +1365,18 @@ UV_EXTERN int uv_fs_scandir(uv_loop_t* loop,
uv_fs_cb cb);
UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req,
uv_dirent_t* ent);
UV_EXTERN int uv_fs_opendir(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
uv_fs_cb cb);
UV_EXTERN int uv_fs_readdir(uv_loop_t* loop,
uv_fs_t* req,
uv_dir_t* dir,
uv_fs_cb cb);
UV_EXTERN int uv_fs_closedir(uv_loop_t* loop,
uv_fs_t* req,
uv_dir_t* dir,
uv_fs_cb cb);
UV_EXTERN int uv_fs_stat(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
......@@ -1405,6 +1491,10 @@ UV_EXTERN int uv_fs_lchown(uv_loop_t* loop,
uv_uid_t uid,
uv_gid_t gid,
uv_fs_cb cb);
UV_EXTERN int uv_fs_statfs(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
uv_fs_cb cb);
enum uv_fs_event {
......@@ -1510,6 +1600,26 @@ UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size
UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);
struct uv_random_s {
UV_REQ_FIELDS
/* read-only */
uv_loop_t* loop;
/* private */
int status;
void* buf;
size_t buflen;
uv_random_cb cb;
struct uv__work work_req;
};
UV_EXTERN int uv_random(uv_loop_t* loop,
uv_random_t* req,
void *buf,
size_t buflen,
unsigned flags, /* For future extension; must be 0. */
uv_random_cb cb);
#if defined(IF_NAMESIZE)
# define UV_IF_NAMESIZE (IF_NAMESIZE + 1)
#elif defined(IFNAMSIZ)
......@@ -1533,8 +1643,10 @@ UV_EXTERN int uv_chdir(const char* dir);
UV_EXTERN uint64_t uv_get_free_memory(void);
UV_EXTERN uint64_t uv_get_total_memory(void);
UV_EXTERN uint64_t uv_get_constrained_memory(void);
UV_EXTERN uint64_t uv_hrtime(void);
UV_EXTERN void uv_sleep(unsigned int msec);
UV_EXTERN void uv_disable_stdio_inheritance(void);
......@@ -1586,6 +1698,8 @@ UV_EXTERN void uv_key_delete(uv_key_t* key);
UV_EXTERN void* uv_key_get(uv_key_t* key);
UV_EXTERN void uv_key_set(uv_key_t* key, void* value);
UV_EXTERN int uv_gettimeofday(uv_timeval64_t* tv);
typedef void (*uv_thread_cb)(void* arg);
UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg);
......
......@@ -439,5 +439,10 @@
# define UV__EFTYPE (-4028)
#endif
#if defined(EILSEQ) && !defined(_WIN32)
# define UV__EILSEQ UV__ERR(EILSEQ)
#else
# define UV__EILSEQ (-4027)
#endif
#endif /* UV_ERRNO_H_ */
......@@ -49,8 +49,8 @@
# include "uv/linux.h"
#elif defined (__MVS__)
# include "uv/os390.h"
#elif defined(__PASE__)
# include "uv/posix.h"
#elif defined(__PASE__) /* __PASE__ and _AIX are both defined on IBM i */
# include "uv/posix.h" /* IBM i needs uv/posix.h, not uv/aix.h */
#elif defined(_AIX)
# include "uv/aix.h"
#elif defined(__sun)
......@@ -63,9 +63,11 @@
defined(__OpenBSD__) || \
defined(__NetBSD__)
# include "uv/bsd.h"
#elif defined(__CYGWIN__) || defined(__MSYS__)
#elif defined(__CYGWIN__) || \
defined(__MSYS__) || \
defined(__GNU__)
# include "uv/posix.h"
#elif defined(__GNU__)
#elif defined(__HAIKU__)
# include "uv/posix.h"
#endif
......@@ -166,6 +168,9 @@ typedef uid_t uv_uid_t;
typedef struct dirent uv__dirent_t;
#define UV_DIR_PRIVATE_FIELDS \
DIR* dir;
#if defined(DT_UNKNOWN)
# define HAVE_DIRENT_TYPES
# if defined(DT_REG)
......@@ -400,11 +405,25 @@ typedef struct {
#else
# define UV_FS_O_CREAT 0
#endif
#if defined(O_DIRECT)
#if defined(__linux__) && defined(__arm__)
# define UV_FS_O_DIRECT 0x10000
#elif defined(__linux__) && defined(__m68k__)
# define UV_FS_O_DIRECT 0x10000
#elif defined(__linux__) && defined(__mips__)
# define UV_FS_O_DIRECT 0x08000
#elif defined(__linux__) && defined(__powerpc__)
# define UV_FS_O_DIRECT 0x20000
#elif defined(__linux__) && defined(__s390x__)
# define UV_FS_O_DIRECT 0x04000
#elif defined(__linux__) && defined(__x86_64__)
# define UV_FS_O_DIRECT 0x04000
#elif defined(O_DIRECT)
# define UV_FS_O_DIRECT O_DIRECT
#else
# define UV_FS_O_DIRECT 0
#endif
#if defined(O_DIRECTORY)
# define UV_FS_O_DIRECTORY O_DIRECTORY
#else
......@@ -477,6 +496,7 @@ typedef struct {
#endif
/* fs open() flags supported on other platforms: */
#define UV_FS_O_FILEMAP 0
#define UV_FS_O_RANDOM 0
#define UV_FS_O_SHORT_LIVED 0
#define UV_FS_O_SEQUENTIAL 0
......
......@@ -31,7 +31,7 @@
*/
#define UV_VERSION_MAJOR 1
#define UV_VERSION_MINOR 27
#define UV_VERSION_MINOR 34
#define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""
......
......@@ -301,6 +301,11 @@ typedef struct uv__dirent_s {
char d_name[1];
} uv__dirent_t;
#define UV_DIR_PRIVATE_FIELDS \
HANDLE dir_handle; \
WIN32_FIND_DATAW find_data; \
BOOL need_find_call;
#define HAVE_DIRENT_TYPES
#define UV__DT_DIR UV_DIRENT_DIR
#define UV__DT_FILE UV_DIRENT_FILE
......@@ -663,6 +668,7 @@ typedef struct {
#define UV_FS_O_APPEND _O_APPEND
#define UV_FS_O_CREAT _O_CREAT
#define UV_FS_O_EXCL _O_EXCL
#define UV_FS_O_FILEMAP 0x20000000
#define UV_FS_O_RANDOM _O_RANDOM
#define UV_FS_O_RDONLY _O_RDONLY
#define UV_FS_O_RDWR _O_RDWR
......
......@@ -241,7 +241,7 @@ static void timer_close_cb(uv_handle_t* timer) {
handle = ctx->parent_handle;
if (ctx == handle->poll_ctx) {
handle->poll_ctx = ctx->previous;
if (handle->poll_ctx == NULL)
if (handle->poll_ctx == NULL && uv__is_closing(handle))
uv__make_close_pending((uv_handle_t*)handle);
} else {
for (last = handle->poll_ctx, it = last->previous;
......
......@@ -27,7 +27,7 @@
#include <stdlib.h>
#define MAX_THREADPOOL_SIZE 128
#define MAX_THREADPOOL_SIZE 1024
static uv_once_t once = UV_ONCE_INIT;
static uv_cond_t cond;
......@@ -372,6 +372,10 @@ int uv_cancel(uv_req_t* req) {
loop = ((uv_getnameinfo_t*) req)->loop;
wreq = &((uv_getnameinfo_t*) req)->work_req;
break;
case UV_RANDOM:
loop = ((uv_random_t*) req)->loop;
wreq = &((uv_random_t*) req)->work_req;
break;
case UV_WORK:
loop = ((uv_work_t*) req)->loop;
wreq = &((uv_work_t*) req)->work_req;
......
......@@ -74,7 +74,7 @@ int uv_timer_start(uv_timer_t* handle,
uint64_t repeat) {
uint64_t clamped_timeout;
if (cb == NULL)
if (uv__is_closing(handle) || cb == NULL)
return UV_EINVAL;
if (uv__is_active(handle))
......
......@@ -34,6 +34,7 @@
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in6_var.h>
#include <arpa/inet.h>
#include <sys/time.h>
......@@ -155,41 +156,45 @@ int uv_exepath(char* buffer, size_t* size) {
}
}
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
int i;
for (i = 0; i < count; ++i) {
uv__free(cpu_infos[i].model);
}
uv__free(cpu_infos);
}
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
uv_interface_address_t* address;
int sockfd, inet6, size = 1;
int sockfd, sock6fd, inet6, i, r, size = 1;
struct ifconf ifc;
struct ifreq *ifr, *p, flg;
struct in6_ifreq if6;
struct sockaddr_dl* sa_addr;
ifc.ifc_req = NULL;
sock6fd = -1;
r = 0;
*count = 0;
*addresses = NULL;
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
return UV__ERR(errno);
r = UV__ERR(errno);
goto cleanup;
}
if (0 > (sock6fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP))) {
r = UV__ERR(errno);
goto cleanup;
}
if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
uv__close(sockfd);
return UV__ERR(errno);
r = UV__ERR(errno);
goto cleanup;
}
ifc.ifc_req = (struct ifreq*)uv__malloc(size);
if (ifc.ifc_req == NULL) {
r = UV_ENOMEM;
goto cleanup;
}
ifc.ifc_len = size;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
uv__close(sockfd);
return UV__ERR(errno);
r = UV__ERR(errno);
goto cleanup;
}
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
......@@ -207,8 +212,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
return UV__ERR(errno);
r = UV__ERR(errno);
goto cleanup;
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
......@@ -217,16 +222,14 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
(*count)++;
}
if (*count == 0) {
uv__close(sockfd);
return 0;
}
if (*count == 0)
goto cleanup;
/* Alloc the return interface structs */
*addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
*addresses = uv__calloc(*count, sizeof(**addresses));
if (!(*addresses)) {
uv__close(sockfd);
return UV_ENOMEM;
r = UV_ENOMEM;
goto cleanup;
}
address = *addresses;
......@@ -243,10 +246,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
inet6 = (p->ifr_addr.sa_family == AF_INET6);
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
return UV_ENOSYS;
}
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1)
goto syserror;
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
continue;
......@@ -260,28 +261,67 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
else
address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
sa_addr = (struct sockaddr_dl*) &p->ifr_addr;
memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) {
uv__close(sockfd);
return UV_ENOSYS;
}
if (inet6)
address->netmask.netmask6 = *((struct sockaddr_in6*) &p->ifr_addr);
else
if (inet6) {
memset(&if6, 0, sizeof(if6));
r = uv__strscpy(if6.ifr_name, p->ifr_name, sizeof(if6.ifr_name));
if (r == UV_E2BIG)
goto cleanup;
r = 0;
memcpy(&if6.ifr_Addr, &p->ifr_addr, sizeof(if6.ifr_Addr));
if (ioctl(sock6fd, SIOCGIFNETMASK6, &if6) == -1)
goto syserror;
address->netmask.netmask6 = *((struct sockaddr_in6*) &if6.ifr_Addr);
/* Explicitly set family as the ioctl call appears to return it as 0. */
address->netmask.netmask6.sin6_family = AF_INET6;
} else {
if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1)
goto syserror;
address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr);
/* Explicitly set family as the ioctl call appears to return it as 0. */
address->netmask.netmask4.sin_family = AF_INET;
}
address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
address++;
}
/* Fill in physical addresses. */
ifr = ifc.ifc_req;
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
p = ifr;
ifr = (struct ifreq*)
((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
if (p->ifr_addr.sa_family != AF_LINK)
continue;
address = *addresses;
for (i = 0; i < *count; i++) {
if (strcmp(address->name, p->ifr_name) == 0) {
sa_addr = (struct sockaddr_dl*) &p->ifr_addr;
memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
}
address++;
}
}
#undef ADDR_SIZE
goto cleanup;
uv__close(sockfd);
return 0;
syserror:
uv_free_interface_addresses(*addresses, *count);
*addresses = NULL;
*count = 0;
r = UV_ENOSYS;
cleanup:
if (sockfd != -1)
uv__close(sockfd);
if (sock6fd != -1)
uv__close(sock6fd);
uv__free(ifc.ifc_req);
return r;
}
......
......@@ -344,6 +344,11 @@ uint64_t uv_get_total_memory(void) {
}
uint64_t uv_get_constrained_memory(void) {
return 0; /* Memory constraints are unknown. */
}
void uv_loadavg(double avg[3]) {
perfstat_cpu_total_t ps_total;
int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
......
......@@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <netinet/in.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/if_packet.h>
typedef struct NetlinkList
{
......@@ -475,6 +476,7 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
l_addedNetmask = 1;
}
break;
case IFA_BROADCAST:
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
break;
......
......@@ -61,14 +61,43 @@ int uv_async_send(uv_async_t* handle) {
if (ACCESS_ONCE(int, handle->pending) != 0)
return 0;
if (cmpxchgi(&handle->pending, 0, 1) == 0)
uv__async_send(handle->loop);
/* Tell the other thread we're busy with the handle. */
if (cmpxchgi(&handle->pending, 0, 1) != 0)
return 0;
/* Wake up the other thread's event loop. */
uv__async_send(handle->loop);
/* Tell the other thread we're done. */
if (cmpxchgi(&handle->pending, 1, 2) != 1)
abort();
return 0;
}
/* Only call this from the event loop thread. */
static int uv__async_spin(uv_async_t* handle) {
int rc;
for (;;) {
/* rc=0 -- handle is not pending.
* rc=1 -- handle is pending, other thread is still working with it.
* rc=2 -- handle is pending, other thread is done.
*/
rc = cmpxchgi(&handle->pending, 2, 0);
if (rc != 1)
return rc;
/* Other thread is busy with this handle, spin until it's done. */
cpu_relax();
}
}
void uv__async_close(uv_async_t* handle) {
uv__async_spin(handle);
QUEUE_REMOVE(&handle->queue);
uv__handle_stop(handle);
}
......@@ -109,8 +138,8 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
QUEUE_REMOVE(q);
QUEUE_INSERT_TAIL(&loop->async_handles, q);
if (cmpxchgi(&h->pending, 1, 0) == 0)
continue;
if (0 == uv__async_spin(h))
continue; /* Not pending. */
if (h->async_cb == NULL)
continue;
......
......@@ -23,7 +23,6 @@
#endif
UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval));
UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval));
UV_UNUSED(static void cpu_relax(void));
/* Prefer hand-rolled assembly over the gcc builtins because the latter also
......@@ -37,10 +36,6 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
: "r" (newval), "0" (oldval)
: "memory");
return out;
#elif defined(_AIX) && defined(__xlC__)
const int out = (*(volatile int*) ptr);
__compare_and_swap(ptr, &oldval, newval);
return out;
#elif defined(__MVS__)
unsigned int op4;
if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
......@@ -55,42 +50,6 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
#endif
}
UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) {
#if defined(__i386__) || defined(__x86_64__)
long out;
__asm__ __volatile__ ("lock; cmpxchg %2, %1;"
: "=a" (out), "+m" (*(volatile long*) ptr)
: "r" (newval), "0" (oldval)
: "memory");
return out;
#elif defined(_AIX) && defined(__xlC__)
const long out = (*(volatile int*) ptr);
# if defined(__64BIT__)
__compare_and_swaplp(ptr, &oldval, newval);
# else
__compare_and_swap(ptr, &oldval, newval);
# endif /* if defined(__64BIT__) */
return out;
#elif defined (__MVS__)
#ifdef _LP64
unsigned long long op4;
if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval,
(unsigned long long*) ptr, *ptr, &op4))
#else
unsigned long op4;
if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
(unsigned int*) ptr, *ptr, &op4))
#endif
return oldval;
else
return op4;
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
return atomic_cas_ulong((ulong_t *)ptr, (ulong_t)oldval, (ulong_t)newval);
#else
return __sync_val_compare_and_swap(ptr, oldval, newval);
#endif
}
UV_UNUSED(static void cpu_relax(void)) {
#if defined(__i386__) || defined(__x86_64__)
__asm__ __volatile__ ("rep; nop"); /* a.k.a. PAUSE */
......
......@@ -31,6 +31,10 @@
#include <net/if_dl.h>
#endif
#if defined(__HAIKU__)
#define IFF_RUNNING IFF_LINK
#endif
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
return 1;
......@@ -45,7 +49,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
if (exclude_type == UV__EXCLUDE_IFPHYS)
return (ent->ifa_addr->sa_family != AF_LINK);
#endif
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) || \
defined(__HAIKU__)
/*
* On BSD getifaddrs returns information related to the raw underlying
* devices. We're not interested in this information.
......@@ -64,7 +69,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
struct ifaddrs* addrs;
struct ifaddrs* ent;
uv_interface_address_t* address;
#if !(defined(__CYGWIN__) || defined(__MSYS__))
int i;
#endif
*count = 0;
*addresses = NULL;
......@@ -84,7 +91,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return 0;
}
*addresses = uv__malloc(*count * sizeof(**addresses));
/* Make sure the memory is initiallized to zero using calloc() */
*addresses = uv__calloc(*count, sizeof(**addresses));
if (*addresses == NULL) {
freeifaddrs(addrs);
......@@ -116,6 +124,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
address++;
}
#if !(defined(__CYGWIN__) || defined(__MSYS__))
/* Fill in physical addresses for each interface */
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
......@@ -124,20 +133,15 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
address = *addresses;
for (i = 0; i < *count; i++) {
#if defined(__CYGWIN__) || defined(__MSYS__)
memset(address->phys_addr, 0, sizeof(address->phys_addr));
#else
if (strcmp(address->name, ent->ifa_name) == 0) {
struct sockaddr_dl* sa_addr;
sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
} else {
memset(address->phys_addr, 0, sizeof(address->phys_addr));
}
#endif
address++;
}
}
#endif
freeifaddrs(addrs);
......
......@@ -30,7 +30,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fcntl.h> /* O_CLOEXEC */
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/un.h>
......@@ -41,6 +41,7 @@
#include <sys/resource.h> /* getrusage */
#include <pwd.h>
#include <sys/utsname.h>
#include <sys/time.h>
#ifdef __sun
# include <sys/filio.h>
......@@ -48,29 +49,36 @@
# include <sys/wait.h>
#endif
#ifdef __APPLE__
# include <mach-o/dyld.h> /* _NSGetExecutablePath */
#if defined(__APPLE__)
# include <sys/filio.h>
# if defined(O_CLOEXEC)
# define UV__O_CLOEXEC O_CLOEXEC
# endif
#endif
# endif /* defined(__APPLE__) */
#if defined(__APPLE__) && !TARGET_OS_IPHONE
# include <crt_externs.h>
# include <mach-o/dyld.h> /* _NSGetExecutablePath */
# define environ (*_NSGetEnviron())
#else /* defined(__APPLE__) && !TARGET_OS_IPHONE */
extern char** environ;
#endif /* !(defined(__APPLE__) && !TARGET_OS_IPHONE) */
#if defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
defined(__NetBSD__)
defined(__NetBSD__) || \
defined(__OpenBSD__)
# include <sys/sysctl.h>
# include <sys/filio.h>
# include <sys/wait.h>
# define UV__O_CLOEXEC O_CLOEXEC
# if defined(__FreeBSD__) && __FreeBSD__ >= 10
# define uv__accept4 accept4
# endif
# if defined(__NetBSD__)
# define uv__accept4(a, b, c, d) paccept((a), (b), (c), NULL, (d))
# endif
# if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
# if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \
defined(__NetBSD__) || defined(__OpenBSD__)
# define UV__SOCK_NONBLOCK SOCK_NONBLOCK
# define UV__SOCK_CLOEXEC SOCK_CLOEXEC
# endif
......@@ -87,6 +95,10 @@
#include <sys/ioctl.h>
#endif
#if defined(__linux__)
#include <sys/syscall.h>
#endif
static int uv__run_pending(uv_loop_t* loop);
/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
......@@ -509,6 +521,34 @@ skip:
}
/* close() on macos has the "interesting" quirk that it fails with EINTR
* without closing the file descriptor when a thread is in the cancel state.
* That's why libuv calls close$NOCANCEL() instead.
*
* glibc on linux has a similar issue: close() is a cancellation point and
* will unwind the thread when it's in the cancel state. Work around that
* by making the system call directly. Musl libc is unaffected.
*/
int uv__close_nocancel(int fd) {
#if defined(__APPLE__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
#if defined(__LP64__)
extern int close$NOCANCEL(int);
return close$NOCANCEL(fd);
#else
extern int close$NOCANCEL$UNIX2003(int);
return close$NOCANCEL$UNIX2003(fd);
#endif
#pragma GCC diagnostic pop
#elif defined(__linux__)
return syscall(SYS_close, fd);
#else
return close(fd);
#endif
}
int uv__close_nocheckstdio(int fd) {
int saved_errno;
int rc;
......@@ -516,7 +556,7 @@ int uv__close_nocheckstdio(int fd) {
assert(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */
saved_errno = errno;
rc = close(fd);
rc = uv__close_nocancel(fd);
if (rc == -1) {
rc = UV__ERR(errno);
if (rc == UV_EINTR || rc == UV__ERR(EINPROGRESS))
......@@ -551,7 +591,7 @@ int uv__nonblock_ioctl(int fd, int set) {
}
#if !defined(__CYGWIN__) && !defined(__MSYS__)
#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__HAIKU__)
int uv__cloexec_ioctl(int fd, int set) {
int r;
......@@ -668,16 +708,38 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
int uv_cwd(char* buffer, size_t* size) {
char scratch[1 + UV__PATH_MAX];
if (buffer == NULL || size == NULL)
return UV_EINVAL;
if (getcwd(buffer, *size) == NULL)
/* Try to read directly into the user's buffer first... */
if (getcwd(buffer, *size) != NULL)
goto fixup;
if (errno != ERANGE)
return UV__ERR(errno);
/* ...or into scratch space if the user's buffer is too small
* so we can report how much space to provide on the next try.
*/
if (getcwd(scratch, sizeof(scratch)) == NULL)
return UV__ERR(errno);
buffer = scratch;
fixup:
*size = strlen(buffer);
if (*size > 1 && buffer[*size - 1] == '/') {
buffer[*size-1] = '\0';
(*size)--;
*size -= 1;
buffer[*size] = '\0';
}
if (buffer == scratch) {
*size += 1;
return UV_ENOBUFS;
}
return 0;
......@@ -919,7 +981,7 @@ int uv_getrusage(uv_rusage_t* rusage) {
rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec;
rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec;
#if !defined(__MVS__)
#if !defined(__MVS__) && !defined(__HAIKU__)
rusage->ru_maxrss = usage.ru_maxrss;
rusage->ru_ixrss = usage.ru_ixrss;
rusage->ru_idrss = usage.ru_idrss;
......@@ -941,24 +1003,17 @@ int uv_getrusage(uv_rusage_t* rusage) {
int uv__open_cloexec(const char* path, int flags) {
int err;
#if defined(O_CLOEXEC)
int fd;
#if defined(UV__O_CLOEXEC)
static int no_cloexec;
if (!no_cloexec) {
fd = open(path, flags | UV__O_CLOEXEC);
if (fd != -1)
return fd;
if (errno != EINVAL)
return UV__ERR(errno);
fd = open(path, flags | O_CLOEXEC);
if (fd == -1)
return UV__ERR(errno);
/* O_CLOEXEC not supported. */
no_cloexec = 1;
}
#endif
return fd;
#else /* O_CLOEXEC */
int err;
int fd;
fd = open(path, flags);
if (fd == -1)
......@@ -971,6 +1026,7 @@ int uv__open_cloexec(const char* path, int flags) {
}
return fd;
#endif /* O_CLOEXEC */
}
......@@ -992,7 +1048,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
static int no_dup3;
if (!no_dup3) {
do
r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC);
r = uv__dup3(oldfd, newfd, O_CLOEXEC);
while (r == -1 && errno == EBUSY);
if (r != -1)
return r;
......@@ -1229,6 +1285,62 @@ int uv_translate_sys_error(int sys_errno) {
}
int uv_os_environ(uv_env_item_t** envitems, int* count) {
int i, j, cnt;
uv_env_item_t* envitem;
*envitems = NULL;
*count = 0;
for (i = 0; environ[i] != NULL; i++);
*envitems = uv__calloc(i, sizeof(**envitems));
if (envitems == NULL)
return UV_ENOMEM;
for (j = 0, cnt = 0; j < i; j++) {
char* buf;
char* ptr;
if (environ[j] == NULL)
break;
buf = uv__strdup(environ[j]);
if (buf == NULL)
goto fail;
ptr = strchr(buf, '=');
if (ptr == NULL) {
uv__free(buf);
continue;
}
*ptr = '\0';
envitem = &(*envitems)[cnt];
envitem->name = buf;
envitem->value = ptr + 1;
cnt++;
}
*count = cnt;
return 0;
fail:
for (i = 0; i < cnt; i++) {
envitem = &(*envitems)[cnt];
uv__free(envitem->name);
}
uv__free(*envitems);
*envitems = NULL;
*count = 0;
return UV_ENOMEM;
}
int uv_os_getenv(const char* name, char* buffer, size_t* size) {
char* var;
size_t len;
......@@ -1429,3 +1541,31 @@ int uv__getsockpeername(const uv_handle_t* handle,
*namelen = (int) socklen;
return 0;
}
int uv_gettimeofday(uv_timeval64_t* tv) {
struct timeval time;
if (tv == NULL)
return UV_EINVAL;
if (gettimeofday(&time, NULL) != 0)
return UV__ERR(errno);
tv->tv_sec = (int64_t) time.tv_sec;
tv->tv_usec = (int32_t) time.tv_usec;
return 0;
}
void uv_sleep(unsigned int msec) {
struct timespec timeout;
int rc;
timeout.tv_sec = msec / 1000;
timeout.tv_nsec = (msec % 1000) * 1000 * 1000;
do
rc = nanosleep(&timeout, &timeout);
while (rc == -1 && errno == EINTR);
assert(rc == 0);
}
......@@ -48,7 +48,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return UV_ENOSYS;
}
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
(void)cpu_infos;
(void)count;
uint64_t uv_get_constrained_memory(void) {
return 0; /* Memory constraints are unknown. */
}
......@@ -23,6 +23,7 @@
#include <dlfcn.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
......@@ -36,7 +37,6 @@
#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
static int (*dynamic_pthread_setname_np)(const char* name);
#if !TARGET_OS_IPHONE
static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
const char*,
......@@ -57,7 +57,6 @@ static CFStringRef* display_name_key;
static CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef);
static CFBundleRef (*pCFBundleGetMainBundle)(void);
static CFBundleRef hi_services_bundle;
static OSStatus (*pSetApplicationIsDaemon)(int);
static CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef);
static void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t,
void*);
......@@ -78,11 +77,9 @@ UV_DESTRUCTOR(static void uv__set_process_title_platform_fini(void)) {
void uv__set_process_title_platform_init(void) {
/* 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");
#if !TARGET_OS_IPHONE
OSStatus (*pSetApplicationIsDaemon)(int);
application_services_handle = dlopen("/System/Library/Frameworks/"
"ApplicationServices.framework/"
"Versions/A/ApplicationServices",
......@@ -169,6 +166,8 @@ void uv__set_process_title_platform_init(void) {
goto out;
}
/* Prevent crash when LaunchServices cannot be connected to. */
pSetApplicationIsDaemon(1);
return;
out:
......@@ -178,8 +177,10 @@ out:
void uv__set_process_title(const char* title) {
char namebuf[64 /* MAXTHREADNAMESIZE */];
#if !TARGET_OS_IPHONE
if (core_foundation_handle != NULL && pSetApplicationIsDaemon(1) != noErr) {
if (core_foundation_handle != NULL) {
CFTypeRef asn;
pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL);
pLSApplicationCheckIn(/* Magic value */ -2,
......@@ -190,9 +191,6 @@ void uv__set_process_title(const char* title) {
}
#endif /* !TARGET_OS_IPHONE */
if (dynamic_pthread_setname_np != NULL) {
char namebuf[64]; /* MAXTHREADNAMESIZE */
uv__strscpy(namebuf, title, sizeof(namebuf));
dynamic_pthread_setname_np(namebuf);
}
uv__strscpy(namebuf, title, sizeof(namebuf));
pthread_setname_np(namebuf);
}
......@@ -117,6 +117,11 @@ uint64_t uv_get_total_memory(void) {
}
uint64_t uv_get_constrained_memory(void) {
return 0; /* Memory constraints are unknown. */
}
void uv_loadavg(double avg[3]) {
struct loadavg info;
size_t size = sizeof(info);
......@@ -218,14 +223,3 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return 0;
}
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
int i;
for (i = 0; i < count; i++) {
uv__free(cpu_infos[i].model);
}
uv__free(cpu_infos);
}
......@@ -137,6 +137,11 @@ uint64_t uv_get_total_memory(void) {
}
uint64_t uv_get_constrained_memory(void) {
return 0; /* Memory constraints are unknown. */
}
void uv_loadavg(double avg[3]) {
struct loadavg info;
size_t size = sizeof(info);
......@@ -283,14 +288,3 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
uv__free(cp_times);
return 0;
}
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
int i;
for (i = 0; i < count; i++) {
uv__free(cpu_infos[i].model);
}
uv__free(cpu_infos);
}
This diff is collapsed.
......@@ -21,9 +21,10 @@
#include "uv.h"
#include "internal.h"
#if TARGET_OS_IPHONE
#if TARGET_OS_IPHONE || MAC_OS_X_VERSION_MAX_ALLOWED < 1070
/* iOS (currently) doesn't provide the FSEvents-API (nor CoreServices) */
/* macOS prior to 10.7 doesn't provide the full FSEvents API so use kqueue */
int uv__fsevents_init(uv_fs_event_t* handle) {
return 0;
......@@ -262,10 +263,12 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
if (len < handle->realpath_len)
continue;
/* Make sure that realpath actually named a directory,
* (unless watching root, which alone keeps a trailing slash on the realpath)
* or that we matched the whole string */
if (handle->realpath_len != len &&
handle->realpath_len > 1 &&
path[handle->realpath_len] != '/')
/* Make sure that realpath actually named a directory,
* or that we matched the whole string */
continue;
if (memcmp(path, handle->realpath, handle->realpath_len) != 0)
......
......@@ -55,19 +55,155 @@
#include <strings.h>
#include <sys/vnode.h>
#include <as400_protos.h>
typedef struct {
int bytes_available;
int bytes_returned;
char current_date_and_time[8];
char system_name[8];
char elapsed_time[6];
char restricted_state_flag;
char reserved;
int percent_processing_unit_used;
int jobs_in_system;
int percent_permanent_addresses;
int percent_temporary_addresses;
int system_asp;
int percent_system_asp_used;
int total_auxiliary_storage;
int current_unprotected_storage_used;
int maximum_unprotected_storage_used;
int percent_db_capability;
int main_storage_size;
int number_of_partitions;
int partition_identifier;
int reserved1;
int current_processing_capacity;
char processor_sharing_attribute;
char reserved2[3];
int number_of_processors;
int active_jobs_in_system;
int active_threads_in_system;
int maximum_jobs_in_system;
int percent_temporary_256mb_segments_used;
int percent_temporary_4gb_segments_used;
int percent_permanent_256mb_segments_used;
int percent_permanent_4gb_segments_used;
int percent_current_interactive_performance;
int percent_uncapped_cpu_capacity_used;
int percent_shared_processor_pool_used;
long main_storage_size_long;
} SSTS0200;
static int get_ibmi_system_status(SSTS0200* rcvr) {
/* rcvrlen is input parameter 2 to QWCRSSTS */
unsigned int rcvrlen = sizeof(*rcvr);
/* format is input parameter 3 to QWCRSSTS ("SSTS0200" in EBCDIC) */
unsigned char format[] = {0xE2, 0xE2, 0xE3, 0xE2, 0xF0, 0xF2, 0xF0, 0xF0};
/* reset_status is input parameter 4 to QWCRSSTS ("*NO " in EBCDIC) */
unsigned char reset_status[] = {
0x5C, 0xD5, 0xD6, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
};
/* errcode is input parameter 5 to QWCRSSTS */
struct _errcode {
int bytes_provided;
int bytes_available;
char msgid[7];
} errcode;
/* qwcrssts_pointer is the 16-byte tagged system pointer to QWCRSSTS */
ILEpointer __attribute__((aligned(16))) qwcrssts_pointer;
/* qwcrssts_argv is the array of argument pointers to QWCRSSTS */
void* qwcrssts_argv[6];
/* Set the IBM i pointer to the QSYS/QWCRSSTS *PGM object */
int rc = _RSLOBJ2(&qwcrssts_pointer, RSLOBJ_TS_PGM, "QWCRSSTS", "QSYS");
if (rc != 0)
return rc;
/* initialize the QWCRSSTS returned info structure */
memset(rcvr, 0, sizeof(*rcvr));
/* initialize the QWCRSSTS error code structure */
memset(&errcode, 0, sizeof(errcode));
errcode.bytes_provided = sizeof(errcode);
/* initialize the array of argument pointers for the QWCRSSTS API */
qwcrssts_argv[0] = rcvr;
qwcrssts_argv[1] = &rcvrlen;
qwcrssts_argv[2] = &format;
qwcrssts_argv[3] = &reset_status;
qwcrssts_argv[4] = &errcode;
qwcrssts_argv[5] = NULL;
/* Call the IBM i QWCRSSTS API from PASE */
rc = _PGMCALL(&qwcrssts_pointer, (void**)&qwcrssts_argv, 0);
return rc;
}
uint64_t uv_get_free_memory(void) {
return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES);
SSTS0200 rcvr;
if (get_ibmi_system_status(&rcvr))
return 0;
/* The amount of main storage, in kilobytes, in the system. */
uint64_t main_storage_size = rcvr.main_storage_size;
/* The current amount of storage in use for temporary objects.
* in millions (M) of bytes.
*/
uint64_t current_unprotected_storage_used =
rcvr.current_unprotected_storage_used * 1024ULL;
uint64_t free_storage_size =
(main_storage_size - current_unprotected_storage_used) * 1024ULL;
return free_storage_size < 0 ? 0 : free_storage_size;
}
uint64_t uv_get_total_memory(void) {
return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES);
SSTS0200 rcvr;
if (get_ibmi_system_status(&rcvr))
return 0;
return (uint64_t)rcvr.main_storage_size * 1024ULL;
}
uint64_t uv_get_constrained_memory(void) {
return 0; /* Memory constraints are unknown. */
}
void uv_loadavg(double avg[3]) {
SSTS0200 rcvr;
if (get_ibmi_system_status(&rcvr)) {
avg[0] = avg[1] = avg[2] = 0;
return;
}
/* The average (in tenths) of the elapsed time during which the processing
* units were in use. For example, a value of 411 in binary would be 41.1%.
* This percentage could be greater than 100% for an uncapped partition.
*/
double processing_unit_used_percent =
rcvr.percent_processing_unit_used / 1000.0;
avg[0] = avg[1] = avg[2] = processing_unit_used_percent;
}
......@@ -110,4 +246,4 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
*count = numcpus;
return 0;
}
\ No newline at end of file
}
......@@ -25,6 +25,7 @@
#include "uv-common.h"
#include <assert.h>
#include <limits.h> /* _POSIX_PATH_MAX, PATH_MAX */
#include <stdlib.h> /* abort */
#include <string.h> /* strrchr */
#include <fcntl.h> /* O_CLOEXEC, may be */
......@@ -60,6 +61,14 @@
# include <AvailabilityMacros.h>
#endif
#if defined(_POSIX_PATH_MAX)
# define UV__PATH_MAX _POSIX_PATH_MAX
#elif defined(PATH_MAX)
# define UV__PATH_MAX PATH_MAX
#else
# define UV__PATH_MAX 8192
#endif
#if defined(__ANDROID__)
int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
# ifdef pthread_sigmask
......@@ -183,6 +192,7 @@ int uv__nonblock_ioctl(int fd, int set);
int uv__nonblock_fcntl(int fd, int set);
int uv__close(int fd); /* preserves errno */
int uv__close_nocheckstdio(int fd);
int uv__close_nocancel(int fd);
int uv__socket(int domain, int type, int protocol);
ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags);
void uv__make_close_pending(uv_handle_t* handle);
......@@ -260,6 +270,12 @@ uv_handle_type uv__handle_type(int fd);
FILE* uv__open_file(const char* path);
int uv__getpwuid_r(uv_passwd_t* pwd);
/* random */
int uv__random_devurandom(void* buf, size_t buflen);
int uv__random_getrandom(void* buf, size_t buflen);
int uv__random_getentropy(void* buf, size_t buflen);
int uv__random_readpath(const char* path, void* buf, size_t buflen);
int uv__random_sysctl(void* buf, size_t buflen);
#if defined(__APPLE__)
int uv___stream_fd(const uv_stream_t* handle);
......
......@@ -59,7 +59,7 @@ int uv__kqueue_init(uv_loop_t* loop) {
}
#if defined(__APPLE__)
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
static int uv__has_forked_with_cfrunloop;
#endif
......@@ -70,7 +70,7 @@ int uv__io_fork(uv_loop_t* loop) {
if (err)
return err;
#if defined(__APPLE__)
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
if (loop->cf_state != NULL) {
/* We cannot start another CFRunloop and/or thread in the child
process; CF aborts if you try or if you try to touch the thread
......@@ -86,7 +86,7 @@ int uv__io_fork(uv_loop_t* loop) {
uv__free(loop->cf_state);
loop->cf_state = NULL;
}
#endif
#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
return err;
}
......@@ -454,25 +454,44 @@ int uv_fs_event_start(uv_fs_event_t* handle,
const char* path,
unsigned int flags) {
int fd;
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
struct stat statbuf;
#endif
if (uv__is_active(handle))
return UV_EINVAL;
#if defined(__APPLE__)
handle->cb = cb;
handle->path = uv__strdup(path);
if (handle->path == NULL)
return UV_ENOMEM;
/* TODO open asynchronously - but how do we report back errors? */
fd = open(handle->path, O_RDONLY);
if (fd == -1) {
uv__free(handle->path);
handle->path = NULL;
return UV__ERR(errno);
}
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
/* Nullify field to perform checks later */
handle->cf_cb = NULL;
handle->realpath = NULL;
handle->realpath_len = 0;
handle->cf_flags = flags;
if (fstat(fd, &statbuf))
goto fallback;
/* FSEvents works only with directories */
if (!(statbuf.st_mode & S_IFDIR))
goto fallback;
if (!uv__has_forked_with_cfrunloop) {
int r;
/* The fallback fd is not used */
/* The fallback fd is no longer needed */
uv__close_nocheckstdio(fd);
handle->event_watcher.fd = -1;
handle->path = uv__strdup(path);
if (handle->path == NULL)
return UV_ENOMEM;
handle->cb = cb;
r = uv__fsevents_init(handle);
if (r == 0) {
uv__handle_start(handle);
......@@ -482,20 +501,9 @@ int uv_fs_event_start(uv_fs_event_t* handle,
}
return r;
}
#endif /* defined(__APPLE__) */
/* TODO open asynchronously - but how do we report back errors? */
fd = open(path, O_RDONLY);
if (fd == -1)
return UV__ERR(errno);
handle->path = uv__strdup(path);
if (handle->path == NULL) {
uv__close_nocheckstdio(fd);
return UV_ENOMEM;
}
fallback:
#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
handle->cb = cb;
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
......@@ -513,8 +521,8 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
uv__handle_stop(handle);
#if defined(__APPLE__)
if (!uv__has_forked_with_cfrunloop)
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
if (!uv__has_forked_with_cfrunloop && handle->cf_cb != NULL)
r = uv__fsevents_close(handle);
#endif
......
......@@ -26,6 +26,7 @@
#include "uv.h"
#include "internal.h"
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -79,16 +80,25 @@ static int read_times(FILE* statfile_fp,
unsigned int numcpus,
uv_cpu_info_t* ci);
static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci);
static unsigned long read_cpufreq(unsigned int cpunum);
static uint64_t read_cpufreq(unsigned int cpunum);
int uv__platform_loop_init(uv_loop_t* loop) {
int fd;
fd = epoll_create1(EPOLL_CLOEXEC);
/* It was reported that EPOLL_CLOEXEC is not defined on Android API < 21,
* a.k.a. Lollipop. Since EPOLL_CLOEXEC is an alias for O_CLOEXEC on all
* architectures, we just use that instead.
*/
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
fd = -1;
errno = ENOSYS;
#else
fd = epoll_create1(O_CLOEXEC);
#endif
/* epoll_create1() can fail either because it's not implemented (old kernel)
* or because it doesn't understand the EPOLL_CLOEXEC flag.
* or because it doesn't understand the O_CLOEXEC flag.
*/
if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
fd = epoll_create(256);
......@@ -198,6 +208,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
* that being the largest value I have seen in the wild (and only once.)
*/
static const int max_safe_timeout = 1789569;
static int no_epoll_pwait;
static int no_epoll_wait;
struct epoll_event events[1024];
struct epoll_event* pe;
struct epoll_event e;
......@@ -205,7 +217,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
QUEUE* q;
uv__io_t* w;
sigset_t sigset;
sigset_t* psigset;
uint64_t sigmask;
uint64_t base;
int have_signals;
int nevents;
......@@ -257,11 +269,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
w->events = w->pevents;
}
psigset = NULL;
sigmask = 0;
if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
sigemptyset(&sigset);
sigaddset(&sigset, SIGPROF);
psigset = &sigset;
sigmask |= 1 << (SIGPROF - 1);
}
assert(timeout >= -1);
......@@ -276,11 +288,35 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
timeout = max_safe_timeout;
nfds = epoll_pwait(loop->backend_fd,
events,
ARRAY_SIZE(events),
timeout,
psigset);
if (sigmask != 0 && no_epoll_pwait != 0)
if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
abort();
if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
nfds = -1;
errno = ENOSYS;
#else
nfds = epoll_pwait(loop->backend_fd,
events,
ARRAY_SIZE(events),
timeout,
&sigset);
#endif
if (nfds == -1 && errno == ENOSYS)
no_epoll_pwait = 1;
} else {
nfds = epoll_wait(loop->backend_fd,
events,
ARRAY_SIZE(events),
timeout);
if (nfds == -1 && errno == ENOSYS)
no_epoll_wait = 1;
}
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
......@@ -301,6 +337,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();
......@@ -715,20 +757,20 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
static int read_times(FILE* statfile_fp,
unsigned int numcpus,
uv_cpu_info_t* ci) {
unsigned long clock_ticks;
struct uv_cpu_times_s ts;
unsigned long user;
unsigned long nice;
unsigned long sys;
unsigned long idle;
unsigned long dummy;
unsigned long irq;
unsigned int num;
unsigned int len;
uint64_t clock_ticks;
uint64_t user;
uint64_t nice;
uint64_t sys;
uint64_t idle;
uint64_t dummy;
uint64_t irq;
uint64_t num;
uint64_t len;
char buf[1024];
clock_ticks = sysconf(_SC_CLK_TCK);
assert(clock_ticks != (unsigned long) -1);
assert(clock_ticks != (uint64_t) -1);
assert(clock_ticks != 0);
rewind(statfile_fp);
......@@ -761,7 +803,8 @@ static int read_times(FILE* statfile_fp,
* fields, they're not allowed in C89 mode.
*/
if (6 != sscanf(buf + len,
"%lu %lu %lu %lu %lu %lu",
"%" PRIu64 " %" PRIu64 " %" PRIu64
"%" PRIu64 " %" PRIu64 " %" PRIu64,
&user,
&nice,
&sys,
......@@ -783,8 +826,8 @@ static int read_times(FILE* statfile_fp,
}
static unsigned long read_cpufreq(unsigned int cpunum) {
unsigned long val;
static uint64_t read_cpufreq(unsigned int cpunum) {
uint64_t val;
char buf[1024];
FILE* fp;
......@@ -797,7 +840,7 @@ static unsigned long read_cpufreq(unsigned int cpunum) {
if (fp == NULL)
return 0;
if (fscanf(fp, "%lu", &val) != 1)
if (fscanf(fp, "%" PRIu64, &val) != 1)
val = 0;
fclose(fp);
......@@ -806,16 +849,6 @@ static unsigned long read_cpufreq(unsigned int cpunum) {
}
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
int i;
for (i = 0; i < count; i++) {
uv__free(cpu_infos[i].model);
}
uv__free(cpu_infos);
}
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
return 1;
......@@ -860,7 +893,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return 0;
}
*addresses = uv__malloc(*count * sizeof(**addresses));
/* Make sure the memory is initiallized to zero using calloc() */
*addresses = uv__calloc(*count, sizeof(**addresses));
if (!(*addresses)) {
freeifaddrs(addrs);
return UV_ENOMEM;
......@@ -899,11 +933,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
address = *addresses;
for (i = 0; i < (*count); i++) {
if (strcmp(address->name, ent->ifa_name) == 0) {
size_t namelen = strlen(ent->ifa_name);
/* Alias interface share the same physical address */
if (strncmp(address->name, ent->ifa_name, namelen) == 0 &&
(address->name[namelen] == 0 || address->name[namelen] == ':')) {
sll = (struct sockaddr_ll*)ent->ifa_addr;
memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr));
} else {
memset(address->phys_addr, 0, sizeof(address->phys_addr));
}
address++;
}
......@@ -933,3 +968,114 @@ void uv__set_process_title(const char* title) {
prctl(PR_SET_NAME, title); /* Only copies first 16 characters. */
#endif
}
static uint64_t uv__read_proc_meminfo(const char* what) {
uint64_t rc;
ssize_t n;
char* p;
int fd;
char buf[4096]; /* Large enough to hold all of /proc/meminfo. */
rc = 0;
fd = uv__open_cloexec("/proc/meminfo", O_RDONLY);
if (fd == -1)
return 0;
n = read(fd, buf, sizeof(buf) - 1);
if (n <= 0)
goto out;
buf[n] = '\0';
p = strstr(buf, what);
if (p == NULL)
goto out;
p += strlen(what);
if (1 != sscanf(p, "%" PRIu64 " kB", &rc))
goto out;
rc *= 1024;
out:
if (uv__close_nocheckstdio(fd))
abort();
return rc;
}
uint64_t uv_get_free_memory(void) {
struct sysinfo info;
uint64_t rc;
rc = uv__read_proc_meminfo("MemFree:");
if (rc != 0)
return rc;
if (0 == sysinfo(&info))
return (uint64_t) info.freeram * info.mem_unit;
return 0;
}
uint64_t uv_get_total_memory(void) {
struct sysinfo info;
uint64_t rc;
rc = uv__read_proc_meminfo("MemTotal:");
if (rc != 0)
return rc;
if (0 == sysinfo(&info))
return (uint64_t) info.totalram * info.mem_unit;
return 0;
}
static uint64_t uv__read_cgroups_uint64(const char* cgroup, const char* param) {
char filename[256];
uint64_t rc;
int fd;
ssize_t n;
char buf[32]; /* Large enough to hold an encoded uint64_t. */
snprintf(filename, 256, "/sys/fs/cgroup/%s/%s", cgroup, param);
rc = 0;
fd = uv__open_cloexec(filename, O_RDONLY);
if (fd < 0)
return 0;
n = read(fd, buf, sizeof(buf) - 1);
if (n > 0) {
buf[n] = '\0';
sscanf(buf, "%" PRIu64, &rc);
}
if (uv__close_nocheckstdio(fd))
abort();
return rc;
}
uint64_t uv_get_constrained_memory(void) {
/*
* This might return 0 if there was a problem getting the memory limit from
* cgroups. This is OK because a return value of 0 signifies that the memory
* limit is unknown.
*/
return uv__read_cgroups_uint64("memory", "memory.limit_in_bytes");
}
......@@ -203,6 +203,22 @@
# endif
#endif /* __NR_statx */
#ifndef __NR_getrandom
# if defined(__x86_64__)
# define __NR_getrandom 318
# elif defined(__i386__)
# define __NR_getrandom 355
# elif defined(__aarch64__)
# define __NR_getrandom 384
# elif defined(__arm__)
# define __NR_getrandom (UV_SYSCALL_BASE + 384)
# elif defined(__ppc__)
# define __NR_getrandom 359
# elif defined(__s390__)
# define __NR_getrandom 349
# endif
#endif /* __NR_getrandom */
int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
#if defined(__i386__)
unsigned long args[4];
......@@ -358,9 +374,21 @@ int uv__statx(int dirfd,
int flags,
unsigned int mask,
struct uv__statx* statxbuf) {
#if defined(__NR_statx)
/* __NR_statx make Android box killed by SIGSYS.
* That looks like a seccomp2 sandbox filter rejecting the system call.
*/
#if defined(__NR_statx) && !defined(__ANDROID__)
return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf);
#else
return errno = ENOSYS, -1;
#endif
}
ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags) {
#if defined(__NR_getrandom)
return syscall(__NR_getrandom, buf, buflen, flags);
#else
return errno = ENOSYS, -1;
#endif
}
......@@ -148,5 +148,6 @@ int uv__statx(int dirfd,
int flags,
unsigned int mask,
struct uv__statx* statxbuf);
ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags);
#endif /* UV_LINUX_SYSCALL_H_ */
......@@ -126,6 +126,11 @@ uint64_t uv_get_total_memory(void) {
}
uint64_t uv_get_constrained_memory(void) {
return 0; /* Memory constraints are unknown. */
}
int uv_resident_set_memory(size_t* rss) {
kvm_t *kd = NULL;
struct kinfo_proc2 *kinfo = NULL;
......@@ -230,13 +235,25 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return 0;
}
int uv__random_sysctl(void* buf, size_t len) {
static int name[] = {CTL_KERN, KERN_ARND};
size_t count, req;
unsigned char* p;
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
int i;
p = buf;
while (len) {
req = len < 32 ? len : 32;
count = req;
for (i = 0; i < count; i++) {
uv__free(cpu_infos[i].model);
if (sysctl(name, ARRAY_SIZE(name), p, &count, NULL, 0) == -1)
return UV__ERR(errno);
if (count != req)
return UV_EIO; /* Can't happen. */
p += count;
len -= count;
}
uv__free(cpu_infos);
return 0;
}
......@@ -136,6 +136,11 @@ uint64_t uv_get_total_memory(void) {
}
uint64_t uv_get_constrained_memory(void) {
return 0; /* Memory constraints are unknown. */
}
int uv_resident_set_memory(size_t* rss) {
struct kinfo_proc kinfo;
size_t page_size = getpagesize();
......@@ -181,14 +186,14 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
int numcpus = 1;
int which[] = {CTL_HW,HW_MODEL,0};
size_t size;
int i;
int i, j;
uv_cpu_info_t* cpu_info;
size = sizeof(model);
if (sysctl(which, 2, &model, &size, NULL, 0))
return UV__ERR(errno);
which[1] = HW_NCPU;
which[1] = HW_NCPUONLINE;
size = sizeof(numcpus);
if (sysctl(which, 2, &numcpus, &size, NULL, 0))
return UV__ERR(errno);
......@@ -197,14 +202,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
if (!(*cpu_infos))
return UV_ENOMEM;
i = 0;
*count = numcpus;
which[1] = HW_CPUSPEED;
size = sizeof(cpuspeed);
if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) {
uv__free(*cpu_infos);
return UV__ERR(errno);
}
if (sysctl(which, 2, &cpuspeed, &size, NULL, 0))
goto error;
size = sizeof(info);
which[0] = CTL_KERN;
......@@ -212,10 +216,8 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
for (i = 0; i < numcpus; i++) {
which[2] = i;
size = sizeof(info);
if (sysctl(which, 3, &info, &size, NULL, 0)) {
uv__free(*cpu_infos);
return UV__ERR(errno);
}
if (sysctl(which, 3, &info, &size, NULL, 0))
goto error;
cpu_info = &(*cpu_infos)[i];
......@@ -230,15 +232,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
return 0;
}
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
int i;
for (i = 0; i < count; i++) {
uv__free(cpu_infos[i].model);
}
error:
*count = 0;
for (j = 0; j < i; j++)
uv__free((*cpu_infos)[j].model);
uv__free(cpu_infos);
uv__free(*cpu_infos);
*cpu_infos = NULL;
return UV__ERR(errno);
}
......@@ -23,11 +23,11 @@
#include "os390-syscalls.h"
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
#include <search.h>
#include <termios.h>
#include <sys/msg.h>
#define CW_INTRPT 1
#define CW_CONDVAR 32
#pragma linkage(BPX4CTW, OS)
......@@ -350,27 +350,34 @@ int nanosleep(const struct timespec* req, struct timespec* rem) {
unsigned secrem;
unsigned nanorem;
int rv;
int rc;
int err;
int rsn;
nano = (int)req->tv_nsec;
seconds = req->tv_sec;
events = CW_CONDVAR;
events = CW_CONDVAR | CW_INTRPT;
secrem = 0;
nanorem = 0;
#if defined(_LP64)
BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn);
BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &err, &rsn);
#else
BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn);
BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &err, &rsn);
#endif
assert(rv == -1 && errno == EAGAIN);
/* Don't clobber errno unless BPX1CTW/BPX4CTW errored.
* Don't leak EAGAIN, that just means the timeout expired.
*/
if (rv == -1)
if (err != EAGAIN)
errno = err;
if(rem != NULL) {
if (rem != NULL && (rv == 0 || err == EINTR || err == EAGAIN)) {
rem->tv_nsec = nanorem;
rem->tv_sec = secrem;
}
return 0;
return rv;
}
......
......@@ -356,6 +356,11 @@ uint64_t uv_get_total_memory(void) {
}
uint64_t uv_get_constrained_memory(void) {
return 0; /* Memory constraints are unknown. */
}
int uv_resident_set_memory(size_t* rss) {
char* ascb;
char* rax;
......@@ -428,13 +433,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
for (int i = 0; i < count; ++i)
uv__free(cpu_infos[i].model);
uv__free(cpu_infos);
}
static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
int* count) {
uv_interface_address_t* address;
......
......@@ -261,7 +261,7 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
addrlen = strlen(sa.sun_path);
if (addrlen >= *size) {
if ((size_t)addrlen >= *size) {
*size = addrlen + 1;
return UV_ENOBUFS;
}
......
......@@ -249,7 +249,7 @@ static int uv__process_open_stream(uv_stdio_container_t* container,
static void uv__process_close_stream(uv_stdio_container_t* container) {
if (!(container->flags & UV_CREATE_PIPE)) return;
uv__stream_close((uv_stream_t*)container->data.stream);
uv__stream_close(container->data.stream);
}
......@@ -315,7 +315,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR);
close_fd = use_fd;
if (use_fd == -1) {
if (use_fd < 0) {
uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
......@@ -385,6 +385,11 @@ static void uv__process_child_init(const uv_process_options_t* options,
if (n == SIGKILL || n == SIGSTOP)
continue; /* Can't be changed. */
#if defined(__HAIKU__)
if (n == SIGKILLTHR)
continue; /* Can't be changed. */
#endif
if (SIG_ERR != signal(n, SIG_DFL))
continue;
......@@ -431,6 +436,8 @@ int uv_spawn(uv_loop_t* loop,
UV_PROCESS_SETGID |
UV_PROCESS_SETUID |
UV_PROCESS_WINDOWS_HIDE |
UV_PROCESS_WINDOWS_HIDE_CONSOLE |
UV_PROCESS_WINDOWS_HIDE_GUI |
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
......
......@@ -375,7 +375,7 @@ static int uv__signal_start(uv_signal_t* handle,
/* Short circuit: if the signal watcher is already watching {signum} don't
* go through the process of deregistering and registering the handler.
* Additionally, this avoids pending signals getting lost in the small time
* Additionally, this avoids pending signals getting lost in the small
* time frame that handle->signum == 0.
*/
if (signum == handle->signum) {
......@@ -477,9 +477,11 @@ static void uv__signal_event(uv_loop_t* loop,
* yet dispatched, the uv__finish_close was deferred. Make close pending
* now if this has happened.
*/
if ((handle->flags & UV_HANDLE_CLOSING) &&
(handle->caught_signals == handle->dispatched_signals)) {
uv__make_close_pending((uv_handle_t*) handle);
if (handle->caught_signals == handle->dispatched_signals) {
if (handle->signum == 0)
uv__handle_stop(handle);
if (handle->flags & UV_HANDLE_CLOSING)
uv__make_close_pending((uv_handle_t*) handle);
}
}
......@@ -569,5 +571,6 @@ static void uv__signal_stop(uv_signal_t* handle) {
uv__signal_unlock_and_unblock(&saved_sigmask);
handle->signum = 0;
uv__handle_stop(handle);
if (handle->caught_signals == handle->dispatched_signals)
uv__handle_stop(handle);
}
......@@ -1000,12 +1000,12 @@ uv_handle_type uv__handle_type(int fd) {
static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
stream->flags |= UV_HANDLE_READ_EOF;
stream->flags &= ~UV_HANDLE_READING;
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
if (!uv__io_active(&stream->io_watcher, POLLOUT))
uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream);
stream->read_cb(stream, UV_EOF, buf);
stream->flags &= ~UV_HANDLE_READING;
}
......@@ -1180,6 +1180,10 @@ static void uv__read(uv_stream_t* stream) {
} else if (errno == ECONNRESET && stream->type == UV_NAMED_PIPE) {
uv__stream_eof(stream, &buf);
return;
#elif defined(_AIX)
} else if (errno == ECONNRESET && (stream->flags & UV_DISCONNECT)) {
uv__stream_eof(stream, &buf);
return;
#endif
} else {
/* Error. User should call uv_close(). */
......@@ -1403,7 +1407,7 @@ int uv_write2(uv_write_t* req,
return UV_EBADF;
if (!(stream->flags & UV_HANDLE_WRITABLE))
return -EPIPE;
return UV_EPIPE;
if (send_handle) {
if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc)
......@@ -1541,7 +1545,7 @@ int uv_try_write(uv_stream_t* stream,
}
if (written == 0 && req_size != 0)
return UV_EAGAIN;
return req.error < 0 ? req.error : UV_EAGAIN;
else
return written;
}
......@@ -1557,7 +1561,7 @@ int uv_read_start(uv_stream_t* stream,
return UV_EINVAL;
if (!(stream->flags & UV_HANDLE_READABLE))
return -ENOTCONN;
return UV_ENOTCONN;
/* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just
* expresses the desired state of the user.
......
......@@ -380,6 +380,11 @@ uint64_t uv_get_total_memory(void) {
}
uint64_t uv_get_constrained_memory(void) {
return 0; /* Memory constraints are unknown. */
}
void uv_loadavg(double avg[3]) {
(void) getloadavg(avg, 3);
}
......@@ -691,16 +696,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
int i;
for (i = 0; i < count; i++) {
uv__free(cpu_infos[i].model);
}
uv__free(cpu_infos);
}
#ifdef SUNOS_NO_IFADDRS
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
*count = 0;
......
......@@ -308,6 +308,23 @@ int uv_tcp_getpeername(const uv_tcp_t* handle,
}
int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
int fd;
struct linger l = { 1, 0 };
/* Disallow setting SO_LINGER to zero due to some platform inconsistencies */
if (handle->flags & UV_HANDLE_SHUTTING)
return UV_EINVAL;
fd = uv__stream_fd(handle);
if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)))
return UV__ERR(errno);
uv_close((uv_handle_t*) handle, close_cb);
return 0;
}
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
static int single_accept = -1;
unsigned long flags;
......
......@@ -37,7 +37,7 @@
#include <sys/sem.h>
#endif
#ifdef __GLIBC__
#if defined(__GLIBC__) && !defined(__UCLIBC__)
#include <gnu/libc-version.h> /* gnu_get_libc_version() */
#endif
......@@ -178,8 +178,21 @@ static size_t thread_stack_size(void) {
if (lim.rlim_cur != RLIM_INFINITY) {
/* pthread_attr_setstacksize() expects page-aligned values. */
lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
if (lim.rlim_cur >= PTHREAD_STACK_MIN)
return lim.rlim_cur;
/* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is
* too small to safely receive signals on.
*
* Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has
* the largest MINSIGSTKSZ of the architectures that musl supports) so
* let's use that as a lower bound.
*
* We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ
* is between 28 and 133 KB when compiling against glibc, depending
* on the architecture.
*/
if (lim.rlim_cur >= 8192)
if (lim.rlim_cur >= PTHREAD_STACK_MIN)
return lim.rlim_cur;
}
#endif
......@@ -209,6 +222,12 @@ int uv_thread_create_ex(uv_thread_t* tid,
size_t pagesize;
size_t stack_size;
/* Used to squelch a -Wcast-function-type warning. */
union {
void (*in)(void*);
void* (*out)(void*);
} f;
stack_size =
params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
......@@ -219,8 +238,10 @@ int uv_thread_create_ex(uv_thread_t* tid,
pagesize = (size_t)getpagesize();
/* Round up to the nearest page boundary. */
stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
#ifdef PTHREAD_STACK_MIN
if (stack_size < PTHREAD_STACK_MIN)
stack_size = PTHREAD_STACK_MIN;
#endif
}
if (stack_size > 0) {
......@@ -233,7 +254,8 @@ int uv_thread_create_ex(uv_thread_t* tid,
abort();
}
err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg);
f.in = entry;
err = pthread_create(tid, attr, f.out, arg);
if (attr != NULL)
pthread_attr_destroy(attr);
......@@ -459,7 +481,7 @@ int uv_sem_trywait(uv_sem_t* sem) {
#else /* !(defined(__APPLE__) && defined(__MACH__)) */
#ifdef __GLIBC__
#if defined(__GLIBC__) && !defined(__UCLIBC__)
/* Hack around https://sourceware.org/bugzilla/show_bug.cgi?id=12674
* by providing a custom implementation for glibc < 2.21 in terms of other
......@@ -495,7 +517,8 @@ typedef struct uv_semaphore_s {
unsigned int value;
} uv_semaphore_t;
#if defined(__GLIBC__) || platform_needs_custom_semaphore
#if (defined(__GLIBC__) && !defined(__UCLIBC__)) || \
platform_needs_custom_semaphore
STATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*));
#endif
......@@ -624,7 +647,7 @@ static int uv__sem_trywait(uv_sem_t* sem) {
}
int uv_sem_init(uv_sem_t* sem, unsigned int value) {
#ifdef __GLIBC__
#if defined(__GLIBC__) && !defined(__UCLIBC__)
uv_once(&glibc_version_check_once, glibc_version_check);
#endif
......
......@@ -365,3 +365,10 @@ int uv_tty_reset_mode(void) {
return err;
}
void uv_tty_set_vterm_state(uv_tty_vtermstate_t state) {
}
int uv_tty_get_vterm_state(uv_tty_vtermstate_t* state) {
return UV_ENOTSUP;
}
......@@ -30,6 +30,7 @@
#if defined(__MVS__)
#include <xti.h>
#endif
#include <sys/un.h>
#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP)
# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
......@@ -164,9 +165,6 @@ static void uv__udp_recvmsg(uv_udp_t* handle) {
*/
count = 32;
memset(&h, 0, sizeof(h));
h.msg_name = &peer;
do {
buf = uv_buf_init(NULL, 0);
handle->alloc_cb((uv_handle_t*) handle, 64 * 1024, &buf);
......@@ -176,6 +174,9 @@ static void uv__udp_recvmsg(uv_udp_t* handle) {
}
assert(buf.base != NULL);
memset(&h, 0, sizeof(h));
memset(&peer, 0, sizeof(peer));
h.msg_name = &peer;
h.msg_namelen = sizeof(peer);
h.msg_iov = (void*) &buf;
h.msg_iovlen = 1;
......@@ -192,17 +193,11 @@ static void uv__udp_recvmsg(uv_udp_t* handle) {
handle->recv_cb(handle, UV__ERR(errno), &buf, NULL, 0);
}
else {
const struct sockaddr *addr;
if (h.msg_namelen == 0)
addr = NULL;
else
addr = (const struct sockaddr*) &peer;
flags = 0;
if (h.msg_flags & MSG_TRUNC)
flags |= UV_UDP_PARTIAL;
handle->recv_cb(handle, nread, &buf, addr, flags);
handle->recv_cb(handle, nread, &buf, (const struct sockaddr*) &peer, flags);
}
}
/* recv_cb callback may decide to pause or close the handle */
......@@ -232,8 +227,16 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
h.msg_namelen = 0;
} else {
h.msg_name = &req->addr;
h.msg_namelen = req->addr.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
if (req->addr.ss_family == AF_INET6)
h.msg_namelen = sizeof(struct sockaddr_in6);
else if (req->addr.ss_family == AF_INET)
h.msg_namelen = sizeof(struct sockaddr_in);
else if (req->addr.ss_family == AF_UNIX)
h.msg_namelen = sizeof(struct sockaddr_un);
else {
assert(0 && "unsupported address family");
abort();
}
}
h.msg_iov = (struct iovec*) req->bufs;
h.msg_iovlen = req->nbufs;
......@@ -268,16 +271,30 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
* are different from the BSDs: it _shares_ the port rather than steal it
* from the current listener. While useful, it's not something we can emulate
* on other platforms so we don't enable it.
*
* zOS does not support getsockname with SO_REUSEPORT option when using
* AF_UNIX.
*/
static int uv__set_reuse(int fd) {
int yes;
#if defined(SO_REUSEPORT) && !defined(__linux__)
yes = 1;
#if defined(SO_REUSEPORT) && defined(__MVS__)
struct sockaddr_in sockfd;
unsigned int sockfd_len = sizeof(sockfd);
if (getsockname(fd, (struct sockaddr*) &sockfd, &sockfd_len) == -1)
return UV__ERR(errno);
if (sockfd.sin_family == AF_UNIX) {
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
return UV__ERR(errno);
} else {
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
return UV__ERR(errno);
}
#elif defined(SO_REUSEPORT) && !defined(__linux__)
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
return UV__ERR(errno);
#else
yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
return UV__ERR(errno);
#endif
......@@ -636,6 +653,100 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
}
#if !defined(__OpenBSD__) && !defined(__NetBSD__)
static int uv__udp_set_source_membership4(uv_udp_t* handle,
const struct sockaddr_in* multicast_addr,
const char* interface_addr,
const struct sockaddr_in* source_addr,
uv_membership membership) {
struct ip_mreq_source mreq;
int optname;
int err;
err = uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR);
if (err)
return err;
memset(&mreq, 0, sizeof(mreq));
if (interface_addr != NULL) {
err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
if (err)
return err;
} else {
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
}
mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
mreq.imr_sourceaddr.s_addr = source_addr->sin_addr.s_addr;
if (membership == UV_JOIN_GROUP)
optname = IP_ADD_SOURCE_MEMBERSHIP;
else if (membership == UV_LEAVE_GROUP)
optname = IP_DROP_SOURCE_MEMBERSHIP;
else
return UV_EINVAL;
if (setsockopt(handle->io_watcher.fd,
IPPROTO_IP,
optname,
&mreq,
sizeof(mreq))) {
return UV__ERR(errno);
}
return 0;
}
static int uv__udp_set_source_membership6(uv_udp_t* handle,
const struct sockaddr_in6* multicast_addr,
const char* interface_addr,
const struct sockaddr_in6* source_addr,
uv_membership membership) {
struct group_source_req mreq;
struct sockaddr_in6 addr6;
int optname;
int err;
err = uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR);
if (err)
return err;
memset(&mreq, 0, sizeof(mreq));
if (interface_addr != NULL) {
err = uv_ip6_addr(interface_addr, 0, &addr6);
if (err)
return err;
mreq.gsr_interface = addr6.sin6_scope_id;
} else {
mreq.gsr_interface = 0;
}
memcpy(&mreq.gsr_group, multicast_addr, sizeof(mreq.gsr_group));
memcpy(&mreq.gsr_source, source_addr, sizeof(mreq.gsr_source));
if (membership == UV_JOIN_GROUP)
optname = MCAST_JOIN_SOURCE_GROUP;
else if (membership == UV_LEAVE_GROUP)
optname = MCAST_LEAVE_SOURCE_GROUP;
else
return UV_EINVAL;
if (setsockopt(handle->io_watcher.fd,
IPPROTO_IPV6,
optname,
&mreq,
sizeof(mreq))) {
return UV__ERR(errno);
}
return 0;
}
#endif
int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
int domain;
int err;
......@@ -725,6 +836,55 @@ int uv_udp_set_membership(uv_udp_t* handle,
}
}
int uv_udp_set_source_membership(uv_udp_t* handle,
const char* multicast_addr,
const char* interface_addr,
const char* source_addr,
uv_membership membership) {
#if !defined(__OpenBSD__) && !defined(__NetBSD__)
int err;
struct sockaddr_storage mcast_addr;
struct sockaddr_in* mcast_addr4;
struct sockaddr_in6* mcast_addr6;
struct sockaddr_storage src_addr;
struct sockaddr_in* src_addr4;
struct sockaddr_in6* src_addr6;
mcast_addr4 = (struct sockaddr_in*)&mcast_addr;
mcast_addr6 = (struct sockaddr_in6*)&mcast_addr;
src_addr4 = (struct sockaddr_in*)&src_addr;
src_addr6 = (struct sockaddr_in6*)&src_addr;
err = uv_ip4_addr(multicast_addr, 0, mcast_addr4);
if (err) {
err = uv_ip6_addr(multicast_addr, 0, mcast_addr6);
if (err)
return err;
err = uv_ip6_addr(source_addr, 0, src_addr6);
if (err)
return err;
return uv__udp_set_source_membership6(handle,
mcast_addr6,
interface_addr,
src_addr6,
membership);
}
err = uv_ip4_addr(source_addr, 0, src_addr4);
if (err)
return err;
return uv__udp_set_source_membership4(handle,
mcast_addr4,
interface_addr,
src_addr4,
membership);
#else
return UV_ENOSYS;
#endif
}
static int uv__setsockopt(uv_udp_t* handle,
int option4,
int option6,
......
......@@ -34,6 +34,7 @@
# include <malloc.h> /* malloc */
#else
# include <net/if.h> /* if_nametoindex */
# include <sys/un.h> /* AF_UNIX, sockaddr_un */
#endif
......@@ -210,6 +211,9 @@ int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) {
memset(addr, 0, sizeof(*addr));
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
#ifdef SIN6_LEN
addr->sin_len = sizeof(*addr);
#endif
return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr));
}
......@@ -376,6 +380,10 @@ int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) {
addrlen = sizeof(struct sockaddr_in);
else if (addr->sa_family == AF_INET6)
addrlen = sizeof(struct sockaddr_in6);
#if defined(AF_UNIX) && !defined(_WIN32)
else if (addr->sa_family == AF_UNIX)
addrlen = sizeof(struct sockaddr_un);
#endif
else
return UV_EINVAL;
} else {
......@@ -631,37 +639,66 @@ int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
dent = dents[(*nbufs)++];
ent->name = dent->d_name;
ent->type = uv__fs_get_dirent_type(dent);
return 0;
}
uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) {
uv_dirent_type_t type;
#ifdef HAVE_DIRENT_TYPES
switch (dent->d_type) {
case UV__DT_DIR:
ent->type = UV_DIRENT_DIR;
type = UV_DIRENT_DIR;
break;
case UV__DT_FILE:
ent->type = UV_DIRENT_FILE;
type = UV_DIRENT_FILE;
break;
case UV__DT_LINK:
ent->type = UV_DIRENT_LINK;
type = UV_DIRENT_LINK;
break;
case UV__DT_FIFO:
ent->type = UV_DIRENT_FIFO;
type = UV_DIRENT_FIFO;
break;
case UV__DT_SOCKET:
ent->type = UV_DIRENT_SOCKET;
type = UV_DIRENT_SOCKET;
break;
case UV__DT_CHAR:
ent->type = UV_DIRENT_CHAR;
type = UV_DIRENT_CHAR;
break;
case UV__DT_BLOCK:
ent->type = UV_DIRENT_BLOCK;
type = UV_DIRENT_BLOCK;
break;
default:
ent->type = UV_DIRENT_UNKNOWN;
type = UV_DIRENT_UNKNOWN;
}
#else
ent->type = UV_DIRENT_UNKNOWN;
type = UV_DIRENT_UNKNOWN;
#endif
return 0;
return type;
}
void uv__fs_readdir_cleanup(uv_fs_t* req) {
uv_dir_t* dir;
uv_dirent_t* dirents;
int i;
if (req->ptr == NULL)
return;
dir = req->ptr;
dirents = dir->dirents;
req->ptr = NULL;
if (dirents == NULL)
return;
for (i = 0; i < req->result; ++i) {
uv__free((char*) dirents[i].name);
dirents[i].name = NULL;
}
}
......@@ -752,3 +789,24 @@ void uv_loop_delete(uv_loop_t* loop) {
if (loop != default_loop)
uv__free(loop);
}
void uv_os_free_environ(uv_env_item_t* envitems, int count) {
int i;
for (i = 0; i < count; i++) {
uv__free(envitems[i].name);
}
uv__free(envitems);
}
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
int i;
for (i = 0; i < count; i++)
uv__free(cpu_infos[i].model);
uv__free(cpu_infos);
}
......@@ -193,6 +193,8 @@ size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs);
int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);
void uv__fs_scandir_cleanup(uv_fs_t* req);
void uv__fs_readdir_cleanup(uv_fs_t* req);
uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent);
int uv__next_timeout(const uv_loop_t* loop);
void uv__run_timers(uv_loop_t* loop);
......
......@@ -132,6 +132,7 @@ int uv_translate_sys_error(int sys_errno) {
case WSAENOBUFS: return UV_ENOBUFS;
case ERROR_BAD_PATHNAME: return UV_ENOENT;
case ERROR_DIRECTORY: return UV_ENOENT;
case ERROR_ENVVAR_NOT_FOUND: return UV_ENOENT;
case ERROR_FILE_NOT_FOUND: return UV_ENOENT;
case ERROR_INVALID_NAME: return UV_ENOENT;
case ERROR_INVALID_DRIVE: return UV_ENOENT;
......
#ifndef UV_WIN_FS_FD_HASH_INL_H_
#define UV_WIN_FS_FD_HASH_INL_H_
#include "uv.h"
#include "internal.h"
/* Files are only inserted in uv__fd_hash when the UV_FS_O_FILEMAP flag is
* specified. Thus, when uv__fd_hash_get returns true, the file mapping in the
* info structure should be used for read/write operations.
*
* If the file is empty, the mapping field will be set to
* INVALID_HANDLE_VALUE. This is not an issue since the file mapping needs to
* be created anyway when the file size changes.
*
* Since file descriptors are sequential integers, the modulo operator is used
* as hashing function. For each bucket, a single linked list of arrays is
* kept to minimize allocations. A statically allocated memory buffer is kept
* for the first array in each bucket. */
#define UV__FD_HASH_SIZE 256
#define UV__FD_HASH_GROUP_SIZE 16
struct uv__fd_info_s {
int flags;
BOOLEAN is_directory;
HANDLE mapping;
LARGE_INTEGER size;
LARGE_INTEGER current_pos;
};
struct uv__fd_hash_entry_s {
uv_file fd;
struct uv__fd_info_s info;
};
struct uv__fd_hash_entry_group_s {
struct uv__fd_hash_entry_s entries[UV__FD_HASH_GROUP_SIZE];
struct uv__fd_hash_entry_group_s* next;
};
struct uv__fd_hash_bucket_s {
size_t size;
struct uv__fd_hash_entry_group_s* data;
};
static uv_mutex_t uv__fd_hash_mutex;
static struct uv__fd_hash_entry_group_s
uv__fd_hash_entry_initial[UV__FD_HASH_SIZE * UV__FD_HASH_GROUP_SIZE];
static struct uv__fd_hash_bucket_s uv__fd_hash[UV__FD_HASH_SIZE];
INLINE static void uv__fd_hash_init(void) {
int i, err;
err = uv_mutex_init(&uv__fd_hash_mutex);
if (err) {
uv_fatal_error(err, "uv_mutex_init");
}
for (i = 0; i < ARRAY_SIZE(uv__fd_hash); ++i) {
uv__fd_hash[i].size = 0;
uv__fd_hash[i].data =
uv__fd_hash_entry_initial + i * UV__FD_HASH_GROUP_SIZE;
}
}
#define FIND_COMMON_VARIABLES \
unsigned i; \
unsigned bucket = fd % ARRAY_SIZE(uv__fd_hash); \
struct uv__fd_hash_entry_s* entry_ptr = NULL; \
struct uv__fd_hash_entry_group_s* group_ptr; \
struct uv__fd_hash_bucket_s* bucket_ptr = &uv__fd_hash[bucket];
#define FIND_IN_GROUP_PTR(group_size) \
do { \
for (i = 0; i < group_size; ++i) { \
if (group_ptr->entries[i].fd == fd) { \
entry_ptr = &group_ptr->entries[i]; \
break; \
} \
} \
} while (0)
#define FIND_IN_BUCKET_PTR() \
do { \
size_t first_group_size = bucket_ptr->size % UV__FD_HASH_GROUP_SIZE; \
if (bucket_ptr->size != 0 && first_group_size == 0) \
first_group_size = UV__FD_HASH_GROUP_SIZE; \
group_ptr = bucket_ptr->data; \
FIND_IN_GROUP_PTR(first_group_size); \
for (group_ptr = group_ptr->next; \
group_ptr != NULL && entry_ptr == NULL; \
group_ptr = group_ptr->next) \
FIND_IN_GROUP_PTR(UV__FD_HASH_GROUP_SIZE); \
} while (0)
INLINE static int uv__fd_hash_get(int fd, struct uv__fd_info_s* info) {
FIND_COMMON_VARIABLES
uv_mutex_lock(&uv__fd_hash_mutex);
FIND_IN_BUCKET_PTR();
if (entry_ptr != NULL) {
*info = entry_ptr->info;
}
uv_mutex_unlock(&uv__fd_hash_mutex);
return entry_ptr != NULL;
}
INLINE static void uv__fd_hash_add(int fd, struct uv__fd_info_s* info) {
FIND_COMMON_VARIABLES
uv_mutex_lock(&uv__fd_hash_mutex);
FIND_IN_BUCKET_PTR();
if (entry_ptr == NULL) {
i = bucket_ptr->size % UV__FD_HASH_GROUP_SIZE;
if (bucket_ptr->size != 0 && i == 0) {
struct uv__fd_hash_entry_group_s* new_group_ptr =
uv__malloc(sizeof(*new_group_ptr));
if (new_group_ptr == NULL) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
new_group_ptr->next = bucket_ptr->data;
bucket_ptr->data = new_group_ptr;
}
bucket_ptr->size += 1;
entry_ptr = &bucket_ptr->data->entries[i];
entry_ptr->fd = fd;
}
entry_ptr->info = *info;
uv_mutex_unlock(&uv__fd_hash_mutex);
}
INLINE static int uv__fd_hash_remove(int fd, struct uv__fd_info_s* info) {
FIND_COMMON_VARIABLES
uv_mutex_lock(&uv__fd_hash_mutex);
FIND_IN_BUCKET_PTR();
if (entry_ptr != NULL) {
*info = entry_ptr->info;
bucket_ptr->size -= 1;
i = bucket_ptr->size % UV__FD_HASH_GROUP_SIZE;
if (entry_ptr != &bucket_ptr->data->entries[i]) {
*entry_ptr = bucket_ptr->data->entries[i];
}
if (bucket_ptr->size != 0 &&
bucket_ptr->size % UV__FD_HASH_GROUP_SIZE == 0) {
struct uv__fd_hash_entry_group_s* old_group_ptr = bucket_ptr->data;
bucket_ptr->data = old_group_ptr->next;
uv__free(old_group_ptr);
}
}
uv_mutex_unlock(&uv__fd_hash_mutex);
return entry_ptr != NULL;
}
#undef FIND_COMMON_VARIABLES
#undef FIND_IN_GROUP_PTR
#undef FIND_IN_BUCKET_PTR
#endif /* UV_WIN_FS_FD_HASH_INL_H_ */
This diff is collapsed.
......@@ -280,6 +280,8 @@ int uv__getsockpeername(const uv_handle_t* handle,
int* namelen,
int delayed_error);
int uv__random_rtlgenrandom(void* buf, size_t buflen);
/*
* Process stdio handles.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment