deps: update libuv to 1.51.0

PR-URL: https://github.com/nodejs/node/pull/58124
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
Node.js GitHub Bot 2025-05-16 02:39:36 -04:00 committed by GitHub
parent b6189c352c
commit 0315283cbd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
59 changed files with 1085 additions and 394 deletions

View file

@ -2,7 +2,7 @@ version: 2
sphinx: sphinx:
builder: html builder: html
configuration: null configuration: docs/src/conf.py
fail_on_warning: false fail_on_warning: false
build: build:

12
deps/uv/AUTHORS vendored
View file

@ -592,3 +592,15 @@ Thad House <ThadHouse@users.noreply.github.com>
Julian A Avar C <28635807+julian-a-avar-c@users.noreply.github.com> Julian A Avar C <28635807+julian-a-avar-c@users.noreply.github.com>
amcgoogan <105525867+amcgoogan@users.noreply.github.com> amcgoogan <105525867+amcgoogan@users.noreply.github.com>
Rafael Gonzaga <rafael.nunu@hotmail.com> Rafael Gonzaga <rafael.nunu@hotmail.com>
Morten Engelhardt Olsen <moro.engelhardt@gmail.com>
Andrey <bag@zurbagan.org>
Julio Jordán <juliojjordanp@outlook.com>
Jinho Jang <verycosy@kakao.com>
Velikiy Kirill <kuklix@ya.ru>
rainlow <37818892+rainlow@users.noreply.github.com>
Paolo Insogna <paolo@cowtech.it>
Robert Nagy <robert@openbsd.org>
mugitya03 <mugitya233@outlook.com>
Itay Bookstein <ibookstein@gmail.com>
crupest <crupest@outlook.com>
AE1020 <68134252+AE1020@users.noreply.github.com>

View file

@ -20,7 +20,7 @@ include(CTest)
set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON) set(CMAKE_C_EXTENSIONS ON)
set(CMAKE_C_STANDARD 90) set(CMAKE_C_STANDARD 11)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
@ -434,6 +434,7 @@ endif()
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|Linux|NetBSD|OpenBSD") if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|Linux|NetBSD|OpenBSD")
list(APPEND uv_test_libraries util) list(APPEND uv_test_libraries util)
list(APPEND uv_libraries m)
endif() endif()
if(CYGWIN OR MSYS) if(CYGWIN OR MSYS)
@ -583,6 +584,7 @@ if(LIBUV_BUILD_TESTS)
test/test-loop-close.c test/test-loop-close.c
test/test-loop-configure.c test/test-loop-configure.c
test/test-loop-handles.c test/test-loop-handles.c
test/test-loop-oom.c
test/test-loop-stop.c test/test-loop-stop.c
test/test-loop-time.c test/test-loop-time.c
test/test-metrics.c test/test-metrics.c

92
deps/uv/ChangeLog vendored
View file

@ -1,4 +1,94 @@
2025.01.15, Version 1.50.0 (Stable) 2025.04.25, Version 1.51.0 (Stable)
Changes since version 1.50.0:
* win: fix leak in uv_os_tmpdir (Saúl Ibarra Corretgé)
* docs: fix RTD build (Saúl Ibarra Corretgé)
* win: lazy-load [GS]etThreadDescription symbols (Ben Noordhuis)
* linux: try preadv64/pwritev64 before preadv/pwritev (Ben Noordhuis)
* win: check cwd length before spawning a child process (Morten Engelhardt
Olsen)
* macos,bsd: handle missing /dev/null in chroot env (Andrey)
* doc: fix README link text (Julio Jordán)
* win: fix order of FILE_STAT_BASIC_INFORMATION struct fields (Hüseyin Açacak)
* macos: increase child process stdio buffer size (Jinho Jang)
* doc: add C3 bindings to LINKS.md (Velikiy Kirill)
* unix: remove unnecessary errno.h include in poll.c (Juan José Arboleda)
* win: fix the inconsistency in volume serial number (Hüseyin Açacak)
* unix: add thread affinity support on openharmony (rainlow)
* unix: enable getrusage for SunOS (Paolo Insogna)
* unix,win: accept NAN/INFINITY as file timestamps (Ben Noordhuis)
* win: add ENABLE_VIRTUAL_TERMINAL_INPUT raw tty mode (Anna Henningsen)
* test: handle UV_ENOTSUP in platform_output (cjihrig)
* doc: fix rendering of threading.html (Tobias Nießen)
* unix,sunos: enable use of sendmmsg on Solaris and Illumos (Stacey Marshall)
* unix: handle out of memory in iface name copy (Ben Noordhuis)
* openbsd: do not error out if cpuspeed is not available (Robert Nagy)
* test: skip thread_name_threadpool on AIX/IBMi (Abdirahim Musse)
* aix,ibmi: fix undeclared identifiers (Richard Lau)
* unix,sunos: prefer SO_REUSEPORT for load balancing (Stacey Marshall)
* doc: free lib pointer before function return (mugitya03)
* test: link with libm (Juan José Arboleda)
* style: rename parameter to match definition (Mohammed Keyvanzadeh)
* test: support partial output lines in test runner (cjihrig)
* build: switch from c90 to c11 (Ben Noordhuis)
* linux: allow nul bytes in abstract socket address (Itay Bookstein)
* sunos: use pipe2 on solaris and illumos (Andy Pan)
* unix: remove TOCTOU issues from uv_pipe_chmod (Ben Noordhuis)
* unix: use pipe_fname if getsockname returns nothing (crupest)
* haiku: use uint32 instead of uint32_t (AE1020)
* doc: update thread pool stack size comment (Ben Noordhuis)
* unix: improve uv_loop_init OOM handling (Ben Noordhuis)
* test: merge uv_tcp_connect callbacks (Juan José Arboleda)
* test: skip multievent tests on macOS with TSAN enabled (Juan José Arboleda)
* linux: align CPU quota calculation with Rust (Juan José Arboleda)
* kqueue: improve fs event watcher OOM handling (Juan José Arboleda)
* sunos: improve fs event watcher OOM handling (Juan José Arboleda)
* build: shorten instructions for cmake build (Juan José Arboleda)
2025.01.15, Version 1.50.0 (Stable), 8fb9cb919489a48880680a56efecff6a7dfb4504
Changes since version 1.49.2: Changes since version 1.49.2:

2
deps/uv/LINKS.md vendored
View file

@ -108,3 +108,5 @@
* [node.pas](https://github.com/vovach777/node.pas) NodeJS-like ecosystem * [node.pas](https://github.com/vovach777/node.pas) NodeJS-like ecosystem
* Haskell * Haskell
* [Z.Haskell](https://z.haskell.world) * [Z.Haskell](https://z.haskell.world)
* C3
* [libuv.c3l](https://github.com/velikoss/libuv.c3l)

5
deps/uv/Makefile.am vendored
View file

@ -206,12 +206,13 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-ipc-send-recv.c \ test/test-ipc-send-recv.c \
test/test-ipc.c \ test/test-ipc.c \
test/test-list.h \ test/test-list.h \
test/test-loop-handles.c \
test/test-loop-alive.c \ test/test-loop-alive.c \
test/test-loop-close.c \ test/test-loop-close.c \
test/test-loop-configure.c \
test/test-loop-handles.c \
test/test-loop-oom.c \
test/test-loop-stop.c \ test/test-loop-stop.c \
test/test-loop-time.c \ test/test-loop-time.c \
test/test-loop-configure.c \
test/test-metrics.c \ test/test-metrics.c \
test/test-multiple-listen.c \ test/test-multiple-listen.c \
test/test-mutexes.c \ test/test-mutexes.c \

4
deps/uv/README.md vendored
View file

@ -189,9 +189,7 @@ $ make install
To build with [CMake][]: To build with [CMake][]:
```bash ```bash
$ mkdir -p build $ cmake -B build -DBUILD_TESTING=ON # generate project with tests
$ (cd build && cmake .. -DBUILD_TESTING=ON) # generate project with tests
$ cmake --build build # add `-j <n>` with cmake >= 3.12 $ cmake --build build # add `-j <n>` with cmake >= 3.12
# Run tests: # Run tests:

View file

@ -4,7 +4,7 @@
|---|---|---|---| |---|---|---|---|
| GNU/Linux | Tier 1 | Linux >= 3.10 with glibc >= 2.17 | | | GNU/Linux | Tier 1 | Linux >= 3.10 with glibc >= 2.17 | |
| macOS | Tier 1 | macOS >= 11 | Currently supported macOS releases | | macOS | Tier 1 | macOS >= 11 | Currently supported macOS releases |
| Windows | Tier 1 | >= Windows 10 | VS 2015 and later are supported | | Windows | Tier 1 | >= Windows 10 | VS 2017 and later are supported |
| FreeBSD | Tier 2 | >= 12 | | | FreeBSD | Tier 2 | >= 12 | |
| AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix | | AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix |
| IBM i | Tier 2 | >= IBM i 7.2 | Maintainers: @libuv/ibmi | | IBM i | Tier 2 | >= IBM i 7.2 | Maintainers: @libuv/ibmi |

View file

@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57) AC_PREREQ(2.57)
AC_INIT([libuv], [1.50.0], [https://github.com/libuv/libuv/issues]) AC_INIT([libuv], [1.51.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4]) m4_include([m4/as_case.m4])
@ -33,7 +33,7 @@ CC_ATTRIBUTE_VISIBILITY([default], [
# we exclude -fno-strict-aliasing for xlc # we exclude -fno-strict-aliasing for xlc
CC_CHECK_FLAG_SUPPORTED_APPEND([-fno-strict-aliasing]) CC_CHECK_FLAG_SUPPORTED_APPEND([-fno-strict-aliasing])
CC_CHECK_CFLAGS_APPEND([-g]) CC_CHECK_CFLAGS_APPEND([-g])
CC_CHECK_CFLAGS_APPEND([-std=gnu89]) CC_CHECK_CFLAGS_APPEND([-std=gnu11])
CC_CHECK_CFLAGS_APPEND([-Wall]) CC_CHECK_CFLAGS_APPEND([-Wall])
CC_CHECK_CFLAGS_APPEND([-Wextra]) CC_CHECK_CFLAGS_APPEND([-Wextra])
CC_CHECK_CFLAGS_APPEND([-Wno-long-long]) CC_CHECK_CFLAGS_APPEND([-Wno-long-long])

View file

@ -430,6 +430,12 @@ API
Equivalent to :man:`utime(2)`, :man:`futimes(3)` and :man:`lutimes(3)` respectively. Equivalent to :man:`utime(2)`, :man:`futimes(3)` and :man:`lutimes(3)` respectively.
Passing `UV_FS_UTIME_NOW` as the atime or mtime sets the timestamp to the
current time.
Passing `UV_FS_UTIME_OMIT` as the atime or mtime leaves the timestamp
untouched.
.. note:: .. note::
z/OS: `uv_fs_lutime()` is not implemented for z/OS. It can still be called but will return z/OS: `uv_fs_lutime()` is not implemented for z/OS. It can still be called but will return
``UV_ENOSYS``. ``UV_ENOSYS``.

View file

@ -58,5 +58,5 @@ libuv can be downloaded from `here <https://dist.libuv.org/dist/>`_.
Installation Installation
------------ ------------
Installation instructions can be found in `the README <https://github.com/libuv/libuv/blob/master/README.md>`_. Installation instructions can be found in the `README <https://github.com/libuv/libuv/blob/master/README.md>`_.

View file

@ -146,6 +146,8 @@ Threads
a thread name can be: Linux, IBM i (16), macOS (64), Windows (32767), and NetBSD (32), etc. `uv_thread_setname()` a thread name can be: Linux, IBM i (16), macOS (64), Windows (32767), and NetBSD (32), etc. `uv_thread_setname()`
will truncate it in case `name` is larger than the limit of the platform. will truncate it in case `name` is larger than the limit of the platform.
Not supported on Windows Server 2016, returns `UV_ENOSYS`.
.. versionadded:: 1.50.0 .. versionadded:: 1.50.0
.. c:function:: int uv_thread_getname(uv_thread_t* tid, char* name, size_t* size) .. c:function:: int uv_thread_getname(uv_thread_t* tid, char* name, size_t* size)
@ -155,9 +157,12 @@ Threads
The buffer should be large enough to hold the name of the thread plus the trailing NUL, or it will be truncated to fit The buffer should be large enough to hold the name of the thread plus the trailing NUL, or it will be truncated to fit
with the trailing NUL. with the trailing NUL.
Not supported on Windows Server 2016, returns `UV_ENOSYS`.
.. versionadded:: 1.50.0 .. versionadded:: 1.50.0
.. c:function:: int uv_thread_setpriority(uv_thread_t tid, int priority) .. c:function:: int uv_thread_setpriority(uv_thread_t tid, int priority)
If the function succeeds, the return value is 0. If the function succeeds, the return value is 0.
If the function fails, the return value is less than zero. If the function fails, the return value is less than zero.
Sets the scheduling priority of the thread specified by tid. It requires elevated Sets the scheduling priority of the thread specified by tid. It requires elevated
@ -165,7 +170,9 @@ Threads
The priority can be set to the following constants. UV_THREAD_PRIORITY_HIGHEST, The priority can be set to the following constants. UV_THREAD_PRIORITY_HIGHEST,
UV_THREAD_PRIORITY_ABOVE_NORMAL, UV_THREAD_PRIORITY_NORMAL, UV_THREAD_PRIORITY_ABOVE_NORMAL, UV_THREAD_PRIORITY_NORMAL,
UV_THREAD_PRIORITY_BELOW_NORMAL, UV_THREAD_PRIORITY_LOWEST. UV_THREAD_PRIORITY_BELOW_NORMAL, UV_THREAD_PRIORITY_LOWEST.
.. c:function:: int uv_thread_getpriority(uv_thread_t tid, int* priority) .. c:function:: int uv_thread_getpriority(uv_thread_t tid, int* priority)
If the function succeeds, the return value is 0. If the function succeeds, the return value is 0.
If the function fails, the return value is less than zero. If the function fails, the return value is less than zero.
Retrieves the scheduling priority of the thread specified by tid. The value in the Retrieves the scheduling priority of the thread specified by tid. The value in the

View file

@ -20,10 +20,10 @@ is 1024).
.. versionchanged:: 1.50.0 threads now have a default name of libuv-worker. .. versionchanged:: 1.50.0 threads now have a default name of libuv-worker.
The threadpool is global and shared across all event loops. When a particular The threadpool is global and shared across all event loops. When a particular
function makes use of the threadpool (i.e. when using :c:func:`uv_queue_work`) function makes use of the threadpool (e.g. when using :c:func:`uv_queue_work`)
libuv preallocates and initializes the maximum number of threads allowed by libuv preallocates and initializes the maximum number of threads allowed by
``UV_THREADPOOL_SIZE``. This causes a relatively minor memory overhead ``UV_THREADPOOL_SIZE``. More threads usually means more throughput but a higher
(~1MB for 128 threads) but increases the performance of threading at runtime. memory footprint. Thread stacks grow lazily on most platforms though.
.. note:: .. note::
Note that even though a global thread pool which is shared across all events Note that even though a global thread pool which is shared across all events

View file

@ -27,10 +27,15 @@ Data types
typedef enum { typedef enum {
/* Initial/normal terminal mode */ /* Initial/normal terminal mode */
UV_TTY_MODE_NORMAL, UV_TTY_MODE_NORMAL,
/* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */ /*
* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled).
* May become equivalent to UV_TTY_MODE_RAW_VT in future libuv versions.
*/
UV_TTY_MODE_RAW, UV_TTY_MODE_RAW,
/* Binary-safe I/O mode for IPC (Unix-only) */ /* Binary-safe I/O mode for IPC (Unix-only) */
UV_TTY_MODE_IO UV_TTY_MODE_IO,
/* Raw input mode. On Windows ENABLE_VIRTUAL_TERMINAL_INPUT is also set. */
UV_TTY_MODE_RAW_VT
} uv_tty_mode_t; } uv_tty_mode_t;
.. c:enum:: uv_tty_vtermstate_t .. c:enum:: uv_tty_vtermstate_t

12
deps/uv/include/uv.h vendored
View file

@ -58,6 +58,7 @@ extern "C" {
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <math.h>
/* Internal type, do not use. */ /* Internal type, do not use. */
struct uv__queue { struct uv__queue {
@ -805,10 +806,15 @@ struct uv_tty_s {
typedef enum { typedef enum {
/* Initial/normal terminal mode */ /* Initial/normal terminal mode */
UV_TTY_MODE_NORMAL, UV_TTY_MODE_NORMAL,
/* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */ /*
* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled).
* May become equivalent to UV_TTY_MODE_RAW_VT in future libuv versions.
*/
UV_TTY_MODE_RAW, UV_TTY_MODE_RAW,
/* Binary-safe I/O mode for IPC (Unix-only) */ /* Binary-safe I/O mode for IPC (Unix-only) */
UV_TTY_MODE_IO UV_TTY_MODE_IO,
/* Raw input mode. On Windows ENABLE_VIRTUAL_TERMINAL_INPUT is also set. */
UV_TTY_MODE_RAW_VT
} uv_tty_mode_t; } uv_tty_mode_t;
typedef enum { typedef enum {
@ -1585,6 +1591,8 @@ UV_EXTERN int uv_fs_chmod(uv_loop_t* loop,
const char* path, const char* path,
int mode, int mode,
uv_fs_cb cb); uv_fs_cb cb);
#define UV_FS_UTIME_NOW (INFINITY)
#define UV_FS_UTIME_OMIT (NAN)
UV_EXTERN int uv_fs_utime(uv_loop_t* loop, UV_EXTERN int uv_fs_utime(uv_loop_t* loop,
uv_fs_t* req, uv_fs_t* req,
const char* path, const char* path,

View file

@ -31,7 +31,7 @@
*/ */
#define UV_VERSION_MAJOR 1 #define UV_VERSION_MAJOR 1
#define UV_VERSION_MINOR 50 #define UV_VERSION_MINOR 51
#define UV_VERSION_PATCH 0 #define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX "" #define UV_VERSION_SUFFIX ""

View file

@ -499,8 +499,11 @@ typedef struct {
union { \ union { \
struct { \ struct { \
/* Used for readable TTY handles */ \ /* Used for readable TTY handles */ \
/* TODO: remove me in v2.x. */ \ union { \
HANDLE unused_; \ /* TODO: remove me in v2.x. */ \
HANDLE unused_; \
int mode; \
} mode; \
uv_buf_t read_line_buffer; \ uv_buf_t read_line_buffer; \
HANDLE read_raw_wait; \ HANDLE read_raw_wait; \
/* Fields used for translating win keystrokes into vt100 characters */ \ /* Fields used for translating win keystrokes into vt100 characters */ \

View file

@ -51,7 +51,7 @@ struct poll_ctx {
static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b); static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b);
static void poll_cb(uv_fs_t* req); static void poll_cb(uv_fs_t* req);
static void timer_cb(uv_timer_t* timer); static void timer_cb(uv_timer_t* timer);
static void timer_close_cb(uv_handle_t* handle); static void timer_close_cb(uv_handle_t* timer);
static uv_stat_t zero_statbuf; static uv_stat_t zero_statbuf;

View file

@ -1120,6 +1120,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
struct ifreq *ifr, *p, flg; struct ifreq *ifr, *p, flg;
struct in6_ifreq if6; struct in6_ifreq if6;
struct sockaddr_dl* sa_addr; struct sockaddr_dl* sa_addr;
size_t namelen;
char* name;
ifc.ifc_req = NULL; ifc.ifc_req = NULL;
sock6fd = -1; sock6fd = -1;
@ -1156,6 +1158,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) #define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
/* Count all up and running ipv4/ipv6 addresses */ /* Count all up and running ipv4/ipv6 addresses */
namelen = 0;
ifr = ifc.ifc_req; ifr = ifc.ifc_req;
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
p = ifr; p = ifr;
@ -1175,6 +1178,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
continue; continue;
namelen += strlen(p->ifr_name) + 1;
(*count)++; (*count)++;
} }
@ -1182,11 +1186,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
goto cleanup; goto cleanup;
/* Alloc the return interface structs */ /* Alloc the return interface structs */
*addresses = uv__calloc(*count, sizeof(**addresses)); *addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
if (!(*addresses)) { if (*addresses == NULL) {
r = UV_ENOMEM; r = UV_ENOMEM;
goto cleanup; goto cleanup;
} }
name = (char*) &(*addresses)[*count];
address = *addresses; address = *addresses;
ifr = ifc.ifc_req; ifr = ifc.ifc_req;
@ -1210,7 +1215,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
/* All conditions above must match count loop */ /* All conditions above must match count loop */
address->name = uv__strdup(p->ifr_name); namelen = strlen(p->ifr_name) + 1;
address->name = memcpy(name, p->ifr_name, namelen);
name += namelen;
if (inet6) if (inet6)
address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
@ -1282,13 +1289,7 @@ cleanup:
void uv_free_interface_addresses(uv_interface_address_t* addresses, void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count) { int count) {
int i;
for (i = 0; i < count; ++i) {
uv__free(addresses[i].name);
}
uv__free(addresses); uv__free(addresses);
} }

View file

@ -280,7 +280,7 @@ static int uv__async_start(uv_loop_t* loop) {
* thus we create one for that, but this fd will not be actually used, * thus we create one for that, but this fd will not be actually used,
* it's just a placeholder and magic number which is going to be closed * it's just a placeholder and magic number which is going to be closed
* during the cleanup, as other FDs. */ * during the cleanup, as other FDs. */
err = uv__open_cloexec("/dev/null", O_RDONLY); err = uv__open_cloexec("/", O_RDONLY);
if (err < 0) if (err < 0)
return err; return err;
@ -308,8 +308,14 @@ static int uv__async_start(uv_loop_t* loop) {
return err; return err;
#endif #endif
uv__io_init(&loop->async_io_watcher, uv__async_io, pipefd[0]); err = uv__io_init_start(loop, &loop->async_io_watcher, uv__async_io,
uv__io_start(loop, &loop->async_io_watcher, POLLIN); pipefd[0], POLLIN);
if (err < 0) {
uv__close(pipefd[0]);
if (pipefd[1] != -1)
uv__close(pipefd[1]);
return err;
}
loop->async_wfd = pipefd[1]; loop->async_wfd = pipefd[1];
#if UV__KQUEUE_EVFILT_USER #if UV__KQUEUE_EVFILT_USER

View file

@ -65,13 +65,13 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
return 0; return 0;
} }
/* TODO(bnoordhuis) share with linux.c */
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
uv_interface_address_t* address;
struct ifaddrs* addrs; struct ifaddrs* addrs;
struct ifaddrs* ent; struct ifaddrs* ent;
uv_interface_address_t* address; size_t namelen;
#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__) char* name;
int i;
#endif
*count = 0; *count = 0;
*addresses = NULL; *addresses = NULL;
@ -80,9 +80,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return UV__ERR(errno); return UV__ERR(errno);
/* Count the number of interfaces */ /* Count the number of interfaces */
namelen = 0;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) { for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
continue; continue;
namelen += strlen(ent->ifa_name) + 1;
(*count)++; (*count)++;
} }
@ -92,20 +94,22 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
} }
/* Make sure the memory is initiallized to zero using calloc() */ /* Make sure the memory is initiallized to zero using calloc() */
*addresses = uv__calloc(*count, sizeof(**addresses)); *addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
if (*addresses == NULL) { if (*addresses == NULL) {
freeifaddrs(addrs); freeifaddrs(addrs);
return UV_ENOMEM; return UV_ENOMEM;
} }
name = (char*) &(*addresses)[*count];
address = *addresses; address = *addresses;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) { for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
continue; continue;
address->name = uv__strdup(ent->ifa_name); namelen = strlen(ent->ifa_name) + 1;
address->name = memcpy(name, ent->ifa_name, namelen);
name += namelen;
if (ent->ifa_addr->sa_family == AF_INET6) { if (ent->ifa_addr->sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
@ -129,6 +133,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__) #if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
/* Fill in physical addresses for each interface */ /* Fill in physical addresses for each interface */
for (ent = addrs; ent != NULL; ent = ent->ifa_next) { for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
int i;
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS)) if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
continue; continue;
@ -151,13 +157,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
} }
/* TODO(bnoordhuis) share with linux.c */
void uv_free_interface_addresses(uv_interface_address_t* addresses, void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count) { int count) {
int i;
for (i = 0; i < count; i++) {
uv__free(addresses[i].name);
}
uv__free(addresses); uv__free(addresses);
} }

View file

@ -867,7 +867,7 @@ static unsigned int next_power_of_two(unsigned int val) {
return val; return val;
} }
static void maybe_resize(uv_loop_t* loop, unsigned int len) { static int maybe_resize(uv_loop_t* loop, unsigned int len) {
uv__io_t** watchers; uv__io_t** watchers;
void* fake_watcher_list; void* fake_watcher_list;
void* fake_watcher_count; void* fake_watcher_count;
@ -875,7 +875,7 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) {
unsigned int i; unsigned int i;
if (len <= loop->nwatchers) if (len <= loop->nwatchers)
return; return 0;
/* Preserve fake watcher list and count at the end of the watchers */ /* Preserve fake watcher list and count at the end of the watchers */
if (loop->watchers != NULL) { if (loop->watchers != NULL) {
@ -891,7 +891,7 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) {
(nwatchers + 2) * sizeof(loop->watchers[0])); (nwatchers + 2) * sizeof(loop->watchers[0]));
if (watchers == NULL) if (watchers == NULL)
abort(); return UV_ENOMEM;
for (i = loop->nwatchers; i < nwatchers; i++) for (i = loop->nwatchers; i < nwatchers; i++)
watchers[i] = NULL; watchers[i] = NULL;
watchers[nwatchers] = fake_watcher_list; watchers[nwatchers] = fake_watcher_list;
@ -899,11 +899,11 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) {
loop->watchers = watchers; loop->watchers = watchers;
loop->nwatchers = nwatchers; loop->nwatchers = nwatchers;
return 0;
} }
void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) { void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) {
assert(cb != NULL);
assert(fd >= -1); assert(fd >= -1);
uv__queue_init(&w->pending_queue); uv__queue_init(&w->pending_queue);
uv__queue_init(&w->watcher_queue); uv__queue_init(&w->watcher_queue);
@ -914,14 +914,18 @@ void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) {
} }
void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) { int uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
int err;
assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI))); assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
assert(0 != events); assert(0 != events);
assert(w->fd >= 0); assert(w->fd >= 0);
assert(w->fd < INT_MAX); assert(w->fd < INT_MAX);
w->pevents |= events; w->pevents |= events;
maybe_resize(loop, w->fd + 1); err = maybe_resize(loop, w->fd + 1);
if (err)
return err;
#if !defined(__sun) #if !defined(__sun)
/* The event ports backend needs to rearm all file descriptors on each and /* The event ports backend needs to rearm all file descriptors on each and
@ -929,7 +933,7 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
* short-circuit here if the event mask is unchanged. * short-circuit here if the event mask is unchanged.
*/ */
if (w->events == w->pevents) if (w->events == w->pevents)
return; return 0;
#endif #endif
if (uv__queue_empty(&w->watcher_queue)) if (uv__queue_empty(&w->watcher_queue))
@ -939,6 +943,25 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
loop->watchers[w->fd] = w; loop->watchers[w->fd] = w;
loop->nfds++; loop->nfds++;
} }
return 0;
}
int uv__io_init_start(uv_loop_t* loop,
uv__io_t* w,
uv__io_cb cb,
int fd,
unsigned int events) {
int err;
assert(cb != NULL);
assert(fd > -1);
uv__io_init(w, cb, fd);
err = uv__io_start(loop, w, events);
if (err)
uv__io_init(w, NULL, -1);
return err;
} }
@ -1078,6 +1101,8 @@ int uv_getrusage_thread(uv_rusage_t* rusage) {
return 0; return 0;
#elif defined(RUSAGE_LWP)
return uv__getrusage(RUSAGE_LWP, rusage);
#elif defined(RUSAGE_THREAD) #elif defined(RUSAGE_THREAD)
return uv__getrusage(RUSAGE_THREAD, rusage); return uv__getrusage(RUSAGE_THREAD, rusage);
#endif /* defined(__APPLE__) */ #endif /* defined(__APPLE__) */
@ -2021,14 +2046,11 @@ unsigned int uv_available_parallelism(void) {
#ifdef __linux__ #ifdef __linux__
{ {
double rc_with_cgroup; long long quota = 0;
uv__cpu_constraint c = {0, 0, 0.0};
if (uv__get_constrained_cpu(&c) == 0 && c.period_length > 0) { if (uv__get_constrained_cpu(&quota) == 0)
rc_with_cgroup = (double)c.quota_per_period / c.period_length * c.proportions; if (quota > 0 && quota < rc)
if (rc_with_cgroup < rc) rc = quota;
rc = (long)rc_with_cgroup; /* Casting is safe since rc_with_cgroup < rc < LONG_MAX */
}
} }
#endif /* __linux__ */ #endif /* __linux__ */

116
deps/uv/src/unix/fs.c vendored
View file

@ -203,8 +203,23 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
} }
UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) { #if defined(__APPLE__) \
|| defined(_AIX71) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
|| defined(__HAIKU__) \
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__) \
|| defined(__sun)
static struct timespec uv__fs_to_timespec(double time) {
struct timespec ts; struct timespec ts;
if (uv__isinf(time))
return (struct timespec){UTIME_NOW, UTIME_NOW};
if (uv__isnan(time))
return (struct timespec){UTIME_OMIT, UTIME_OMIT};
ts.tv_sec = time; ts.tv_sec = time;
ts.tv_nsec = (time - ts.tv_sec) * 1e9; ts.tv_nsec = (time - ts.tv_sec) * 1e9;
@ -221,41 +236,23 @@ UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) {
} }
return ts; return ts;
} }
#endif
UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) {
struct timeval tv;
tv.tv_sec = time;
tv.tv_usec = (time - tv.tv_sec) * 1e6;
if (tv.tv_usec < 0) {
tv.tv_usec += 1e6;
tv.tv_sec -= 1;
}
return tv;
}
static ssize_t uv__fs_futime(uv_fs_t* req) { static ssize_t uv__fs_futime(uv_fs_t* req) {
#if defined(__linux__) \ #if defined(__APPLE__) \
|| defined(_AIX71) \ || defined(_AIX71) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
|| defined(__HAIKU__) \ || defined(__HAIKU__) \
|| defined(__GNU__) || defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__) \
|| defined(__sun)
struct timespec ts[2]; struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime); ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime); ts[1] = uv__fs_to_timespec(req->mtime);
return futimens(req->file, ts); return futimens(req->file, ts);
#elif defined(__APPLE__) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__sun)
struct timeval tv[2];
tv[0] = uv__fs_to_timeval(req->atime);
tv[1] = uv__fs_to_timeval(req->mtime);
# if defined(__sun)
return futimesat(req->file, NULL, tv);
# else
return futimes(req->file, tv);
# endif
#elif defined(__MVS__) #elif defined(__MVS__)
attrib_t atr; attrib_t atr;
memset(&atr, 0, sizeof(atr)); memset(&atr, 0, sizeof(atr));
@ -461,12 +458,7 @@ static ssize_t uv__pwritev_emul(int fd,
/* The function pointer cache is an uintptr_t because _Atomic void* /* The function pointer cache is an uintptr_t because _Atomic void*
* doesn't work on macos/ios/etc... * doesn't work on macos/ios/etc...
* Disable optimization on armv7 to work around the bug described in
* https://github.com/libuv/libuv/issues/4532
*/ */
#if defined(__arm__) && (__ARM_ARCH == 7)
__attribute__((optimize("O0")))
#endif
static ssize_t uv__preadv_or_pwritev(int fd, static ssize_t uv__preadv_or_pwritev(int fd,
const struct iovec* bufs, const struct iovec* bufs,
size_t nbufs, size_t nbufs,
@ -479,7 +471,12 @@ static ssize_t uv__preadv_or_pwritev(int fd,
p = (void*) atomic_load_explicit(cache, memory_order_relaxed); p = (void*) atomic_load_explicit(cache, memory_order_relaxed);
if (p == NULL) { if (p == NULL) {
#ifdef RTLD_DEFAULT #ifdef RTLD_DEFAULT
p = dlsym(RTLD_DEFAULT, is_pread ? "preadv" : "pwritev"); /* Try _LARGEFILE_SOURCE version of preadv/pwritev first,
* then fall back to the plain version, for libcs like musl.
*/
p = dlsym(RTLD_DEFAULT, is_pread ? "preadv64" : "pwritev64");
if (p == NULL)
p = dlsym(RTLD_DEFAULT, is_pread ? "preadv" : "pwritev");
dlerror(); /* Clear errors. */ dlerror(); /* Clear errors. */
#endif /* RTLD_DEFAULT */ #endif /* RTLD_DEFAULT */
if (p == NULL) if (p == NULL)
@ -487,10 +484,7 @@ static ssize_t uv__preadv_or_pwritev(int fd,
atomic_store_explicit(cache, (uintptr_t) p, memory_order_relaxed); atomic_store_explicit(cache, (uintptr_t) p, memory_order_relaxed);
} }
/* Use memcpy instead of `f = p` to work around a compiler bug, f = p;
* see https://github.com/libuv/libuv/issues/4532
*/
memcpy(&f, &p, sizeof(p));
return f(fd, bufs, nbufs, off); return f(fd, bufs, nbufs, off);
} }
@ -1145,25 +1139,20 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
static ssize_t uv__fs_utime(uv_fs_t* req) { static ssize_t uv__fs_utime(uv_fs_t* req) {
#if defined(__linux__) \ #if defined(__APPLE__) \
|| defined(_AIX71) \ || defined(_AIX71) \
|| defined(__sun) \ || defined(__DragonFly__) \
|| defined(__HAIKU__) || defined(__FreeBSD__) \
|| defined(__HAIKU__) \
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__) \
|| defined(__sun)
struct timespec ts[2]; struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime); ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime); ts[1] = uv__fs_to_timespec(req->mtime);
return utimensat(AT_FDCWD, req->path, ts, 0); return utimensat(AT_FDCWD, req->path, ts, 0);
#elif defined(__APPLE__) \ #elif defined(_AIX) && !defined(_AIX71)
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
|| defined(__NetBSD__) \
|| defined(__OpenBSD__)
struct timeval tv[2];
tv[0] = uv__fs_to_timeval(req->atime);
tv[1] = uv__fs_to_timeval(req->mtime);
return utimes(req->path, tv);
#elif defined(_AIX) \
&& !defined(_AIX71)
struct utimbuf buf; struct utimbuf buf;
buf.actime = req->atime; buf.actime = req->atime;
buf.modtime = req->mtime; buf.modtime = req->mtime;
@ -1184,24 +1173,19 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
static ssize_t uv__fs_lutime(uv_fs_t* req) { static ssize_t uv__fs_lutime(uv_fs_t* req) {
#if defined(__linux__) || \ #if defined(__APPLE__) \
defined(_AIX71) || \ || defined(_AIX71) \
defined(__sun) || \ || defined(__DragonFly__) \
defined(__HAIKU__) || \ || defined(__FreeBSD__) \
defined(__GNU__) || \ || defined(__HAIKU__) \
defined(__OpenBSD__) || defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__) \
|| defined(__sun)
struct timespec ts[2]; struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime); ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime); ts[1] = uv__fs_to_timespec(req->mtime);
return utimensat(AT_FDCWD, req->path, ts, AT_SYMLINK_NOFOLLOW); return utimensat(AT_FDCWD, req->path, ts, AT_SYMLINK_NOFOLLOW);
#elif defined(__APPLE__) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__NetBSD__)
struct timeval tv[2];
tv[0] = uv__fs_to_timeval(req->atime);
tv[1] = uv__fs_to_timeval(req->mtime);
return lutimes(req->path, tv);
#else #else
errno = ENOSYS; errno = ENOSYS;
return -1; return -1;

View file

@ -120,7 +120,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
int i; int i;
status_t status; status_t status;
system_info system; system_info system;
uint32_t topology_count; uint32 topology_count; /* Haiku expects address of uint32, not uint32_t */
uint64_t cpuspeed; uint64_t cpuspeed;
uv_cpu_info_t* cpu_info; uv_cpu_info_t* cpu_info;

View file

@ -394,6 +394,8 @@ static int get_ibmi_physical_address(const char* line, char (*phys_addr)[6]) {
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
uv_interface_address_t* address; uv_interface_address_t* address;
struct ifaddrs_pase *ifap = NULL, *cur; struct ifaddrs_pase *ifap = NULL, *cur;
size_t namelen;
char* name;
int inet6, r = 0; int inet6, r = 0;
*count = 0; *count = 0;
@ -403,6 +405,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return UV_ENOSYS; return UV_ENOSYS;
/* The first loop to get the size of the array to be allocated */ /* The first loop to get the size of the array to be allocated */
namelen = 0;
for (cur = ifap; cur; cur = cur->ifa_next) { for (cur = ifap; cur; cur = cur->ifa_next) {
if (!(cur->ifa_addr->sa_family == AF_INET6 || if (!(cur->ifa_addr->sa_family == AF_INET6 ||
cur->ifa_addr->sa_family == AF_INET)) cur->ifa_addr->sa_family == AF_INET))
@ -411,6 +414,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING)) if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
continue; continue;
namelen += strlen(cur->ifa_name) + 1;
(*count)++; (*count)++;
} }
@ -420,11 +424,13 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
} }
/* Alloc the return interface structs */ /* Alloc the return interface structs */
*addresses = uv__calloc(*count, sizeof(**addresses)); *addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
if (*addresses == NULL) { if (*addresses == NULL) {
Qp2freeifaddrs(ifap); Qp2freeifaddrs(ifap);
return UV_ENOMEM; return UV_ENOMEM;
} }
name = (char*) &(*addresses)[*count];
address = *addresses; address = *addresses;
/* The second loop to fill in the array */ /* The second loop to fill in the array */
@ -436,7 +442,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING)) if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
continue; continue;
address->name = uv__strdup(cur->ifa_name); namelen = strlen(cur->ifa_name) + 1;
address->name = memcpy(name, cur->ifa_name, namelen);
name += namelen;
inet6 = (cur->ifa_addr->sa_family == AF_INET6); inet6 = (cur->ifa_addr->sa_family == AF_INET6);
@ -497,13 +505,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
} }
void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) { void uv_free_interface_addresses(uv_interface_address_t* addresses,
int i; int count) {
for (i = 0; i < count; ++i) {
uv__free(addresses[i].name);
}
uv__free(addresses); uv__free(addresses);
} }

View file

@ -257,7 +257,12 @@ void uv__make_close_pending(uv_handle_t* handle);
int uv__getiovmax(void); int uv__getiovmax(void);
void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd); void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd);
void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events); int uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events);
int uv__io_init_start(uv_loop_t* loop,
uv__io_t* w,
uv__io_cb cb,
int fd,
unsigned int events);
void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events); void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events);
void uv__io_close(uv_loop_t* loop, uv__io_t* w); void uv__io_close(uv_loop_t* loop, uv__io_t* w);
void uv__io_feed(uv_loop_t* loop, uv__io_t* w); void uv__io_feed(uv_loop_t* loop, uv__io_t* w);
@ -489,13 +494,7 @@ uv__fs_copy_file_range(int fd_in,
#endif #endif
#ifdef __linux__ #ifdef __linux__
typedef struct { int uv__get_constrained_cpu(long long* quota);
long long quota_per_period;
long long period_length;
double proportions;
} uv__cpu_constraint;
int uv__get_constrained_cpu(uv__cpu_constraint* constraint);
#endif #endif
#if defined(__sun) && !defined(__illumos__) #if defined(__sun) && !defined(__illumos__)

View file

@ -569,6 +569,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
const char* path, const char* path,
unsigned int flags) { unsigned int flags) {
int fd; int fd;
int r;
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
struct stat statbuf; struct stat statbuf;
#endif #endif
@ -604,7 +605,6 @@ int uv_fs_event_start(uv_fs_event_t* handle,
if (0 == atomic_load_explicit(&uv__has_forked_with_cfrunloop, if (0 == atomic_load_explicit(&uv__has_forked_with_cfrunloop,
memory_order_relaxed)) { memory_order_relaxed)) {
int r;
/* The fallback fd is no longer needed */ /* The fallback fd is no longer needed */
uv__close_nocheckstdio(fd); uv__close_nocheckstdio(fd);
handle->event_watcher.fd = -1; handle->event_watcher.fd = -1;
@ -620,11 +620,16 @@ int uv_fs_event_start(uv_fs_event_t* handle,
fallback: fallback:
#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ #endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
uv__handle_start(handle); r = uv__io_init_start(handle->loop,
uv__io_init(&handle->event_watcher, uv__fs_event, fd); &handle->event_watcher,
uv__io_start(handle->loop, &handle->event_watcher, POLLIN); uv__fs_event,
fd,
POLLIN);
return 0; if (!r)
uv__handle_start(handle);
return r;
} }

View file

@ -1954,11 +1954,15 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
return !exclude_type; return !exclude_type;
} }
/* TODO(bnoordhuis) share with bsd-ifaddrs.c */
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
struct ifaddrs *addrs, *ent;
uv_interface_address_t* address; uv_interface_address_t* address;
struct sockaddr_ll* sll;
struct ifaddrs* addrs;
struct ifaddrs* ent;
size_t namelen;
char* name;
int i; int i;
struct sockaddr_ll *sll;
*count = 0; *count = 0;
*addresses = NULL; *addresses = NULL;
@ -1967,10 +1971,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return UV__ERR(errno); return UV__ERR(errno);
/* Count the number of interfaces */ /* Count the number of interfaces */
namelen = 0;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) { for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
continue; continue;
namelen += strlen(ent->ifa_name) + 1;
(*count)++; (*count)++;
} }
@ -1980,19 +1986,22 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
} }
/* Make sure the memory is initiallized to zero using calloc() */ /* Make sure the memory is initiallized to zero using calloc() */
*addresses = uv__calloc(*count, sizeof(**addresses)); *addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
if (!(*addresses)) { if (*addresses == NULL) {
freeifaddrs(addrs); freeifaddrs(addrs);
return UV_ENOMEM; return UV_ENOMEM;
} }
name = (char*) &(*addresses)[*count];
address = *addresses; address = *addresses;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) { for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR)) if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
continue; continue;
address->name = uv__strdup(ent->ifa_name); namelen = strlen(ent->ifa_name) + 1;
address->name = memcpy(name, ent->ifa_name, namelen);
name += namelen;
if (ent->ifa_addr->sa_family == AF_INET6) { if (ent->ifa_addr->sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
@ -2036,14 +2045,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
} }
/* TODO(bnoordhuis) share with bsd-ifaddrs.c */
void uv_free_interface_addresses(uv_interface_address_t* addresses, void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count) { int count) {
int i;
for (i = 0; i < count; i++) {
uv__free(addresses[i].name);
}
uv__free(addresses); uv__free(addresses);
} }
@ -2301,49 +2305,83 @@ uint64_t uv_get_available_memory(void) {
static int uv__get_cgroupv2_constrained_cpu(const char* cgroup, static int uv__get_cgroupv2_constrained_cpu(const char* cgroup,
uv__cpu_constraint* constraint) { long long* quota) {
char path[256]; static const char cgroup_mount[] = "/sys/fs/cgroup";
char buf[1024];
unsigned int weight;
int cgroup_size;
const char* cgroup_trimmed; const char* cgroup_trimmed;
char buf[1024];
char full_path[256];
char path[256];
char quota_buf[16]; char quota_buf[16];
char* last_slash;
int cgroup_size;
long long limit;
long long min_quota;
long long period;
if (strncmp(cgroup, "0::/", 4) != 0) if (strncmp(cgroup, "0::/", 4) != 0)
return UV_EINVAL; return UV_EINVAL;
/* Trim ending \n by replacing it with a 0 */ /* Trim ending \n by replacing it with a 0 */
cgroup_trimmed = cgroup + sizeof("0::/") - 1; /* Skip the prefix "0::/" */ cgroup_trimmed = cgroup + sizeof("0::/") - 1; /* Skip the prefix "0::/" */
cgroup_size = (int)strcspn(cgroup_trimmed, "\n"); /* Find the first slash */ cgroup_size = (int)strcspn(cgroup_trimmed, "\n"); /* Find the first \n */
min_quota = LLONG_MAX;
/* Construct the path to the cpu.max file */ /* Construct the path to the cpu.max files */
snprintf(path, sizeof(path), "/sys/fs/cgroup/%.*s/cpu.max", cgroup_size, snprintf(path, sizeof(path), "%s/%.*s/cgroup.controllers", cgroup_mount,
cgroup_trimmed); cgroup_size, cgroup_trimmed);
/* Read cpu.max */ /* Read controllers, if not exists, not really a cgroup */
if (uv__slurp(path, buf, sizeof(buf)) < 0) if (uv__slurp(path, buf, sizeof(buf)) < 0)
return UV_EIO; return UV_EIO;
if (sscanf(buf, "%15s %llu", quota_buf, &constraint->period_length) != 2) snprintf(path, sizeof(path), "%s/%.*s", cgroup_mount, cgroup_size,
return UV_EINVAL;
if (strncmp(quota_buf, "max", 3) == 0)
constraint->quota_per_period = LLONG_MAX;
else if (sscanf(quota_buf, "%lld", &constraint->quota_per_period) != 1)
return UV_EINVAL; // conversion failed
/* Construct the path to the cpu.weight file */
snprintf(path, sizeof(path), "/sys/fs/cgroup/%.*s/cpu.weight", cgroup_size,
cgroup_trimmed); cgroup_trimmed);
/* Read cpu.weight */ /*
if (uv__slurp(path, buf, sizeof(buf)) < 0) * Traverse up the cgroup v2 hierarchy, starting from the current cgroup path.
return UV_EIO; * At each level, attempt to read the "cpu.max" file, which defines the CPU
* quota and period.
*
* This reflects how Linux applies cgroup limits hierarchically.
*
* e.g: given a path like /sys/fs/cgroup/foo/bar/baz, we check:
* - /sys/fs/cgroup/foo/bar/baz/cpu.max
* - /sys/fs/cgroup/foo/bar/cpu.max
* - /sys/fs/cgroup/foo/cpu.max
* - /sys/fs/cgroup/cpu.max
*/
while (strncmp(path, cgroup_mount, strlen(cgroup_mount)) == 0) {
snprintf(full_path, sizeof(full_path), "%s/cpu.max", path);
if (sscanf(buf, "%u", &weight) != 1) /* Silently ignore and continue if the file does not exist */
return UV_EINVAL; if (uv__slurp(full_path, quota_buf, sizeof(quota_buf)) < 0)
goto next;
constraint->proportions = (double)weight / 100.0; /* No limit, move on */
if (strncmp(quota_buf, "max", 3) == 0)
goto next;
/* Read cpu.max */
if (sscanf(quota_buf, "%lld %lld", &limit, &period) != 2)
goto next;
/* Can't divide by 0 */
if (period == 0)
goto next;
*quota = limit / period;
if (*quota < min_quota)
min_quota = *quota;
next:
/* Move up one level in the cgroup hierarchy by trimming the last path.
* The loop ends once we reach the cgroup root mount point.
*/
last_slash = strrchr(path, '/');
if (last_slash == NULL || strcmp(path, cgroup_mount) == 0)
break;
*last_slash = '\0';
}
return 0; return 0;
} }
@ -2364,12 +2402,13 @@ static char* uv__cgroup1_find_cpu_controller(const char* cgroup,
} }
static int uv__get_cgroupv1_constrained_cpu(const char* cgroup, static int uv__get_cgroupv1_constrained_cpu(const char* cgroup,
uv__cpu_constraint* constraint) { long long* quota) {
char path[256]; char path[256];
char buf[1024]; char buf[1024];
unsigned int shares;
int cgroup_size; int cgroup_size;
char* cgroup_cpu; char* cgroup_cpu;
long long period_length;
long long quota_per_period;
cgroup_cpu = uv__cgroup1_find_cpu_controller(cgroup, &cgroup_size); cgroup_cpu = uv__cgroup1_find_cpu_controller(cgroup, &cgroup_size);
@ -2380,10 +2419,11 @@ static int uv__get_cgroupv1_constrained_cpu(const char* cgroup,
snprintf(path, sizeof(path), "/sys/fs/cgroup/%.*s/cpu.cfs_quota_us", snprintf(path, sizeof(path), "/sys/fs/cgroup/%.*s/cpu.cfs_quota_us",
cgroup_size, cgroup_cpu); cgroup_size, cgroup_cpu);
/* Read cpu.cfs_quota_us */
if (uv__slurp(path, buf, sizeof(buf)) < 0) if (uv__slurp(path, buf, sizeof(buf)) < 0)
return UV_EIO; return UV_EIO;
if (sscanf(buf, "%lld", &constraint->quota_per_period) != 1) if (sscanf(buf, "%lld", &quota_per_period) != 1)
return UV_EINVAL; return UV_EINVAL;
/* Construct the path to the cpu.cfs_period_us file */ /* Construct the path to the cpu.cfs_period_us file */
@ -2394,26 +2434,19 @@ static int uv__get_cgroupv1_constrained_cpu(const char* cgroup,
if (uv__slurp(path, buf, sizeof(buf)) < 0) if (uv__slurp(path, buf, sizeof(buf)) < 0)
return UV_EIO; return UV_EIO;
if (sscanf(buf, "%lld", &constraint->period_length) != 1) if (sscanf(buf, "%lld", &period_length) != 1)
return UV_EINVAL; return UV_EINVAL;
/* Construct the path to the cpu.shares file */ /* Can't divide by 0 */
snprintf(path, sizeof(path), "/sys/fs/cgroup/%.*s/cpu.shares", cgroup_size, if (period_length == 0)
cgroup_cpu);
/* Read cpu.shares */
if (uv__slurp(path, buf, sizeof(buf)) < 0)
return UV_EIO;
if (sscanf(buf, "%u", &shares) != 1)
return UV_EINVAL; return UV_EINVAL;
constraint->proportions = (double)shares / 1024.0; *quota = quota_per_period / period_length;
return 0; return 0;
} }
int uv__get_constrained_cpu(uv__cpu_constraint* constraint) { int uv__get_constrained_cpu(long long* quota) {
char cgroup[1024]; char cgroup[1024];
/* Read the cgroup from /proc/self/cgroup */ /* Read the cgroup from /proc/self/cgroup */
@ -2424,9 +2457,9 @@ int uv__get_constrained_cpu(uv__cpu_constraint* constraint) {
* The entry for cgroup v2 is always in the format "0::$PATH" * The entry for cgroup v2 is always in the format "0::$PATH"
* see https://docs.kernel.org/admin-guide/cgroup-v2.html */ * see https://docs.kernel.org/admin-guide/cgroup-v2.html */
if (strncmp(cgroup, "0::/", 4) == 0) if (strncmp(cgroup, "0::/", 4) == 0)
return uv__get_cgroupv2_constrained_cpu(cgroup, constraint); return uv__get_cgroupv2_constrained_cpu(cgroup, quota);
else else
return uv__get_cgroupv1_constrained_cpu(cgroup, constraint); return uv__get_cgroupv1_constrained_cpu(cgroup, quota);
} }
@ -2456,6 +2489,7 @@ static int compare_watchers(const struct watcher_list* a,
static int init_inotify(uv_loop_t* loop) { static int init_inotify(uv_loop_t* loop) {
int err;
int fd; int fd;
if (loop->inotify_fd != -1) if (loop->inotify_fd != -1)
@ -2465,10 +2499,14 @@ static int init_inotify(uv_loop_t* loop) {
if (fd < 0) if (fd < 0)
return UV__ERR(errno); return UV__ERR(errno);
loop->inotify_fd = fd; err = uv__io_init_start(loop, &loop->inotify_read_watcher, uv__inotify_read,
uv__io_init(&loop->inotify_read_watcher, uv__inotify_read, loop->inotify_fd); fd, POLLIN);
uv__io_start(loop, &loop->inotify_read_watcher, POLLIN); if (err) {
uv__close(fd);
return err;
}
loop->inotify_fd = fd;
return 0; return 0;
} }

View file

@ -32,12 +32,11 @@ int uv_loop_init(uv_loop_t* loop) {
void* saved_data; void* saved_data;
int err; int err;
saved_data = loop->data; saved_data = loop->data;
memset(loop, 0, sizeof(*loop)); memset(loop, 0, sizeof(*loop));
loop->data = saved_data; loop->data = saved_data;
lfields = (uv__loop_internal_fields_t*) uv__calloc(1, sizeof(*lfields)); lfields = uv__calloc(1, sizeof(*lfields));
if (lfields == NULL) if (lfields == NULL)
return UV_ENOMEM; return UV_ENOMEM;
loop->internal_fields = lfields; loop->internal_fields = lfields;
@ -116,6 +115,11 @@ fail_rwlock_init:
fail_signal_init: fail_signal_init:
uv__platform_loop_delete(loop); uv__platform_loop_delete(loop);
if (loop->backend_fd != -1) {
uv__close(loop->backend_fd);
loop->backend_fd = -1;
}
fail_platform_init: fail_platform_init:
uv_mutex_destroy(&lfields->loop_metrics.lock); uv_mutex_destroy(&lfields->loop_metrics.lock);

View file

@ -211,8 +211,16 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
which[1] = HW_CPUSPEED; which[1] = HW_CPUSPEED;
size = sizeof(cpuspeed); size = sizeof(cpuspeed);
if (sysctl(which, ARRAY_SIZE(which), &cpuspeed, &size, NULL, 0)) cpuspeed = 0;
/*
* HW_CPUSPEED can return EOPNOTSUPP if cpuspeed is 0,
* so ignore that and continue the flow, because we
* still care about the rest of the CPU info.
*/
if (sysctl(which, ARRAY_SIZE(which), &cpuspeed, &size, NULL, 0) &&
(errno != EOPNOTSUPP)) {
goto error; goto error;
}
size = sizeof(info); size = sizeof(info);
for (i = 0; i < numcpus; i++) { for (i = 0; i < numcpus; i++) {

View file

@ -31,13 +31,15 @@
/* Does the file path contain embedded nul bytes? */ /* Does the file path contain embedded nul bytes? */
static int includes_nul(const char *s, size_t n) { static int includes_invalid_nul(const char *s, size_t n) {
if (n == 0) if (n == 0)
return 0; return 0;
#ifdef __linux__ #ifdef __linux__
/* Accept abstract socket namespace path ("\0/virtual/path"). */ /* Accept abstract socket namespace paths, throughout which nul bytes have
s++; * no special significance ("\0foo\0bar").
n--; */
if (s[0] == '\0')
return 0;
#endif #endif
return NULL != memchr(s, '\0', n); return NULL != memchr(s, '\0', n);
} }
@ -84,7 +86,7 @@ int uv_pipe_bind2(uv_pipe_t* handle,
return UV_EINVAL; return UV_EINVAL;
#endif #endif
if (includes_nul(name, namelen)) if (includes_invalid_nul(name, namelen))
return UV_EINVAL; return UV_EINVAL;
if (flags & UV_PIPE_NO_TRUNCATE) if (flags & UV_PIPE_NO_TRUNCATE)
@ -271,7 +273,7 @@ int uv_pipe_connect2(uv_connect_t* req,
if (namelen == 0) if (namelen == 0)
return UV_EINVAL; return UV_EINVAL;
if (includes_nul(name, namelen)) if (includes_invalid_nul(name, namelen))
return UV_EINVAL; return UV_EINVAL;
if (flags & UV_PIPE_NO_TRUNCATE) if (flags & UV_PIPE_NO_TRUNCATE)
@ -445,13 +447,18 @@ uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
int uv_pipe_chmod(uv_pipe_t* handle, int mode) { int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
unsigned desired_mode;
struct stat pipe_stat;
char name_buffer[1 + UV__PATH_MAX]; char name_buffer[1 + UV__PATH_MAX];
int desired_mode;
size_t name_len; size_t name_len;
const char* name;
int fd;
int r; int r;
if (handle == NULL || uv__stream_fd(handle) == -1) if (handle == NULL)
return UV_EBADF;
fd = uv__stream_fd(handle);
if (fd == -1)
return UV_EBADF; return UV_EBADF;
if (mode != UV_READABLE && if (mode != UV_READABLE &&
@ -459,31 +466,32 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
mode != (UV_WRITABLE | UV_READABLE)) mode != (UV_WRITABLE | UV_READABLE))
return UV_EINVAL; return UV_EINVAL;
/* Unfortunately fchmod does not work on all platforms, we will use chmod. */
name_len = sizeof(name_buffer);
r = uv_pipe_getsockname(handle, name_buffer, &name_len);
if (r != 0)
return r;
/* stat must be used as fstat has a bug on Darwin */
if (uv__stat(name_buffer, &pipe_stat) == -1)
return UV__ERR(errno);
desired_mode = 0; desired_mode = 0;
if (mode & UV_READABLE) if (mode & UV_READABLE)
desired_mode |= S_IRUSR | S_IRGRP | S_IROTH; desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
if (mode & UV_WRITABLE) if (mode & UV_WRITABLE)
desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH; desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
/* Exit early if pipe already has desired mode. */ /* fchmod on macOS and (Free|Net|Open)BSD does not support UNIX sockets. */
if ((pipe_stat.st_mode & desired_mode) == desired_mode) if (fchmod(fd, desired_mode))
return 0; if (errno != EINVAL && errno != EOPNOTSUPP)
return UV__ERR(errno);
pipe_stat.st_mode |= desired_mode; /* Fall back to chmod. */
name_len = sizeof(name_buffer);
r = uv_pipe_getsockname(handle, name_buffer, &name_len);
if (r != 0)
return r;
name = name_buffer;
r = chmod(name_buffer, pipe_stat.st_mode); /* On some platforms, getsockname returns an empty string, and we try with pipe_fname. */
if (name_len == 0 && handle->pipe_fname != NULL)
name = handle->pipe_fname;
return r != -1 ? 0 : UV__ERR(errno); if (chmod(name, desired_mode))
return UV__ERR(errno);
return 0;
} }
@ -494,7 +502,9 @@ int uv_pipe(uv_os_fd_t fds[2], int read_flags, int write_flags) {
defined(__FreeBSD__) || \ defined(__FreeBSD__) || \
defined(__OpenBSD__) || \ defined(__OpenBSD__) || \
defined(__DragonFly__) || \ defined(__DragonFly__) || \
defined(__NetBSD__) defined(__NetBSD__) || \
defined(__illumos__) || \
(defined(UV__SOLARIS_11_4) && UV__SOLARIS_11_4)
int flags = O_CLOEXEC; int flags = O_CLOEXEC;
if ((read_flags & UV_NONBLOCK_PIPE) && (write_flags & UV_NONBLOCK_PIPE)) if ((read_flags & UV_NONBLOCK_PIPE) && (write_flags & UV_NONBLOCK_PIPE))

View file

@ -24,7 +24,6 @@
#include <unistd.h> #include <unistd.h>
#include <assert.h> #include <assert.h>
#include <errno.h>
static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {

View file

@ -188,8 +188,12 @@ void uv__wait_children(uv_loop_t* loop) {
static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
int mask; int mask;
int fd; int fd;
int ret;
int size;
int i;
mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM; mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM;
size = 64 * 1024;
switch (container->flags & mask) { switch (container->flags & mask) {
case UV_IGNORE: case UV_IGNORE:
@ -199,8 +203,17 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
assert(container->data.stream != NULL); assert(container->data.stream != NULL);
if (container->data.stream->type != UV_NAMED_PIPE) if (container->data.stream->type != UV_NAMED_PIPE)
return UV_EINVAL; return UV_EINVAL;
else else {
return uv_socketpair(SOCK_STREAM, 0, fds, 0, 0); ret = uv_socketpair(SOCK_STREAM, 0, fds, 0, 0);
if (ret == 0)
for (i = 0; i < 2; i++) {
setsockopt(fds[i], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
setsockopt(fds[i], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
}
}
return ret;
case UV_INHERIT_FD: case UV_INHERIT_FD:
case UV_INHERIT_STREAM: case UV_INHERIT_STREAM:

View file

@ -259,22 +259,28 @@ static void uv__signal_unregister_handler(int signum) {
static int uv__signal_loop_once_init(uv_loop_t* loop) { static int uv__signal_loop_once_init(uv_loop_t* loop) {
int* pipefd;
int err; int err;
/* Return if already initialized. */ /* Return if already initialized. */
if (loop->signal_pipefd[0] != -1) pipefd = loop->signal_pipefd;
if (pipefd[0] != -1)
return 0; return 0;
err = uv__make_pipe(loop->signal_pipefd, UV_NONBLOCK_PIPE); err = uv__make_pipe(pipefd, UV_NONBLOCK_PIPE);
if (err) if (err)
return err; return err;
uv__io_init(&loop->signal_io_watcher, err = uv__io_init_start(loop, &loop->signal_io_watcher, uv__signal_event,
uv__signal_event, pipefd[0], POLLIN);
loop->signal_pipefd[0]); if (err) {
uv__io_start(loop, &loop->signal_io_watcher, POLLIN); uv__close(pipefd[0]);
uv__close(pipefd[1]);
pipefd[0] = -1;
pipefd[1] = -1;
}
return 0; return err;
} }

View file

@ -546,8 +546,15 @@ int uv_fs_event_start(uv_fs_event_t* handle,
} }
if (first_run) { if (first_run) {
uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd); err = uv__io_init_start(handle->loop,
uv__io_start(handle->loop, &handle->loop->fs_event_watcher, POLLIN); &handle->loop->fs_event_watcher,
uv__fs_event_read,
portfd,
POLLIN);
if (err)
uv__handle_stop(handle);
return err;
} }
return 0; return 0;
@ -826,6 +833,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
uv_interface_address_t* address; uv_interface_address_t* address;
struct ifaddrs* addrs; struct ifaddrs* addrs;
struct ifaddrs* ent; struct ifaddrs* ent;
size_t namelen;
char* name;
*count = 0; *count = 0;
*addresses = NULL; *addresses = NULL;
@ -834,9 +843,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return UV__ERR(errno); return UV__ERR(errno);
/* Count the number of interfaces */ /* Count the number of interfaces */
namelen = 0;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) { for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent)) if (uv__ifaddr_exclude(ent))
continue; continue;
namelen += strlen(ent->ifa_name) + 1;
(*count)++; (*count)++;
} }
@ -845,19 +856,22 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return 0; return 0;
} }
*addresses = uv__malloc(*count * sizeof(**addresses)); *addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
if (!(*addresses)) { if (*addresses == NULL) {
freeifaddrs(addrs); freeifaddrs(addrs);
return UV_ENOMEM; return UV_ENOMEM;
} }
name = (char*) &(*addresses)[*count];
address = *addresses; address = *addresses;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) { for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent)) if (uv__ifaddr_exclude(ent))
continue; continue;
address->name = uv__strdup(ent->ifa_name); namelen = strlen(ent->ifa_name) + 1;
address->name = memcpy(name, ent->ifa_name, namelen);
name += namelen;
if (ent->ifa_addr->sa_family == AF_INET6) { if (ent->ifa_addr->sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr); address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
@ -885,13 +899,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
#endif /* SUNOS_NO_IFADDRS */ #endif /* SUNOS_NO_IFADDRS */
void uv_free_interface_addresses(uv_interface_address_t* addresses, void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count) { int count) {
int i;
for (i = 0; i < count; i++) {
uv__free(addresses[i].name);
}
uv__free(addresses); uv__free(addresses);
} }

View file

@ -214,7 +214,7 @@ int uv_thread_setaffinity(uv_thread_t* tid,
if (cpumask[i]) if (cpumask[i])
CPU_SET(i, &cpuset); CPU_SET(i, &cpuset);
#if defined(__ANDROID__) #if defined(__ANDROID__) || defined(__OHOS__)
if (sched_setaffinity(pthread_gettid_np(*tid), sizeof(cpuset), &cpuset)) if (sched_setaffinity(pthread_gettid_np(*tid), sizeof(cpuset), &cpuset))
r = errno; r = errno;
else else
@ -242,7 +242,7 @@ int uv_thread_getaffinity(uv_thread_t* tid,
return UV_EINVAL; return UV_EINVAL;
CPU_ZERO(&cpuset); CPU_ZERO(&cpuset);
#if defined(__ANDROID__) #if defined(__ANDROID__) || defined(__OHOS__)
if (sched_getaffinity(pthread_gettid_np(*tid), sizeof(cpuset), &cpuset)) if (sched_getaffinity(pthread_gettid_np(*tid), sizeof(cpuset), &cpuset))
r = errno; r = errno;
else else

View file

@ -284,6 +284,11 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
int fd; int fd;
int rc; int rc;
if (uv__is_raw_tty_mode(mode)) {
/* There is only a single raw TTY mode on UNIX. */
mode = UV_TTY_MODE_RAW;
}
if (tty->mode == (int) mode) if (tty->mode == (int) mode)
return 0; return 0;
@ -324,6 +329,8 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
case UV_TTY_MODE_IO: case UV_TTY_MODE_IO:
uv__tty_make_raw(&tmp); uv__tty_make_raw(&tmp);
break; break;
default:
UNREACHABLE();
} }
/* Apply changes after draining */ /* Apply changes after draining */

View file

@ -300,6 +300,9 @@ static void uv__udp_recvmsg(uv_udp_t* handle) {
* *
* zOS does not support getsockname with SO_REUSEPORT option when using * zOS does not support getsockname with SO_REUSEPORT option when using
* AF_UNIX. * AF_UNIX.
*
* Solaris 11.4: SO_REUSEPORT will not load balance when SO_REUSEADDR
* is also set, but it's not valid for every socket type.
*/ */
static int uv__sock_reuseaddr(int fd) { static int uv__sock_reuseaddr(int fd) {
int yes; int yes;
@ -317,8 +320,18 @@ static int uv__sock_reuseaddr(int fd) {
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
return UV__ERR(errno); return UV__ERR(errno);
} }
#elif defined(SO_REUSEPORT) && !defined(__linux__) && !defined(__GNU__) && \ #elif defined(SO_REUSEPORT) && defined(UV__SOLARIS_11_4) && UV__SOLARIS_11_4
!defined(__sun__) && !defined(__DragonFly__) && !defined(_AIX73) if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) {
if (errno != ENOPROTOOPT)
return UV__ERR(errno);
/* Not all socket types accept SO_REUSEPORT. */
errno = 0;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
return UV__ERR(errno);
}
#elif defined(SO_REUSEPORT) && \
!defined(__linux__) && !defined(__GNU__) && \
!defined(__illumos__) && !defined(__DragonFly__) && !defined(_AIX73)
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
return UV__ERR(errno); return UV__ERR(errno);
#else #else
@ -1298,7 +1311,8 @@ static int uv__udp_sendmsgv(int fd,
r = 0; r = 0;
nsent = 0; nsent = 0;
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
(defined(__sun__) && defined(MSG_WAITFORONE))
if (count > 1) { if (count > 1) {
for (i = 0; i < count; /*empty*/) { for (i = 0; i < count; /*empty*/) {
struct mmsghdr m[20]; struct mmsghdr m[20];
@ -1325,7 +1339,9 @@ static int uv__udp_sendmsgv(int fd,
goto exit; goto exit;
} }
#endif /* defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) */ #endif /* defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) ||
* (defined(__sun__) && defined(MSG_WAITFORONE))
*/
for (i = 0; i < count; i++, nsent++) for (i = 0; i < count; i++, nsent++)
if ((r = uv__udp_sendmsg1(fd, bufs[i], nbufs[i], addrs[i]))) if ((r = uv__udp_sendmsg1(fd, bufs[i], nbufs[i], addrs[i])))

View file

@ -31,6 +31,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include "uv.h" #include "uv.h"
#include "uv/tree.h" #include "uv/tree.h"
@ -125,7 +126,7 @@ enum {
/* Only used by uv_tty_t handles. */ /* Only used by uv_tty_t handles. */
UV_HANDLE_TTY_READABLE = 0x01000000, UV_HANDLE_TTY_READABLE = 0x01000000,
UV_HANDLE_TTY_RAW = 0x02000000, UV_HANDLE_UNUSED0 = 0x02000000,
UV_HANDLE_TTY_SAVED_POSITION = 0x04000000, UV_HANDLE_TTY_SAVED_POSITION = 0x04000000,
UV_HANDLE_TTY_SAVED_ATTRIBUTES = 0x08000000, UV_HANDLE_TTY_SAVED_ATTRIBUTES = 0x08000000,
@ -140,6 +141,10 @@ enum {
UV_HANDLE_REAP = 0x10000000 UV_HANDLE_REAP = 0x10000000
}; };
static inline int uv__is_raw_tty_mode(uv_tty_mode_t m) {
return m == UV_TTY_MODE_RAW || m == UV_TTY_MODE_RAW_VT;
}
int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap); int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
void uv__loop_close(uv_loop_t* loop); void uv__loop_close(uv_loop_t* loop);
@ -448,4 +453,22 @@ struct uv__loop_internal_fields_s {
# define UV_PTHREAD_MAX_NAMELEN_NP 16 # define UV_PTHREAD_MAX_NAMELEN_NP 16
#endif #endif
/* Open-coded so downstream users don't have to link libm. */
static inline int uv__isinf(double d) {
uint64_t v;
STATIC_ASSERT(sizeof(v) == sizeof(d));
memcpy(&v, &d, sizeof(v));
return (v << 1 >> 53) == 2047 && !(v << 12);
}
/* Open-coded so downstream users don't have to link libm. */
static inline int uv__isnan(double d) {
uint64_t v;
STATIC_ASSERT(sizeof(v) == sizeof(d));
memcpy(&v, &d, sizeof(v));
return (v << 1 >> 53) == 2047 && !!(v << 12);
}
#endif /* UV_COMMON_H_ */ #endif /* UV_COMMON_H_ */

View file

@ -114,7 +114,7 @@ static int uv__loops_add(uv_loop_t* loop) {
failed_loops_realloc: failed_loops_realloc:
uv_mutex_unlock(&uv__loops_lock); uv_mutex_unlock(&uv__loops_lock);
return ERROR_OUTOFMEMORY; return UV_ENOMEM;
} }

29
deps/uv/src/win/fs.c vendored
View file

@ -1788,7 +1788,7 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
SetLastError(pRtlNtStatusToDosError(nt_status)); SetLastError(pRtlNtStatusToDosError(nt_status));
return -1; return -1;
} else { } else {
stat_info.VolumeSerialNumber.QuadPart = volume_info.VolumeSerialNumber; stat_info.VolumeSerialNumber.LowPart = volume_info.VolumeSerialNumber;
} }
stat_info.DeviceType = device_info.DeviceType; stat_info.DeviceType = device_info.DeviceType;
@ -1839,7 +1839,7 @@ INLINE static void fs__stat_assign_statbuf_null(uv_stat_t* statbuf) {
INLINE static void fs__stat_assign_statbuf(uv_stat_t* statbuf, INLINE static void fs__stat_assign_statbuf(uv_stat_t* statbuf,
FILE_STAT_BASIC_INFORMATION stat_info, int do_lstat) { FILE_STAT_BASIC_INFORMATION stat_info, int do_lstat) {
statbuf->st_dev = stat_info.VolumeSerialNumber.QuadPart; statbuf->st_dev = stat_info.VolumeSerialNumber.LowPart;
/* Todo: st_mode should probably always be 0666 for everyone. We might also /* Todo: st_mode should probably always be 0666 for everyone. We might also
* want to report 0777 if the file is a .exe or a directory. * want to report 0777 if the file is a .exe or a directory.
@ -2580,14 +2580,29 @@ fchmod_cleanup:
INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) { INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
FILETIME filetime_a, filetime_m; FILETIME filetime_as, *filetime_a = &filetime_as;
FILETIME filetime_ms, *filetime_m = &filetime_ms;
FILETIME now;
TIME_T_TO_FILETIME(atime, &filetime_a); if (uv__isinf(atime) || uv__isinf(mtime))
TIME_T_TO_FILETIME(mtime, &filetime_m); GetSystemTimeAsFileTime(&now);
if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) { if (uv__isinf(atime))
filetime_a = &now;
else if (uv__isnan(atime))
filetime_a = NULL;
else
TIME_T_TO_FILETIME(atime, filetime_a);
if (uv__isinf(mtime))
filetime_m = &now;
else if (uv__isnan(mtime))
filetime_m = NULL;
else
TIME_T_TO_FILETIME(mtime, filetime_m);
if (!SetFileTime(handle, NULL, filetime_a, filetime_m))
return -1; return -1;
}
return 0; return 0;
} }

View file

@ -898,7 +898,7 @@ int uv_spawn(uv_loop_t* loop,
*env = NULL, *cwd = NULL; *env = NULL, *cwd = NULL;
STARTUPINFOW startup; STARTUPINFOW startup;
PROCESS_INFORMATION info; PROCESS_INFORMATION info;
DWORD process_flags; DWORD process_flags, cwd_len;
BYTE* child_stdio_buffer; BYTE* child_stdio_buffer;
uv__process_init(loop, process); uv__process_init(loop, process);
@ -947,9 +947,10 @@ int uv_spawn(uv_loop_t* loop,
if (err) if (err)
goto done_uv; goto done_uv;
cwd_len = wcslen(cwd);
} else { } else {
/* Inherit cwd */ /* Inherit cwd */
DWORD cwd_len, r; DWORD r;
cwd_len = GetCurrentDirectoryW(0, NULL); cwd_len = GetCurrentDirectoryW(0, NULL);
if (!cwd_len) { if (!cwd_len) {
@ -970,6 +971,15 @@ int uv_spawn(uv_loop_t* loop,
} }
} }
/* If cwd is too long, shorten it */
if (cwd_len >= MAX_PATH) {
cwd_len = GetShortPathNameW(cwd, cwd, cwd_len);
if (cwd_len == 0) {
err = GetLastError();
goto done;
}
}
/* Get PATH environment variable. */ /* Get PATH environment variable. */
path = find_path(env); path = find_path(env);
if (path == NULL) { if (path == NULL) {

View file

@ -57,6 +57,9 @@ STATIC_ASSERT(sizeof(uv_thread_t) <= sizeof(void*));
static uv_key_t uv__current_thread_key; static uv_key_t uv__current_thread_key;
static uv_once_t uv__current_thread_init_guard = UV_ONCE_INIT; static uv_once_t uv__current_thread_init_guard = UV_ONCE_INIT;
static uv_once_t uv__thread_name_once = UV_ONCE_INIT;
HRESULT (WINAPI *pGetThreadDescription)(HANDLE, PWSTR*);
HRESULT (WINAPI *pSetThreadDescription)(HANDLE, PCWSTR);
static void uv__init_current_thread_key(void) { static void uv__init_current_thread_key(void) {
@ -278,12 +281,28 @@ int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
} }
static void uv__thread_name_init_once(void) {
HMODULE m;
m = GetModuleHandleA("api-ms-win-core-processthreads-l1-1-3.dll");
if (m != NULL) {
pGetThreadDescription = (void*) GetProcAddress(m, "GetThreadDescription");
pSetThreadDescription = (void*) GetProcAddress(m, "SetThreadDescription");
}
}
int uv_thread_setname(const char* name) { int uv_thread_setname(const char* name) {
HRESULT hr; HRESULT hr;
WCHAR* namew; WCHAR* namew;
int err; int err;
char namebuf[UV_PTHREAD_MAX_NAMELEN_NP]; char namebuf[UV_PTHREAD_MAX_NAMELEN_NP];
uv_once(&uv__thread_name_once, uv__thread_name_init_once);
if (pSetThreadDescription == NULL)
return UV_ENOSYS;
if (name == NULL) if (name == NULL)
return UV_EINVAL; return UV_EINVAL;
@ -295,7 +314,7 @@ int uv_thread_setname(const char* name) {
if (err) if (err)
return err; return err;
hr = SetThreadDescription(GetCurrentThread(), namew); hr = pSetThreadDescription(GetCurrentThread(), namew);
uv__free(namew); uv__free(namew);
if (FAILED(hr)) if (FAILED(hr))
return uv_translate_sys_error(HRESULT_CODE(hr)); return uv_translate_sys_error(HRESULT_CODE(hr));
@ -312,6 +331,11 @@ int uv_thread_getname(uv_thread_t* tid, char* name, size_t size) {
int r; int r;
DWORD exit_code; DWORD exit_code;
uv_once(&uv__thread_name_once, uv__thread_name_init_once);
if (pGetThreadDescription == NULL)
return UV_ENOSYS;
if (name == NULL || size == 0) if (name == NULL || size == 0)
return UV_EINVAL; return UV_EINVAL;
@ -324,7 +348,7 @@ int uv_thread_getname(uv_thread_t* tid, char* name, size_t size) {
namew = NULL; namew = NULL;
thread_name = NULL; thread_name = NULL;
hr = GetThreadDescription(*tid, &namew); hr = pGetThreadDescription(*tid, &namew);
if (FAILED(hr)) if (FAILED(hr))
return uv_translate_sys_error(HRESULT_CODE(hr)); return uv_translate_sys_error(HRESULT_CODE(hr));

80
deps/uv/src/win/tty.c vendored
View file

@ -58,6 +58,9 @@
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif #endif
#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
#endif
#define CURSOR_SIZE_SMALL 25 #define CURSOR_SIZE_SMALL 25
#define CURSOR_SIZE_LARGE 100 #define CURSOR_SIZE_LARGE 100
@ -119,7 +122,10 @@ static int uv_tty_virtual_width = -1;
* handle signalling SIGWINCH * handle signalling SIGWINCH
*/ */
static HANDLE uv__tty_console_handle = INVALID_HANDLE_VALUE; static HANDLE uv__tty_console_handle_out = INVALID_HANDLE_VALUE;
static HANDLE uv__tty_console_handle_in = INVALID_HANDLE_VALUE;
static DWORD uv__tty_console_in_original_mode = (DWORD)-1;
static volatile LONG uv__tty_console_in_need_mode_reset = 0;
static int uv__tty_console_height = -1; static int uv__tty_console_height = -1;
static int uv__tty_console_width = -1; static int uv__tty_console_width = -1;
static HANDLE uv__tty_console_resized = INVALID_HANDLE_VALUE; static HANDLE uv__tty_console_resized = INVALID_HANDLE_VALUE;
@ -159,19 +165,21 @@ static uv_tty_vtermstate_t uv__vterm_state = UV_TTY_UNSUPPORTED;
static void uv__determine_vterm_state(HANDLE handle); static void uv__determine_vterm_state(HANDLE handle);
void uv__console_init(void) { void uv__console_init(void) {
DWORD dwMode;
if (uv_sem_init(&uv_tty_output_lock, 1)) if (uv_sem_init(&uv_tty_output_lock, 1))
abort(); abort();
uv__tty_console_handle = CreateFileW(L"CONOUT$", uv__tty_console_handle_out = CreateFileW(L"CONOUT$",
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE, FILE_SHARE_WRITE,
0, 0,
OPEN_EXISTING, OPEN_EXISTING,
0, 0,
0); 0);
if (uv__tty_console_handle != INVALID_HANDLE_VALUE) { if (uv__tty_console_handle_out != INVALID_HANDLE_VALUE) {
CONSOLE_SCREEN_BUFFER_INFO sb_info; CONSOLE_SCREEN_BUFFER_INFO sb_info;
uv_mutex_init(&uv__tty_console_resize_mutex); uv_mutex_init(&uv__tty_console_resize_mutex);
if (GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info)) { if (GetConsoleScreenBufferInfo(uv__tty_console_handle_out, &sb_info)) {
uv__tty_console_width = sb_info.dwSize.X; uv__tty_console_width = sb_info.dwSize.X;
uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1; uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1;
} }
@ -179,6 +187,18 @@ void uv__console_init(void) {
NULL, NULL,
WT_EXECUTELONGFUNCTION); WT_EXECUTELONGFUNCTION);
} }
uv__tty_console_handle_in = CreateFileW(L"CONIN$",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
0,
0);
if (uv__tty_console_handle_in != INVALID_HANDLE_VALUE) {
if (GetConsoleMode(uv__tty_console_handle_in, &dwMode)) {
uv__tty_console_in_original_mode = dwMode;
}
}
} }
@ -253,7 +273,9 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {
/* Initialize TTY input specific fields. */ /* Initialize TTY input specific fields. */
tty->flags |= UV_HANDLE_TTY_READABLE | UV_HANDLE_READABLE; tty->flags |= UV_HANDLE_TTY_READABLE | UV_HANDLE_READABLE;
/* TODO: remove me in v2.x. */ /* TODO: remove me in v2.x. */
tty->tty.rd.unused_ = NULL; tty->tty.rd.mode.unused_ = NULL;
/* Partially overwrites unused_ again. */
tty->tty.rd.mode.mode = 0;
tty->tty.rd.read_line_buffer = uv_null_buf_; tty->tty.rd.read_line_buffer = uv_null_buf_;
tty->tty.rd.read_raw_wait = NULL; tty->tty.rd.read_raw_wait = NULL;
@ -344,6 +366,7 @@ static void uv__tty_capture_initial_style(
int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
DWORD flags; DWORD flags;
DWORD try_set_flags;
unsigned char was_reading; unsigned char was_reading;
uv_alloc_cb alloc_cb; uv_alloc_cb alloc_cb;
uv_read_cb read_cb; uv_read_cb read_cb;
@ -353,14 +376,19 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
return UV_EINVAL; return UV_EINVAL;
} }
if (!!mode == !!(tty->flags & UV_HANDLE_TTY_RAW)) { if ((int)mode == tty->tty.rd.mode.mode) {
return 0; return 0;
} }
try_set_flags = 0;
switch (mode) { switch (mode) {
case UV_TTY_MODE_NORMAL: case UV_TTY_MODE_NORMAL:
flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
break; break;
case UV_TTY_MODE_RAW_VT:
try_set_flags = ENABLE_VIRTUAL_TERMINAL_INPUT;
InterlockedExchange(&uv__tty_console_in_need_mode_reset, 1);
/* fallthrough */
case UV_TTY_MODE_RAW: case UV_TTY_MODE_RAW:
flags = ENABLE_WINDOW_INPUT; flags = ENABLE_WINDOW_INPUT;
break; break;
@ -386,16 +414,16 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
} }
uv_sem_wait(&uv_tty_output_lock); uv_sem_wait(&uv_tty_output_lock);
if (!SetConsoleMode(tty->handle, flags)) { if (!SetConsoleMode(tty->handle, flags | try_set_flags) &&
!SetConsoleMode(tty->handle, flags)) {
err = uv_translate_sys_error(GetLastError()); err = uv_translate_sys_error(GetLastError());
uv_sem_post(&uv_tty_output_lock); uv_sem_post(&uv_tty_output_lock);
return err; return err;
} }
uv_sem_post(&uv_tty_output_lock); uv_sem_post(&uv_tty_output_lock);
/* Update flag. */ /* Update mode. */
tty->flags &= ~UV_HANDLE_TTY_RAW; tty->tty.rd.mode.mode = mode;
tty->flags |= mode ? UV_HANDLE_TTY_RAW : 0;
/* If we just stopped reading, restart. */ /* If we just stopped reading, restart. */
if (was_reading) { if (was_reading) {
@ -614,7 +642,7 @@ static void uv__tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) {
static void uv__tty_queue_read(uv_loop_t* loop, uv_tty_t* handle) { static void uv__tty_queue_read(uv_loop_t* loop, uv_tty_t* handle) {
if (handle->flags & UV_HANDLE_TTY_RAW) { if (uv__is_raw_tty_mode(handle->tty.rd.mode.mode)) {
uv__tty_queue_read_raw(loop, handle); uv__tty_queue_read_raw(loop, handle);
} else { } else {
uv__tty_queue_read_line(loop, handle); uv__tty_queue_read_line(loop, handle);
@ -702,7 +730,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
handle->flags &= ~UV_HANDLE_READ_PENDING; handle->flags &= ~UV_HANDLE_READ_PENDING;
if (!(handle->flags & UV_HANDLE_READING) || if (!(handle->flags & UV_HANDLE_READING) ||
!(handle->flags & UV_HANDLE_TTY_RAW)) { !(uv__is_raw_tty_mode(handle->tty.rd.mode.mode))) {
goto out; goto out;
} }
@ -1050,7 +1078,7 @@ int uv__tty_read_stop(uv_tty_t* handle) {
if (!(handle->flags & UV_HANDLE_READ_PENDING)) if (!(handle->flags & UV_HANDLE_READ_PENDING))
return 0; return 0;
if (handle->flags & UV_HANDLE_TTY_RAW) { if (uv__is_raw_tty_mode(handle->tty.rd.mode.mode)) {
/* Cancel raw read. Write some bullshit event to force the console wait to /* Cancel raw read. Write some bullshit event to force the console wait to
* return. */ * return. */
memset(&record, 0, sizeof record); memset(&record, 0, sizeof record);
@ -2293,7 +2321,17 @@ void uv__tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
int uv_tty_reset_mode(void) { int uv_tty_reset_mode(void) {
/* Not necessary to do anything. */ /**
* Shells on Windows do know to reset output flags after a program exits,
* but not necessarily input flags, so we do that for them.
*/
if (
uv__tty_console_handle_in != INVALID_HANDLE_VALUE &&
uv__tty_console_in_original_mode != (DWORD)-1 &&
InterlockedExchange(&uv__tty_console_in_need_mode_reset, 0) != 0
) {
SetConsoleMode(uv__tty_console_handle_in, uv__tty_console_in_original_mode);
}
return 0; return 0;
} }
@ -2390,7 +2428,7 @@ static void uv__tty_console_signal_resize(void) {
CONSOLE_SCREEN_BUFFER_INFO sb_info; CONSOLE_SCREEN_BUFFER_INFO sb_info;
int width, height; int width, height;
if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info)) if (!GetConsoleScreenBufferInfo(uv__tty_console_handle_out, &sb_info))
return; return;
width = sb_info.dwSize.X; width = sb_info.dwSize.X;

View file

@ -1016,6 +1016,7 @@ int uv_os_homedir(char* buffer, size_t* size) {
int uv_os_tmpdir(char* buffer, size_t* size) { int uv_os_tmpdir(char* buffer, size_t* size) {
int r;
wchar_t *path; wchar_t *path;
size_t len; size_t len;
@ -1054,7 +1055,9 @@ int uv_os_tmpdir(char* buffer, size_t* size) {
path[len] = L'\0'; path[len] = L'\0';
} }
return uv__copy_utf16_to_utf8(path, len, buffer, size); r = uv__copy_utf16_to_utf8(path, len, buffer, size);
uv__free(path);
return r;
} }

View file

@ -4145,8 +4145,8 @@ typedef struct _FILE_STAT_BASIC_INFORMATION {
ULONG DeviceType; ULONG DeviceType;
ULONG DeviceCharacteristics; ULONG DeviceCharacteristics;
ULONG Reserved; ULONG Reserved;
FILE_ID_128 FileId128;
LARGE_INTEGER VolumeSerialNumber; LARGE_INTEGER VolumeSerialNumber;
FILE_ID_128 FileId128;
} FILE_STAT_BASIC_INFORMATION; } FILE_STAT_BASIC_INFORMATION;
#endif #endif
@ -4828,13 +4828,4 @@ typedef int (WINAPI *uv_sGetHostNameW)
int); int);
extern uv_sGetHostNameW pGetHostNameW; extern uv_sGetHostNameW pGetHostNameW;
/* processthreadsapi.h */
#if defined(__MINGW32__)
WINBASEAPI
HRESULT WINAPI GetThreadDescription(HANDLE hThread,
PWSTR *ppszThreadDescription);
WINBASEAPI
HRESULT WINAPI SetThreadDescription(HANDLE hThread, PCWSTR lpThreadDescription);
#endif
#endif /* UV_WIN_WINAPI_H_ */ #endif /* UV_WIN_WINAPI_H_ */

View file

@ -367,6 +367,7 @@ long int process_output_size(process_info_t *p) {
/* Copy the contents of the stdio output buffer to `fd`. */ /* Copy the contents of the stdio output buffer to `fd`. */
int process_copy_output(process_info_t* p, FILE* stream) { int process_copy_output(process_info_t* p, FILE* stream) {
char buf[1024]; char buf[1024];
int partial;
int r; int r;
r = fseek(p->stdout_file, 0, SEEK_SET); r = fseek(p->stdout_file, 0, SEEK_SET);
@ -375,9 +376,9 @@ int process_copy_output(process_info_t* p, FILE* stream) {
return -1; return -1;
} }
/* TODO: what if the line is longer than buf */ partial = 0;
while ((r = fread(buf, 1, sizeof(buf), p->stdout_file)) != 0) while ((r = fread(buf, 1, sizeof(buf), p->stdout_file)) != 0)
print_lines(buf, r, stream); partial = print_lines(buf, r, stream, partial);
if (ferror(p->stdout_file)) { if (ferror(p->stdout_file)) {
perror("read"); perror("read");

View file

@ -219,6 +219,7 @@ long int process_output_size(process_info_t *p) {
int process_copy_output(process_info_t* p, FILE* stream) { int process_copy_output(process_info_t* p, FILE* stream) {
char buf[1024]; char buf[1024];
int partial;
int fd, r; int fd, r;
fd = _open_osfhandle((intptr_t)p->stdio_out, _O_RDONLY | _O_TEXT); fd = _open_osfhandle((intptr_t)p->stdio_out, _O_RDONLY | _O_TEXT);
@ -229,8 +230,9 @@ int process_copy_output(process_info_t* p, FILE* stream) {
if (r < 0) if (r < 0)
return -1; return -1;
partial = 0;
while ((r = _read(fd, buf, sizeof(buf))) != 0) while ((r = _read(fd, buf, sizeof(buf))) != 0)
print_lines(buf, r, stream); partial = print_lines(buf, r, stream, partial);
_close(fd); _close(fd);
return 0; return 0;

16
deps/uv/test/runner.c vendored
View file

@ -426,13 +426,17 @@ void print_tests(FILE* stream) {
} }
void print_lines(const char* buffer, size_t size, FILE* stream) { int print_lines(const char* buffer, size_t size, FILE* stream, int partial) {
const char* start; const char* start;
const char* end; const char* end;
start = buffer; start = buffer;
while ((end = memchr(start, '\n', &buffer[size] - start))) { while ((end = memchr(start, '\n', &buffer[size] - start))) {
fputs("# ", stream); if (partial == 0)
fputs("# ", stream);
else
partial = 0;
fwrite(start, 1, (int)(end - start), stream); fwrite(start, 1, (int)(end - start), stream);
fputs("\n", stream); fputs("\n", stream);
fflush(stream); fflush(stream);
@ -441,9 +445,13 @@ void print_lines(const char* buffer, size_t size, FILE* stream) {
end = &buffer[size]; end = &buffer[size];
if (start < end) { if (start < end) {
fputs("# ", stream); if (partial == 0)
fputs("# ", stream);
fwrite(start, 1, (int)(end - start), stream); fwrite(start, 1, (int)(end - start), stream);
fputs("\n", stream);
fflush(stream); fflush(stream);
return 1;
} }
return 0;
} }

View file

@ -123,7 +123,7 @@ int run_test_part(const char* test, const char* part);
void print_tests(FILE* stream); void print_tests(FILE* stream);
/* Print lines in |buffer| as TAP diagnostics to |stream|. */ /* Print lines in |buffer| as TAP diagnostics to |stream|. */
void print_lines(const char* buffer, size_t size, FILE* stream); int print_lines(const char* buffer, size_t size, FILE* stream, int partial);
/* /*
* Stuff that should be implemented by test-runner-<platform>.h * Stuff that should be implemented by test-runner-<platform>.h

View file

@ -22,11 +22,7 @@
#include "uv.h" #include "uv.h"
#include "task.h" #include "task.h"
static void connect_4(uv_connect_t* req, int status) { static void connect_cb(uv_connect_t* req, int status) {
ASSERT_NE(status, UV_EADDRNOTAVAIL);
}
static void connect_6(uv_connect_t* req, int status) {
ASSERT_NE(status, UV_EADDRNOTAVAIL); ASSERT_NE(status, UV_EADDRNOTAVAIL);
} }
@ -46,7 +42,7 @@ TEST_IMPL(connect_unspecified) {
ASSERT_OK(uv_tcp_connect(&connect4, ASSERT_OK(uv_tcp_connect(&connect4,
&socket4, &socket4,
(const struct sockaddr*) &addr4, (const struct sockaddr*) &addr4,
connect_4)); connect_cb));
if (can_ipv6()) { if (can_ipv6()) {
ASSERT_OK(uv_tcp_init(loop, &socket6)); ASSERT_OK(uv_tcp_init(loop, &socket6));
@ -54,7 +50,7 @@ TEST_IMPL(connect_unspecified) {
ASSERT_OK(uv_tcp_connect(&connect6, ASSERT_OK(uv_tcp_connect(&connect6,
&socket6, &socket6,
(const struct sockaddr*) &addr6, (const struct sockaddr*) &addr6,
connect_6)); connect_cb));
} }
ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT)); ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));

View file

@ -32,7 +32,7 @@
static uv_fs_event_t fs_event; static uv_fs_event_t fs_event;
static const char file_prefix[] = "fsevent-"; static const char file_prefix[] = "fsevent-";
static const int fs_event_file_count = 16; static const int fs_event_file_count = 16;
#if defined(__APPLE__) || defined(_WIN32) #if (defined(__APPLE__) && !defined(__TSAN__)) || defined(_WIN32)
static const char file_prefix_in_subdir[] = "subdir"; static const char file_prefix_in_subdir[] = "subdir";
static int fs_multievent_cb_called; static int fs_multievent_cb_called;
#endif #endif
@ -250,7 +250,7 @@ static void fs_event_cb_dir_multi_file(uv_fs_event_t* handle,
} }
} }
#if defined(__APPLE__) || defined(_WIN32) #if (defined(__APPLE__) && !defined(__TSAN__)) || defined(_WIN32)
static const char* fs_event_get_filename_in_subdir(int i) { static const char* fs_event_get_filename_in_subdir(int i) {
snprintf(fs_event_filename, snprintf(fs_event_filename,
sizeof(fs_event_filename), sizeof(fs_event_filename),

271
deps/uv/test/test-fs.c vendored
View file

@ -59,6 +59,18 @@
#define TOO_LONG_NAME_LENGTH 65536 #define TOO_LONG_NAME_LENGTH 65536
#define PATHMAX 4096 #define PATHMAX 4096
#ifdef _WIN32
static const int is_win32 = 1;
#else
static const int is_win32 = 0;
#endif
#if defined(__APPLE__) || defined(__SUNPRO_C)
static const int is_apple_or_sunpro_c = 1;
#else
static const int is_apple_or_sunpro_c = 0;
#endif
typedef struct { typedef struct {
const char* path; const char* path;
double atime; double atime;
@ -827,43 +839,70 @@ static void check_utime(const char* path,
ASSERT_OK(req.result); ASSERT_OK(req.result);
s = &req.statbuf; s = &req.statbuf;
if (s->st_atim.tv_nsec == 0 && s->st_mtim.tv_nsec == 0) { if (isfinite(atime)) {
/* /* Test sub-second timestamps only when supported (such as Windows with
* Test sub-second timestamps only when supported (such as Windows with
* NTFS). Some other platforms support sub-second timestamps, but that * NTFS). Some other platforms support sub-second timestamps, but that
* support is filesystem-dependent. Notably OS X (HFS Plus) does NOT * support is filesystem-dependent. Notably OS X (HFS Plus) does NOT
* support sub-second timestamps. But kernels may round or truncate in * support sub-second timestamps. But kernels may round or truncate in
* either direction, so we may accept either possible answer. * either direction, so we may accept either possible answer.
*/ */
#ifdef _WIN32 if (s->st_atim.tv_nsec == 0) {
ASSERT_DOUBLE_EQ(atime, (long) atime); if (is_win32)
ASSERT_DOUBLE_EQ(mtime, (long) atime); ASSERT_DOUBLE_EQ(atime, (long) atime);
#endif if (atime > 0 || (long) atime == atime)
if (atime > 0 || (long) atime == atime) ASSERT_EQ(s->st_atim.tv_sec, (long) atime);
ASSERT_EQ(s->st_atim.tv_sec, (long) atime); ASSERT_GE(s->st_atim.tv_sec, (long) atime - 1);
if (mtime > 0 || (long) mtime == mtime) ASSERT_LE(s->st_atim.tv_sec, (long) atime);
ASSERT_EQ(s->st_mtim.tv_sec, (long) mtime); } else {
ASSERT_GE(s->st_atim.tv_sec, (long) atime - 1); double st_atim;
ASSERT_GE(s->st_mtim.tv_sec, (long) mtime - 1); /* TODO(vtjnash): would it be better to normalize this? */
ASSERT_LE(s->st_atim.tv_sec, (long) atime); if (!is_apple_or_sunpro_c)
ASSERT_LE(s->st_mtim.tv_sec, (long) mtime); ASSERT_DOUBLE_GE(s->st_atim.tv_nsec, 0);
} else { st_atim = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9;
double st_atim; /* Linux does not allow reading reliably the atime of a symlink
double st_mtim; * since readlink() can update it
#if !defined(__APPLE__) && !defined(__SUNPRO_C) */
/* TODO(vtjnash): would it be better to normalize this? */ if (!test_lutime)
ASSERT_DOUBLE_GE(s->st_atim.tv_nsec, 0); ASSERT_DOUBLE_EQ(st_atim, atime);
ASSERT_DOUBLE_GE(s->st_mtim.tv_nsec, 0); }
#endif } else if (isinf(atime)) {
st_atim = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9; /* We test with timestamps that are in the distant past
st_mtim = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9; * (if you're a Gen Z-er) so check it's more recent than that.
/*
* Linux does not allow reading reliably the atime of a symlink
* since readlink() can update it
*/ */
if (!test_lutime) ASSERT_GT(s->st_atim.tv_sec, 1739710000);
ASSERT_DOUBLE_EQ(st_atim, atime); } else {
ASSERT_DOUBLE_EQ(st_mtim, mtime); ASSERT_OK(0);
}
if (isfinite(mtime)) {
/* Test sub-second timestamps only when supported (such as Windows with
* NTFS). Some other platforms support sub-second timestamps, but that
* support is filesystem-dependent. Notably OS X (HFS Plus) does NOT
* support sub-second timestamps. But kernels may round or truncate in
* either direction, so we may accept either possible answer.
*/
if (s->st_mtim.tv_nsec == 0) {
if (is_win32)
ASSERT_DOUBLE_EQ(mtime, (long) atime);
if (mtime > 0 || (long) mtime == mtime)
ASSERT_EQ(s->st_mtim.tv_sec, (long) mtime);
ASSERT_GE(s->st_mtim.tv_sec, (long) mtime - 1);
ASSERT_LE(s->st_mtim.tv_sec, (long) mtime);
} else {
double st_mtim;
/* TODO(vtjnash): would it be better to normalize this? */
if (!is_apple_or_sunpro_c)
ASSERT_DOUBLE_GE(s->st_mtim.tv_nsec, 0);
st_mtim = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9;
ASSERT_DOUBLE_EQ(st_mtim, mtime);
}
} else if (isinf(mtime)) {
/* We test with timestamps that are in the distant past
* (if you're a Gen Z-er) so check it's more recent than that.
*/
ASSERT_GT(s->st_mtim.tv_sec, 1739710000);
} else {
ASSERT_OK(0);
} }
uv_fs_req_cleanup(&req); uv_fs_req_cleanup(&req);
@ -1607,6 +1646,50 @@ TEST_IMPL(fs_fstat) {
} }
TEST_IMPL(fs_fstat_st_dev) {
uv_fs_t req;
uv_fs_t req_link;
uv_loop_t* loop = uv_default_loop();
char* test_file = "tmp_st_dev";
char* symlink_file = "tmp_st_dev_link";
unlink(test_file);
unlink(symlink_file);
// Create file
int r = uv_fs_open(NULL, &req, test_file, UV_FS_O_RDWR | UV_FS_O_CREAT,
S_IWUSR | S_IRUSR, NULL);
ASSERT_GE(r, 0);
ASSERT_GE(req.result, 0);
uv_fs_req_cleanup(&req);
// Create a symlink
r = uv_fs_symlink(loop, &req, test_file, symlink_file, 0, NULL);
ASSERT_EQ(r, 0);
uv_fs_req_cleanup(&req);
// Call uv_fs_fstat for file
r = uv_fs_stat(loop, &req, test_file, NULL);
ASSERT_EQ(r, 0);
// Call uv_fs_fstat for symlink
r = uv_fs_stat(loop, &req_link, symlink_file, NULL);
ASSERT_EQ(r, 0);
// Compare st_dev
ASSERT_EQ(((uv_stat_t*)req.ptr)->st_dev, ((uv_stat_t*)req_link.ptr)->st_dev);
// Cleanup
uv_fs_req_cleanup(&req);
uv_fs_req_cleanup(&req_link);
unlink(test_file);
unlink(symlink_file);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(fs_fstat_stdio) { TEST_IMPL(fs_fstat_stdio) {
int fd; int fd;
int res; int res;
@ -2684,13 +2767,46 @@ TEST_IMPL(fs_utime) {
atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */ atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */
r = uv_fs_utime(NULL, &req, path, atime, mtime, NULL); ASSERT_OK(uv_fs_utime(NULL, &req, path, atime, mtime, NULL));
ASSERT_OK(r);
ASSERT_OK(req.result); ASSERT_OK(req.result);
uv_fs_req_cleanup(&req); uv_fs_req_cleanup(&req);
check_utime(path, atime, mtime, /* test_lutime */ 0); check_utime(path, atime, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_utime(NULL,
&req,
path,
UV_FS_UTIME_OMIT,
UV_FS_UTIME_OMIT,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_utime(NULL,
&req,
path,
UV_FS_UTIME_NOW,
UV_FS_UTIME_OMIT,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, UV_FS_UTIME_NOW, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_utime(NULL, &req, path, atime, mtime, NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_utime(NULL,
&req,
path,
UV_FS_UTIME_OMIT,
UV_FS_UTIME_NOW,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, UV_FS_UTIME_NOW, /* test_lutime */ 0);
atime = mtime = 1291404900.25; /* 2010-12-03 20:35:00.25 - mees <3 */ atime = mtime = 1291404900.25; /* 2010-12-03 20:35:00.25 - mees <3 */
checkme.path = path; checkme.path = path;
checkme.atime = atime; checkme.atime = atime;
@ -2824,9 +2940,43 @@ TEST_IMPL(fs_futime) {
ASSERT_OK(req.result); ASSERT_OK(req.result);
#endif #endif
uv_fs_req_cleanup(&req); uv_fs_req_cleanup(&req);
check_utime(path, atime, mtime, /* test_lutime */ 0); check_utime(path, atime, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_futime(NULL,
&req,
file,
UV_FS_UTIME_OMIT,
UV_FS_UTIME_OMIT,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_futime(NULL,
&req,
file,
UV_FS_UTIME_NOW,
UV_FS_UTIME_OMIT,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, UV_FS_UTIME_NOW, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_futime(NULL, &req, file, atime, mtime, NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_futime(NULL,
&req,
file,
UV_FS_UTIME_OMIT,
UV_FS_UTIME_NOW,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, UV_FS_UTIME_NOW, /* test_lutime */ 0);
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */ atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
checkme.atime = atime; checkme.atime = atime;
@ -2888,20 +3038,50 @@ TEST_IMPL(fs_lutime) {
/* Test the synchronous version. */ /* Test the synchronous version. */
atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */ atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */
checkme.atime = atime;
checkme.mtime = mtime;
checkme.path = symlink_path;
req.data = &checkme;
r = uv_fs_lutime(NULL, &req, symlink_path, atime, mtime, NULL); r = uv_fs_lutime(NULL, &req, symlink_path, atime, mtime, NULL);
#if (defined(_AIX) && !defined(_AIX71)) || \ #if (defined(_AIX) && !defined(_AIX71)) || defined(__MVS__)
defined(__MVS__)
ASSERT_EQ(r, UV_ENOSYS); ASSERT_EQ(r, UV_ENOSYS);
RETURN_SKIP("lutime is not implemented for z/OS and AIX versions below 7.1"); RETURN_SKIP("lutime is not implemented for z/OS and AIX versions below 7.1");
#endif #endif
ASSERT_OK(r); ASSERT_OK(r);
lutime_cb(&req); ASSERT_OK(req.result);
ASSERT_EQ(1, lutime_cb_count); uv_fs_req_cleanup(&req);
check_utime(symlink_path, atime, mtime, /* test_lutime */ 1);
ASSERT_OK(uv_fs_lutime(NULL,
&req,
symlink_path,
UV_FS_UTIME_OMIT,
UV_FS_UTIME_OMIT,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(symlink_path, atime, mtime, /* test_lutime */ 1);
ASSERT_OK(uv_fs_lutime(NULL,
&req,
symlink_path,
UV_FS_UTIME_NOW,
UV_FS_UTIME_OMIT,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(symlink_path, UV_FS_UTIME_NOW, mtime, /* test_lutime */ 1);
ASSERT_OK(uv_fs_lutime(NULL, &req, symlink_path, atime, mtime, NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(symlink_path, atime, mtime, /* test_lutime */ 1);
ASSERT_OK(uv_fs_lutime(NULL,
&req,
symlink_path,
UV_FS_UTIME_OMIT,
UV_FS_UTIME_NOW,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(symlink_path, atime, UV_FS_UTIME_NOW, /* test_lutime */ 1);
/* Test the asynchronous version. */ /* Test the asynchronous version. */
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 */ atime = mtime = 1291404900; /* 2010-12-03 20:35:00 */
@ -2909,11 +3089,12 @@ TEST_IMPL(fs_lutime) {
checkme.atime = atime; checkme.atime = atime;
checkme.mtime = mtime; checkme.mtime = mtime;
checkme.path = symlink_path; checkme.path = symlink_path;
req.data = &checkme;
r = uv_fs_lutime(loop, &req, symlink_path, atime, mtime, lutime_cb); r = uv_fs_lutime(loop, &req, symlink_path, atime, mtime, lutime_cb);
ASSERT_OK(r); ASSERT_OK(r);
uv_run(loop, UV_RUN_DEFAULT); uv_run(loop, UV_RUN_DEFAULT);
ASSERT_EQ(2, lutime_cb_count); ASSERT_EQ(1, lutime_cb_count);
/* Cleanup. */ /* Cleanup. */
unlink(path); unlink(path);

View file

@ -33,6 +33,7 @@ TEST_DECLARE (loop_stop_before_run)
TEST_DECLARE (loop_update_time) TEST_DECLARE (loop_update_time)
TEST_DECLARE (loop_backend_timeout) TEST_DECLARE (loop_backend_timeout)
TEST_DECLARE (loop_configure) TEST_DECLARE (loop_configure)
TEST_DECLARE (loop_init_oom)
TEST_DECLARE (default_loop_close) TEST_DECLARE (default_loop_close)
TEST_DECLARE (barrier_1) TEST_DECLARE (barrier_1)
TEST_DECLARE (barrier_2) TEST_DECLARE (barrier_2)
@ -53,7 +54,8 @@ TEST_DECLARE (tty_raw)
TEST_DECLARE (tty_empty_write) TEST_DECLARE (tty_empty_write)
TEST_DECLARE (tty_large_write) TEST_DECLARE (tty_large_write)
TEST_DECLARE (tty_raw_cancel) TEST_DECLARE (tty_raw_cancel)
TEST_DECLARE (tty_duplicate_vt100_fn_key) TEST_DECLARE (tty_duplicate_vt100_fn_key_libuv)
TEST_DECLARE (tty_duplicate_vt100_fn_key_winvt)
TEST_DECLARE (tty_duplicate_alt_modifier_key) TEST_DECLARE (tty_duplicate_alt_modifier_key)
TEST_DECLARE (tty_composing_character) TEST_DECLARE (tty_composing_character)
TEST_DECLARE (tty_cursor_up) TEST_DECLARE (tty_cursor_up)
@ -364,6 +366,7 @@ TEST_DECLARE (fs_mkdtemp)
TEST_DECLARE (fs_mkstemp) TEST_DECLARE (fs_mkstemp)
TEST_DECLARE (fs_fstat) TEST_DECLARE (fs_fstat)
TEST_DECLARE (fs_fstat_stdio) TEST_DECLARE (fs_fstat_stdio)
TEST_DECLARE (fs_fstat_st_dev)
TEST_DECLARE (fs_access) TEST_DECLARE (fs_access)
TEST_DECLARE (fs_chmod) TEST_DECLARE (fs_chmod)
TEST_DECLARE (fs_copyfile) TEST_DECLARE (fs_copyfile)
@ -603,6 +606,7 @@ TASK_LIST_START
TEST_ENTRY (loop_update_time) TEST_ENTRY (loop_update_time)
TEST_ENTRY (loop_backend_timeout) TEST_ENTRY (loop_backend_timeout)
TEST_ENTRY (loop_configure) TEST_ENTRY (loop_configure)
TEST_ENTRY (loop_init_oom)
TEST_ENTRY (default_loop_close) TEST_ENTRY (default_loop_close)
TEST_ENTRY (barrier_1) TEST_ENTRY (barrier_1)
TEST_ENTRY (barrier_2) TEST_ENTRY (barrier_2)
@ -635,7 +639,8 @@ TASK_LIST_START
TEST_ENTRY (tty_empty_write) TEST_ENTRY (tty_empty_write)
TEST_ENTRY (tty_large_write) TEST_ENTRY (tty_large_write)
TEST_ENTRY (tty_raw_cancel) TEST_ENTRY (tty_raw_cancel)
TEST_ENTRY (tty_duplicate_vt100_fn_key) TEST_ENTRY (tty_duplicate_vt100_fn_key_libuv)
TEST_ENTRY (tty_duplicate_vt100_fn_key_winvt)
TEST_ENTRY (tty_duplicate_alt_modifier_key) TEST_ENTRY (tty_duplicate_alt_modifier_key)
TEST_ENTRY (tty_composing_character) TEST_ENTRY (tty_composing_character)
TEST_ENTRY (tty_cursor_up) TEST_ENTRY (tty_cursor_up)
@ -1083,6 +1088,7 @@ TASK_LIST_START
TEST_ENTRY (fs_mkstemp) TEST_ENTRY (fs_mkstemp)
TEST_ENTRY (fs_fstat) TEST_ENTRY (fs_fstat)
TEST_ENTRY (fs_fstat_stdio) TEST_ENTRY (fs_fstat_stdio)
TEST_ENTRY (fs_fstat_st_dev)
TEST_ENTRY (fs_access) TEST_ENTRY (fs_access)
TEST_ENTRY (fs_chmod) TEST_ENTRY (fs_chmod)
TEST_ENTRY (fs_copyfile) TEST_ENTRY (fs_copyfile)

62
deps/uv/test/test-loop-oom.c vendored Normal file
View file

@ -0,0 +1,62 @@
/* Copyright libuv contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
#include <stdlib.h>
#include <string.h>
static int limit;
static int alloc;
static void* t_realloc(void* p, size_t n) {
alloc += n;
if (alloc > limit)
return NULL;
p = realloc(p, n);
ASSERT_NOT_NULL(p);
return p;
}
static void* t_calloc(size_t m, size_t n) {
return t_realloc(NULL, m * n);
}
static void* t_malloc(size_t n) {
return t_realloc(NULL, n);
}
TEST_IMPL(loop_init_oom) {
uv_loop_t loop;
int err;
ASSERT_OK(uv_replace_allocator(t_malloc, t_realloc, t_calloc, free));
for (;;) {
err = uv_loop_init(&loop);
if (err == 0)
break;
ASSERT_EQ(err, UV_ENOMEM);
limit += 8;
alloc = 0;
}
ASSERT_OK(uv_loop_close(&loop));
return 0;
}

View file

@ -59,7 +59,7 @@ static void pipe_client_connect_cb(uv_connect_t* req, int status) {
ASSERT_OK(r); ASSERT_OK(r);
if (*buf == '\0') { /* Linux abstract socket. */ if (*buf == '\0') { /* Linux abstract socket. */
const char expected[] = "\0" TEST_PIPENAME; const char expected[] = "\0" TEST_PIPENAME "\0";
ASSERT_EQ(len, sizeof(expected) - 1); ASSERT_EQ(len, sizeof(expected) - 1);
ASSERT_MEM_EQ(buf, expected, len); ASSERT_MEM_EQ(buf, expected, len);
} else { } else {
@ -223,7 +223,7 @@ TEST_IMPL(pipe_getsockname) {
TEST_IMPL(pipe_getsockname_abstract) { TEST_IMPL(pipe_getsockname_abstract) {
/* TODO(bnoordhuis) Use unique name, susceptible to concurrent test runs. */ /* TODO(bnoordhuis) Use unique name, susceptible to concurrent test runs. */
static const char name[] = "\0" TEST_PIPENAME; static const char name[] = "\0" TEST_PIPENAME "\0";
#if defined(__linux__) #if defined(__linux__)
char buf[256]; char buf[256];
size_t buflen; size_t buflen;

View file

@ -236,21 +236,24 @@ TEST_IMPL(platform_output) {
printf(" version: %s\n", uname.version); printf(" version: %s\n", uname.version);
printf(" machine: %s\n", uname.machine); printf(" machine: %s\n", uname.machine);
ASSERT_OK(uv_getrusage_thread(&rusage)); err = uv_getrusage_thread(&rusage);
ASSERT_UINT64_GE(rusage.ru_utime.tv_sec, 0); if (err != UV_ENOTSUP) {
ASSERT_UINT64_GE(rusage.ru_utime.tv_usec, 0); ASSERT_OK(err);
ASSERT_UINT64_GE(rusage.ru_stime.tv_sec, 0); ASSERT_UINT64_GE(rusage.ru_utime.tv_sec, 0);
ASSERT_UINT64_GE(rusage.ru_stime.tv_usec, 0); ASSERT_UINT64_GE(rusage.ru_utime.tv_usec, 0);
printf("uv_getrusage_thread:\n"); ASSERT_UINT64_GE(rusage.ru_stime.tv_sec, 0);
printf(" user: %llu sec %llu microsec\n", ASSERT_UINT64_GE(rusage.ru_stime.tv_usec, 0);
(unsigned long long) rusage.ru_utime.tv_sec, printf("uv_getrusage_thread:\n");
(unsigned long long) rusage.ru_utime.tv_usec); printf(" user: %llu sec %llu microsec\n",
printf(" system: %llu sec %llu microsec\n", (unsigned long long) rusage.ru_utime.tv_sec,
(unsigned long long) rusage.ru_stime.tv_sec, (unsigned long long) rusage.ru_utime.tv_usec);
(unsigned long long) rusage.ru_stime.tv_usec); printf(" system: %llu sec %llu microsec\n",
printf(" page faults: %llu\n", (unsigned long long) rusage.ru_majflt); (unsigned long long) rusage.ru_stime.tv_sec,
printf(" maximum resident set size: %llu\n", (unsigned long long) rusage.ru_stime.tv_usec);
(unsigned long long) rusage.ru_maxrss); printf(" page faults: %llu\n", (unsigned long long) rusage.ru_majflt);
printf(" maximum resident set size: %llu\n",
(unsigned long long) rusage.ru_maxrss);
}
return 0; return 0;
} }

View file

@ -178,6 +178,10 @@ static void after_work_cb(uv_work_t* req, int status) {
} }
TEST_IMPL(thread_name_threadpool) { TEST_IMPL(thread_name_threadpool) {
#if defined(_AIX) || defined(__PASE__)
RETURN_SKIP("API not available on this platform");
#endif
uv_work_t req; uv_work_t req;
loop = uv_default_loop(); loop = uv_default_loop();
// Just to make sure all workers will be executed // Just to make sure all workers will be executed

View file

@ -131,7 +131,7 @@ static void make_key_event_records(WORD virt_key, DWORD ctr_key_state,
# undef KEV # undef KEV
} }
TEST_IMPL(tty_duplicate_vt100_fn_key) { TEST_IMPL(tty_duplicate_vt100_fn_key_libuv) {
int r; int r;
int ttyin_fd; int ttyin_fd;
uv_tty_t tty_in; uv_tty_t tty_in;
@ -163,6 +163,10 @@ TEST_IMPL(tty_duplicate_vt100_fn_key) {
r = uv_read_start((uv_stream_t*)&tty_in, tty_alloc, tty_read); r = uv_read_start((uv_stream_t*)&tty_in, tty_alloc, tty_read);
ASSERT_OK(r); ASSERT_OK(r);
/*
* libuv has chosen to emit ESC[[A, but other terminals, and even
* Windows itself use a different escape sequence, see the test below.
*/
expect_str = ESC"[[A"; expect_str = ESC"[[A";
expect_nread = strlen(expect_str); expect_nread = strlen(expect_str);
@ -184,6 +188,62 @@ TEST_IMPL(tty_duplicate_vt100_fn_key) {
return 0; return 0;
} }
TEST_IMPL(tty_duplicate_vt100_fn_key_winvt) {
int r;
int ttyin_fd;
uv_tty_t tty_in;
uv_loop_t* loop;
HANDLE handle;
INPUT_RECORD records[2];
DWORD written;
loop = uv_default_loop();
/* Make sure we have an FD that refers to a tty */
handle = CreateFileA("conin$",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
ASSERT_PTR_NE(handle, INVALID_HANDLE_VALUE);
ttyin_fd = _open_osfhandle((intptr_t) handle, 0);
ASSERT_GE(ttyin_fd, 0);
ASSERT_EQ(UV_TTY, uv_guess_handle(ttyin_fd));
r = uv_tty_init(uv_default_loop(), &tty_in, ttyin_fd, 1); /* Readable. */
ASSERT_OK(r);
ASSERT(uv_is_readable((uv_stream_t*) &tty_in));
ASSERT(!uv_is_writable((uv_stream_t*) &tty_in));
r = uv_read_start((uv_stream_t*)&tty_in, tty_alloc, tty_read);
ASSERT_OK(r);
/*
* Some keys, like F1, get are assigned a different value by Windows
* in ENABLE_VIRTUAL_TERMINAL_INPUT mode vs. libuv in the test above.
*/
expect_str = ESC"OP";
expect_nread = strlen(expect_str);
/* Turn on raw mode. */
r = uv_tty_set_mode(&tty_in, UV_TTY_MODE_RAW_VT);
ASSERT_OK(r);
/*
* Send F1 keystroke.
*/
make_key_event_records(VK_F1, 0, TRUE, records);
WriteConsoleInputW(handle, records, ARRAY_SIZE(records), &written);
ASSERT_EQ(written, ARRAY_SIZE(records));
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_duplicate_alt_modifier_key) { TEST_IMPL(tty_duplicate_alt_modifier_key) {
int r; int r;
int ttyin_fd; int ttyin_fd;