deps: upgrade to libuv 1.23.0

Notable changes:
- Restores compatibility with the old IPC protocol.
- Adds uv_open_osfhandle().
- Adds uv_os_{get,set}priority().

PR-URL: https://github.com/nodejs/node/pull/22365
Fixes: https://github.com/nodejs/node/issues/21671
Fixes: https://github.com/nodejs/node/issues/15433
Refs: https://github.com/nodejs/node/pull/21675
Refs: https://github.com/nodejs/node-addon-api/issues/304
Refs: https://github.com/nodejs/abi-stable-node/issues/318
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
pull/22365/head
cjihrig 2018-08-16 22:14:55 -04:00
parent 95b0e2c133
commit 4e7d82945d
No known key found for this signature in database
GPG Key ID: 7434390BDBE9B9C5
24 changed files with 633 additions and 104 deletions

1
deps/uv/AUTHORS vendored
View File

@ -345,3 +345,4 @@ Peter Johnson <johnson.peter@gmail.com>
Paolo Greppi <paolo.greppi@libpf.com>
Shelley Vohr <shelley.vohr@gmail.com>
Ujjwal Sharma <usharma1998@gmail.com>
Michał Kozakiewicz <michalkozakiewicz3@gmail.com>

View File

@ -98,6 +98,7 @@ set(uv_test_sources
test/test-poll-closesocket.c
test/test-poll-oob.c
test/test-poll.c
test/test-process-priority.c
test/test-process-title-threadsafe.c
test/test-process-title.c
test/test-queue-foreach-delete.c

22
deps/uv/ChangeLog vendored
View File

@ -1,3 +1,25 @@
2018.08.18, Version 1.23.0 (Stable), 7ebb26225f2eaae6db22f4ef34ce76fa16ff89ec
Changes since version 1.22.0:
* win,pipe: restore compatibility with the old IPC framing protocol (Bert
Belder)
* fs: add uv_open_osfhandle (Bartosz Sosnowski)
* doc: update Visual C++ Build Tools URL (Michał Kozakiewicz)
* unix: loop starvation on successful write complete (jBarz)
* win: add uv__getnameinfo_work() error handling (A. Hauptmann)
* win: return UV_ENOMEM from uv_loop_init() (cjihrig)
* unix,win: add uv_os_{get,set}priority() (cjihrig)
* test: fix warning in test-tcp-open (Santiago Gimeno)
2018.07.11, Version 1.22.0 (Stable), 8568f78a777d79d35eb7d6994617267b9fb33967
Changes since version 1.21.0:

1
deps/uv/Makefile.am vendored
View File

@ -224,6 +224,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-poll-close-doesnt-corrupt-stack.c \
test/test-poll-closesocket.c \
test/test-poll-oob.c \
test/test-process-priority.c \
test/test-process-title.c \
test/test-process-title-threadsafe.c \
test/test-queue-foreach-delete.c \

2
deps/uv/README.md vendored
View File

@ -349,7 +349,7 @@ See the [guidelines for contributing][].
[libuv_banner]: https://raw.githubusercontent.com/libuv/libuv/master/img/banner.png
[x32]: https://en.wikipedia.org/wiki/X32_ABI
[Python 2.6 or 2.7]: https://www.python.org/downloads/
[Visual C++ Build Tools]: http://landinghub.visualstudio.com/visual-cpp-build-tools
[Visual C++ Build Tools]: https://visualstudio.microsoft.com/visual-cpp-build-tools/
[Visual Studio 2015 Update 3]: https://www.visualstudio.com/vs/older-downloads/
[Visual Studio 2017]: https://www.visualstudio.com/downloads/
[Git for Windows]: http://git-scm.com/download/win

View File

@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
AC_INIT([libuv], [1.22.0], [https://github.com/libuv/libuv/issues])
AC_INIT([libuv], [1.23.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])

View File

@ -403,6 +403,15 @@ Helper functions
.. versionadded:: 1.12.0
.. c:function:: int uv_open_osfhandle(uv_os_fd_t os_fd)
For a OS-dependent handle, get the file descriptor in the C runtime.
On UNIX, returns the ``os_fd`` intact. On Windows, this calls `_open_osfhandle <https://msdn.microsoft.com/en-us/library/bdts1c9x.aspx>`_.
Note that the return value is still owned by the CRT,
any attempts to close it or to use it after closing the handle may lead to malfunction.
.. versionadded:: 1.23.0
File open constants
-------------------

View File

@ -517,3 +517,31 @@ API
storage required to hold the value.
.. versionadded:: 1.12.0
.. c:function:: int uv_os_getpriority(uv_pid_t pid, int* priority)
Retrieves the scheduling priority of the process specified by `pid`. The
returned value of `priority` is between -20 (high priority) and 19 (low
priority).
.. note::
On Windows, the returned priority will equal one of the `UV_PRIORITY`
constants.
.. versionadded:: 1.23.0
.. c:function:: int uv_os_setpriority(uv_pid_t pid, int priority)
Sets the scheduling priority of the process specified by `pid`. The
`priority` value range is between -20 (high priority) and 19 (low priority).
The constants `UV_PRIORITY_LOW`, `UV_PRIORITY_BELOW_NORMAL`,
`UV_PRIORITY_NORMAL`, `UV_PRIORITY_ABOVE_NORMAL`, `UV_PRIORITY_HIGH`, and
`UV_PRIORITY_HIGHEST` are also provided for convenience.
.. note::
On Windows, this function utilizes `SetPriorityClass()`. The `priority`
argument is mapped to a Windows priority class. When retrieving the
process priority, the result will equal one of the `UV_PRIORITY`
constants, and not necessarily the exact value of `priority`.
.. versionadded:: 1.23.0

11
deps/uv/include/uv.h vendored
View File

@ -1065,6 +1065,7 @@ UV_EXTERN int uv_set_process_title(const char* title);
UV_EXTERN int uv_resident_set_memory(size_t* rss);
UV_EXTERN int uv_uptime(double* uptime);
UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd);
UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_fd);
typedef struct {
long tv_sec;
@ -1099,6 +1100,16 @@ UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd);
UV_EXTERN uv_pid_t uv_os_getpid(void);
UV_EXTERN uv_pid_t uv_os_getppid(void);
#define UV_PRIORITY_LOW 19
#define UV_PRIORITY_BELOW_NORMAL 10
#define UV_PRIORITY_NORMAL 0
#define UV_PRIORITY_ABOVE_NORMAL -7
#define UV_PRIORITY_HIGH -14
#define UV_PRIORITY_HIGHEST -20
UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority);
UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);

View File

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

View File

@ -1338,6 +1338,9 @@ uv_os_fd_t uv_get_osfhandle(int fd) {
return fd;
}
int uv_open_osfhandle(uv_os_fd_t os_fd) {
return os_fd;
}
uv_pid_t uv_os_getpid(void) {
return getpid();
@ -1347,3 +1350,31 @@ uv_pid_t uv_os_getpid(void) {
uv_pid_t uv_os_getppid(void) {
return getppid();
}
int uv_os_getpriority(uv_pid_t pid, int* priority) {
int r;
if (priority == NULL)
return UV_EINVAL;
errno = 0;
r = getpriority(PRIO_PROCESS, (int) pid);
if (r == -1 && errno != 0)
return UV__ERR(errno);
*priority = r;
return 0;
}
int uv_os_setpriority(uv_pid_t pid, int priority) {
if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
return UV_EINVAL;
if (setpriority(PRIO_PROCESS, (int) pid, priority) != 0)
return UV__ERR(errno);
return 0;
}

View File

@ -950,10 +950,16 @@ error:
static void uv__write_callbacks(uv_stream_t* stream) {
uv_write_t* req;
QUEUE* q;
QUEUE pq;
while (!QUEUE_EMPTY(&stream->write_completed_queue)) {
if (QUEUE_EMPTY(&stream->write_completed_queue))
return;
QUEUE_MOVE(&stream->write_completed_queue, &pq);
while (!QUEUE_EMPTY(&pq)) {
/* Pop a req off write_completed_queue. */
q = QUEUE_HEAD(&stream->write_completed_queue);
q = QUEUE_HEAD(&pq);
req = QUEUE_DATA(q, uv_write_t, queue);
QUEUE_REMOVE(q);
uv__req_unregister(stream->loop, req);
@ -969,8 +975,6 @@ static void uv__write_callbacks(uv_stream_t* stream) {
if (req->cb)
req->cb(req, req->error);
}
assert(QUEUE_EMPTY(&stream->write_completed_queue));
}

View File

@ -249,8 +249,10 @@ int uv_loop_init(uv_loop_t* loop) {
loop->endgame_handles = NULL;
loop->timer_heap = timer_heap = uv__malloc(sizeof(*timer_heap));
if (timer_heap == NULL)
if (timer_heap == NULL) {
err = UV_ENOMEM;
goto fail_timers_alloc;
}
heap_init(timer_heap);

View File

@ -42,7 +42,7 @@ static void uv__getnameinfo_work(struct uv__work* w) {
uv_getnameinfo_t* req;
WCHAR host[NI_MAXHOST];
WCHAR service[NI_MAXSERV];
int ret = 0;
int ret;
req = container_of(w, uv_getnameinfo_t, work_req);
if (GetNameInfoW((struct sockaddr*)&req->storage,
@ -53,27 +53,34 @@ static void uv__getnameinfo_work(struct uv__work* w) {
ARRAY_SIZE(service),
req->flags)) {
ret = WSAGetLastError();
req->retcode = uv__getaddrinfo_translate_error(ret);
return;
}
req->retcode = uv__getaddrinfo_translate_error(ret);
/* convert results to UTF-8 */
WideCharToMultiByte(CP_UTF8,
0,
host,
-1,
req->host,
sizeof(req->host),
NULL,
NULL);
ret = WideCharToMultiByte(CP_UTF8,
0,
host,
-1,
req->host,
sizeof(req->host),
NULL,
NULL);
if (ret == 0) {
req->retcode = uv_translate_sys_error(GetLastError());
return;
}
WideCharToMultiByte(CP_UTF8,
0,
service,
-1,
req->service,
sizeof(req->service),
NULL,
NULL);
ret = WideCharToMultiByte(CP_UTF8,
0,
service,
-1,
req->service,
sizeof(req->service),
NULL,
NULL);
if (ret == 0) {
req->retcode = uv_translate_sys_error(GetLastError());
}
}

View File

@ -157,3 +157,7 @@ int uv_is_closing(const uv_handle_t* handle) {
uv_os_fd_t uv_get_osfhandle(int fd) {
return uv__get_osfhandle(fd);
}
int uv_open_osfhandle(uv_os_fd_t os_fd) {
return _open_osfhandle((intptr_t) os_fd, 0);
}

View File

@ -61,10 +61,15 @@ extern UV_THREAD_LOCAL int uv__crt_assert_enabled;
* TCP
*/
typedef enum {
UV__IPC_SOCKET_XFER_NONE = 0,
UV__IPC_SOCKET_XFER_TCP_CONNECTION,
UV__IPC_SOCKET_XFER_TCP_SERVER
} uv__ipc_socket_xfer_type_t;
typedef struct {
WSAPROTOCOL_INFOW socket_info;
uint32_t delayed_error;
uint32_t flags; /* Either zero or UV_HANDLE_CONNECTION. */
} uv__ipc_socket_xfer_info_t;
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
@ -89,8 +94,11 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
int uv__tcp_xfer_export(uv_tcp_t* handle,
int pid,
uv__ipc_socket_xfer_type_t* xfer_type,
uv__ipc_socket_xfer_info_t* xfer_info);
int uv__tcp_xfer_import(uv_tcp_t* tcp,
uv__ipc_socket_xfer_type_t xfer_type,
uv__ipc_socket_xfer_info_t* xfer_info);
int uv__tcp_xfer_import(uv_tcp_t* tcp, uv__ipc_socket_xfer_info_t* xfer_info);
/*

176
deps/uv/src/win/pipe.c vendored
View File

@ -25,11 +25,12 @@
#include <stdlib.h>
#include <string.h>
#include "uv.h"
#include "internal.h"
#include "handle-inl.h"
#include "stream-inl.h"
#include "internal.h"
#include "req-inl.h"
#include "stream-inl.h"
#include "uv-common.h"
#include "uv.h"
#include <aclapi.h>
#include <accctrl.h>
@ -52,19 +53,36 @@ static const int pipe_prefix_len = sizeof(pipe_prefix) - 1;
/* IPC incoming xfer queue item. */
typedef struct {
uv__ipc_socket_xfer_type_t xfer_type;
uv__ipc_socket_xfer_info_t xfer_info;
QUEUE member;
} uv__ipc_xfer_queue_item_t;
/* IPC frame types. */
enum { UV__IPC_DATA_FRAME = 0, UV__IPC_XFER_FRAME = 1 };
/* IPC frame header flags. */
/* clang-format off */
enum {
UV__IPC_FRAME_HAS_DATA = 0x01,
UV__IPC_FRAME_HAS_SOCKET_XFER = 0x02,
UV__IPC_FRAME_XFER_IS_TCP_CONNECTION = 0x04,
/* These are combinations of the flags above. */
UV__IPC_FRAME_XFER_FLAGS = 0x06,
UV__IPC_FRAME_VALID_FLAGS = 0x07
};
/* clang-format on */
/* IPC frame header. */
typedef struct {
uint32_t type;
uint32_t payload_length;
uint32_t flags;
uint32_t reserved1; /* Ignored. */
uint32_t data_length; /* Must be zero if there is no data. */
uint32_t reserved2; /* Must be zero. */
} uv__ipc_frame_header_t;
/* To implement the IPC protocol correctly, these structures must have exactly
* the right size. */
STATIC_ASSERT(sizeof(uv__ipc_frame_header_t) == 16);
STATIC_ASSERT(sizeof(uv__ipc_socket_xfer_info_t) == 632);
/* Coalesced write request. */
typedef struct {
uv_write_t req; /* Internal heap-allocated write request. */
@ -878,7 +896,8 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
server->pipe.conn.ipc_xfer_queue_length--;
item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
err = uv__tcp_xfer_import((uv_tcp_t*) client, &item->xfer_info);
err = uv__tcp_xfer_import(
(uv_tcp_t*) client, item->xfer_type, &item->xfer_info);
if (err != 0)
return err;
@ -1458,10 +1477,10 @@ int uv__pipe_write_ipc(uv_loop_t* loop,
uv_buf_t stack_bufs[6];
uv_buf_t* bufs;
size_t buf_count, buf_index;
uv__ipc_frame_header_t xfer_frame_header;
uv__ipc_frame_header_t frame_header;
uv__ipc_socket_xfer_type_t xfer_type = UV__IPC_SOCKET_XFER_NONE;
uv__ipc_socket_xfer_info_t xfer_info;
uv__ipc_frame_header_t data_frame_header;
size_t data_length;
uint64_t data_length;
size_t i;
int err;
@ -1472,8 +1491,8 @@ int uv__pipe_write_ipc(uv_loop_t* loop,
if (data_length > UINT32_MAX)
return WSAENOBUFS; /* Maps to UV_ENOBUFS. */
/* Prepare xfer frame payload. */
if (send_handle) {
/* Prepare the frame's socket xfer payload. */
if (send_handle != NULL) {
uv_tcp_t* send_tcp_handle = (uv_tcp_t*) send_handle;
/* Verify that `send_handle` it is indeed a tcp handle. */
@ -1481,20 +1500,18 @@ int uv__pipe_write_ipc(uv_loop_t* loop,
return ERROR_NOT_SUPPORTED;
/* Export the tcp handle. */
err = uv__tcp_xfer_export(
send_tcp_handle, uv__pipe_get_ipc_remote_pid(handle), &xfer_info);
err = uv__tcp_xfer_export(send_tcp_handle,
uv__pipe_get_ipc_remote_pid(handle),
&xfer_type,
&xfer_info);
if (err != 0)
return err;
}
/* Compute the number of uv_buf_t's required. */
buf_count = 0;
if (send_handle != NULL) {
buf_count += 2; /* One for the frame header, one for the payload. */
}
if (data_buf_count > 0) {
buf_count += 1 + data_buf_count; /* One extra for the frame header. */
}
buf_count = 1 + data_buf_count; /* Frame header and data buffers. */
if (send_handle != NULL)
buf_count += 1; /* One extra for the socket xfer information. */
/* Use the on-stack buffer array if it is big enough; otherwise allocate
* space for it on the heap. */
@ -1509,25 +1526,32 @@ int uv__pipe_write_ipc(uv_loop_t* loop,
}
buf_index = 0;
if (send_handle != NULL) {
/* Add xfer frame header. */
xfer_frame_header.type = UV__IPC_XFER_FRAME;
xfer_frame_header.payload_length = sizeof xfer_info;
bufs[buf_index++] =
uv_buf_init((char*) &xfer_frame_header, sizeof xfer_frame_header);
/* Initialize frame header and add it to the buffers list. */
memset(&frame_header, 0, sizeof frame_header);
bufs[buf_index++] = uv_buf_init((char*) &frame_header, sizeof frame_header);
/* Add xfer frame payload. */
if (send_handle != NULL) {
/* Add frame header flags. */
switch (xfer_type) {
case UV__IPC_SOCKET_XFER_TCP_CONNECTION:
frame_header.flags |= UV__IPC_FRAME_HAS_SOCKET_XFER |
UV__IPC_FRAME_XFER_IS_TCP_CONNECTION;
break;
case UV__IPC_SOCKET_XFER_TCP_SERVER:
frame_header.flags |= UV__IPC_FRAME_HAS_SOCKET_XFER;
break;
default:
assert(0); // Unreachable.
}
/* Add xfer info buffer. */
bufs[buf_index++] = uv_buf_init((char*) &xfer_info, sizeof xfer_info);
}
if (data_length > 0) {
/* Add data frame header. */
data_frame_header.type = UV__IPC_DATA_FRAME;
data_frame_header.payload_length = (uint32_t) data_length;
bufs[buf_index++] =
uv_buf_init((char*) &data_frame_header, sizeof data_frame_header);
/* Add data buffers. */
/* Update frame header. */
frame_header.flags |= UV__IPC_FRAME_HAS_DATA;
frame_header.data_length = (uint32_t) data_length;
/* Add data buffers to buffers list. */
for (i = 0; i < data_buf_count; i++)
bufs[buf_index++] = data_bufs[i];
}
@ -1601,14 +1625,18 @@ static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
static void uv__pipe_queue_ipc_xfer_info(
uv_pipe_t* handle, uv__ipc_socket_xfer_info_t* xfer_info) {
uv_pipe_t* handle,
uv__ipc_socket_xfer_type_t xfer_type,
uv__ipc_socket_xfer_info_t* xfer_info) {
uv__ipc_xfer_queue_item_t* item;
item = (uv__ipc_xfer_queue_item_t*) uv__malloc(sizeof(*item));
if (item == NULL)
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
memcpy(&item->xfer_info, xfer_info, sizeof(item->xfer_info));
item->xfer_type = xfer_type;
item->xfer_info = *xfer_info;
QUEUE_INSERT_TAIL(&handle->pipe.conn.ipc_xfer_queue, &item->member);
handle->pipe.conn.ipc_xfer_queue_length++;
}
@ -1678,7 +1706,7 @@ static DWORD uv__pipe_read_ipc(uv_loop_t* loop, uv_pipe_t* handle) {
int err;
if (*data_remaining > 0) {
/* Read data frame payload. */
/* Read frame data payload. */
DWORD bytes_read =
uv__pipe_read_data(loop, handle, *data_remaining, *data_remaining);
*data_remaining -= bytes_read;
@ -1687,6 +1715,8 @@ static DWORD uv__pipe_read_ipc(uv_loop_t* loop, uv_pipe_t* handle) {
} else {
/* Start of a new IPC frame. */
uv__ipc_frame_header_t frame_header;
uint32_t xfer_flags;
uv__ipc_socket_xfer_type_t xfer_type;
uv__ipc_socket_xfer_info_t xfer_info;
/* Read the IPC frame header. */
@ -1695,33 +1725,57 @@ static DWORD uv__pipe_read_ipc(uv_loop_t* loop, uv_pipe_t* handle) {
if (err)
goto error;
if (frame_header.type == UV__IPC_DATA_FRAME) {
/* Data frame: capture payload length. Actual data will be read in
* subsequent call to uv__pipe_read_ipc(). */
*data_remaining = frame_header.payload_length;
/* Validate that flags are valid. */
if ((frame_header.flags & ~UV__IPC_FRAME_VALID_FLAGS) != 0)
goto invalid;
/* Validate that reserved2 is zero. */
if (frame_header.reserved2 != 0)
goto invalid;
/* Return number of bytes read. */
return sizeof frame_header;
} else if (frame_header.type == UV__IPC_XFER_FRAME) {
/* Xfer frame: read the payload. */
assert(frame_header.payload_length == sizeof xfer_info);
err =
uv__pipe_read_exactly(handle->handle, &xfer_info, sizeof xfer_info);
if (err)
goto error;
/* Store the pending socket info. */
uv__pipe_queue_ipc_xfer_info(handle, &xfer_info);
/* Return number of bytes read. */
return sizeof frame_header + sizeof xfer_info;
/* Parse xfer flags. */
xfer_flags = frame_header.flags & UV__IPC_FRAME_XFER_FLAGS;
if (xfer_flags & UV__IPC_FRAME_HAS_SOCKET_XFER) {
/* Socket coming -- determine the type. */
xfer_type = xfer_flags & UV__IPC_FRAME_XFER_IS_TCP_CONNECTION
? UV__IPC_SOCKET_XFER_TCP_CONNECTION
: UV__IPC_SOCKET_XFER_TCP_SERVER;
} else if (xfer_flags == 0) {
/* No socket. */
xfer_type = UV__IPC_SOCKET_XFER_NONE;
} else {
/* Invalid flags. */
goto invalid;
}
/* Invalid frame. */
err = WSAECONNABORTED; /* Maps to UV_ECONNABORTED. */
/* Parse data frame information. */
if (frame_header.flags & UV__IPC_FRAME_HAS_DATA) {
*data_remaining = frame_header.data_length;
} else if (frame_header.data_length != 0) {
/* Data length greater than zero but data flag not set -- invalid. */
goto invalid;
}
/* If no socket xfer info follows, return here. Data will be read in a
* subsequent invocation of uv__pipe_read_ipc(). */
if (xfer_type == UV__IPC_SOCKET_XFER_NONE)
return sizeof frame_header; /* Number of bytes read. */
/* Read transferred socket information. */
err = uv__pipe_read_exactly(handle->handle, &xfer_info, sizeof xfer_info);
if (err)
goto error;
/* Store the pending socket info. */
uv__pipe_queue_ipc_xfer_info(handle, xfer_type, &xfer_info);
/* Return number of bytes read. */
return sizeof frame_header + sizeof xfer_info;
}
invalid:
/* Invalid frame. */
err = WSAECONNABORTED; /* Maps to UV_ECONNABORTED. */
error:
uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);
return 0; /* Break out of read loop. */

34
deps/uv/src/win/tcp.c vendored
View File

@ -1191,8 +1191,12 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
int uv__tcp_xfer_export(uv_tcp_t* handle,
int target_pid,
uv__ipc_socket_xfer_type_t* xfer_type,
uv__ipc_socket_xfer_info_t* xfer_info) {
if (!(handle->flags & UV_HANDLE_CONNECTION)) {
if (handle->flags & UV_HANDLE_CONNECTION) {
*xfer_type = UV__IPC_SOCKET_XFER_TCP_CONNECTION;
} else {
*xfer_type = UV__IPC_SOCKET_XFER_TCP_SERVER;
/* We're about to share the socket with another process. Because this is a
* listening socket, we assume that the other process will be accepting
* connections on it. Thus, before sharing the socket with another process,
@ -1208,12 +1212,9 @@ int uv__tcp_xfer_export(uv_tcp_t* handle,
}
}
if (WSADuplicateSocketW(
handle->socket, target_pid, &xfer_info->socket_info)) {
if (WSADuplicateSocketW(handle->socket, target_pid, &xfer_info->socket_info))
return WSAGetLastError();
}
xfer_info->delayed_error = handle->delayed_error;
xfer_info->flags = handle->flags & UV_HANDLE_CONNECTION;
/* Mark the local copy of the handle as 'shared' so we behave in a way that's
* friendly to the process(es) that we share the socket with. */
@ -1223,14 +1224,21 @@ int uv__tcp_xfer_export(uv_tcp_t* handle,
}
int uv__tcp_xfer_import(uv_tcp_t* tcp, uv__ipc_socket_xfer_info_t* xfer_info) {
int uv__tcp_xfer_import(uv_tcp_t* tcp,
uv__ipc_socket_xfer_type_t xfer_type,
uv__ipc_socket_xfer_info_t* xfer_info) {
int err;
SOCKET socket = WSASocketW(FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
&xfer_info->socket_info,
0,
WSA_FLAG_OVERLAPPED);
SOCKET socket;
assert(xfer_type == UV__IPC_SOCKET_XFER_TCP_SERVER ||
xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION);
socket = WSASocketW(FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO,
&xfer_info->socket_info,
0,
WSA_FLAG_OVERLAPPED);
if (socket == INVALID_SOCKET) {
return WSAGetLastError();
@ -1246,7 +1254,7 @@ int uv__tcp_xfer_import(uv_tcp_t* tcp, uv__ipc_socket_xfer_info_t* xfer_info) {
tcp->delayed_error = xfer_info->delayed_error;
tcp->flags |= UV_HANDLE_BOUND | UV_HANDLE_SHARED_TCP_SOCKET;
if (xfer_info->flags & UV_HANDLE_CONNECTION) {
if (xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION) {
uv_connection_init((uv_stream_t*)tcp);
tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
}

View File

@ -1530,3 +1530,97 @@ int uv_os_gethostname(char* buffer, size_t* size) {
*size = len;
return 0;
}
static int uv__get_handle(uv_pid_t pid, int access, HANDLE* handle) {
int r;
if (pid == 0)
*handle = GetCurrentProcess();
else
*handle = OpenProcess(access, FALSE, pid);
if (*handle == NULL) {
r = GetLastError();
if (r == ERROR_INVALID_PARAMETER)
return UV_ESRCH;
else
return uv_translate_sys_error(r);
}
return 0;
}
int uv_os_getpriority(uv_pid_t pid, int* priority) {
HANDLE handle;
int r;
if (priority == NULL)
return UV_EINVAL;
r = uv__get_handle(pid, PROCESS_QUERY_LIMITED_INFORMATION, &handle);
if (r != 0)
return r;
r = GetPriorityClass(handle);
if (r == 0) {
r = uv_translate_sys_error(GetLastError());
} else {
/* Map Windows priority classes to Unix nice values. */
if (r == REALTIME_PRIORITY_CLASS)
*priority = UV_PRIORITY_HIGHEST;
else if (r == HIGH_PRIORITY_CLASS)
*priority = UV_PRIORITY_HIGH;
else if (r == ABOVE_NORMAL_PRIORITY_CLASS)
*priority = UV_PRIORITY_ABOVE_NORMAL;
else if (r == NORMAL_PRIORITY_CLASS)
*priority = UV_PRIORITY_NORMAL;
else if (r == BELOW_NORMAL_PRIORITY_CLASS)
*priority = UV_PRIORITY_BELOW_NORMAL;
else /* IDLE_PRIORITY_CLASS */
*priority = UV_PRIORITY_LOW;
r = 0;
}
CloseHandle(handle);
return r;
}
int uv_os_setpriority(uv_pid_t pid, int priority) {
HANDLE handle;
int priority_class;
int r;
/* Map Unix nice values to Windows priority classes. */
if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
return UV_EINVAL;
else if (priority < UV_PRIORITY_HIGH)
priority_class = REALTIME_PRIORITY_CLASS;
else if (priority < UV_PRIORITY_ABOVE_NORMAL)
priority_class = HIGH_PRIORITY_CLASS;
else if (priority < UV_PRIORITY_NORMAL)
priority_class = ABOVE_NORMAL_PRIORITY_CLASS;
else if (priority < UV_PRIORITY_BELOW_NORMAL)
priority_class = NORMAL_PRIORITY_CLASS;
else if (priority < UV_PRIORITY_LOW)
priority_class = BELOW_NORMAL_PRIORITY_CLASS;
else
priority_class = IDLE_PRIORITY_CLASS;
r = uv__get_handle(pid, PROCESS_SET_INFORMATION, &handle);
if (r != 0)
return r;
if (SetPriorityClass(handle, priority_class) == 0)
r = uv_translate_sys_error(GetLastError());
CloseHandle(handle);
return r;
}

View File

@ -3069,6 +3069,52 @@ TEST_IMPL(get_osfhandle_valid_handle) {
return 0;
}
TEST_IMPL(open_osfhandle_valid_handle) {
int r;
uv_os_fd_t handle;
int fd;
/* Setup. */
unlink("test_file");
loop = uv_default_loop();
r = uv_fs_open(NULL,
&open_req1,
"test_file",
O_RDWR | O_CREAT,
S_IWUSR | S_IRUSR,
NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
handle = uv_get_osfhandle(open_req1.result);
#ifdef _WIN32
ASSERT(handle != INVALID_HANDLE_VALUE);
#else
ASSERT(handle >= 0);
#endif
fd = uv_open_osfhandle(handle);
#ifdef _WIN32
ASSERT(fd > 0);
#else
ASSERT(fd == open_req1.result);
#endif
r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
ASSERT(r == 0);
ASSERT(close_req.result == 0);
uv_fs_req_cleanup(&close_req);
/* Cleanup. */
unlink("test_file");
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(fs_file_pos_after_op_with_offset) {
int r;

View File

@ -121,6 +121,7 @@ TEST_DECLARE (tcp_bind6_error_addrnotavail)
TEST_DECLARE (tcp_bind6_error_fault)
TEST_DECLARE (tcp_bind6_error_inval)
TEST_DECLARE (tcp_bind6_localhost_ok)
TEST_DECLARE (tcp_write_ready)
TEST_DECLARE (udp_alloc_cb_fail)
TEST_DECLARE (udp_bind)
TEST_DECLARE (udp_bind_reuseaddr)
@ -213,6 +214,7 @@ TEST_DECLARE (pipe_close_stdout_read_stdin)
TEST_DECLARE (pipe_set_non_blocking)
TEST_DECLARE (pipe_set_chmod)
TEST_DECLARE (process_ref)
TEST_DECLARE (process_priority)
TEST_DECLARE (has_ref)
TEST_DECLARE (active)
TEST_DECLARE (embed)
@ -334,6 +336,7 @@ TEST_DECLARE (fs_rename_to_existing_file)
TEST_DECLARE (fs_write_multiple_bufs)
TEST_DECLARE (fs_read_write_null_arguments)
TEST_DECLARE (get_osfhandle_valid_handle)
TEST_DECLARE (open_osfhandle_valid_handle)
TEST_DECLARE (fs_write_alotof_bufs)
TEST_DECLARE (fs_write_alotof_bufs_with_offset)
TEST_DECLARE (fs_file_pos_after_op_with_offset)
@ -544,6 +547,8 @@ TASK_LIST_START
TEST_ENTRY (tcp_open_bound)
TEST_ENTRY (tcp_open_connected)
TEST_HELPER (tcp_open_connected, tcp4_echo_server)
TEST_ENTRY (tcp_write_ready)
TEST_HELPER (tcp_write_ready, tcp4_echo_server)
TEST_ENTRY (tcp_shutdown_after_write)
TEST_HELPER (tcp_shutdown_after_write, tcp4_echo_server)
@ -685,6 +690,7 @@ TASK_LIST_START
TEST_ENTRY (pipe_ref4)
TEST_HELPER (pipe_ref4, pipe_echo_server)
TEST_ENTRY (process_ref)
TEST_ENTRY (process_priority)
TEST_ENTRY (has_ref)
TEST_ENTRY (loop_handles)
@ -887,6 +893,7 @@ TASK_LIST_START
TEST_ENTRY (fs_fchmod_archive_readonly)
#endif
TEST_ENTRY (get_osfhandle_valid_handle)
TEST_ENTRY (open_osfhandle_valid_handle)
TEST_ENTRY (threadpool_queue_work_simple)
TEST_ENTRY (threadpool_queue_work_einval)
TEST_ENTRY (threadpool_multiple_event_loops)

View File

@ -0,0 +1,81 @@
/* 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"
TEST_IMPL(process_priority) {
int priority;
int r;
int i;
#if defined(__MVS__)
if (uv_os_setpriority(0, 0) == UV_ENOSYS)
RETURN_SKIP("functionality not supported on zOS");
#endif
/* Verify that passing a NULL pointer returns UV_EINVAL. */
r = uv_os_getpriority(0, NULL);
ASSERT(r == UV_EINVAL);
/* Verify that all valid values work. */
for (i = UV_PRIORITY_HIGHEST; i <= UV_PRIORITY_LOW; i++) {
r = uv_os_setpriority(0, i);
/* If UV_EACCES is returned, the current user doesn't have permission to
set this specific priority. */
if (r == UV_EACCES)
continue;
ASSERT(r == 0);
ASSERT(uv_os_getpriority(0, &priority) == 0);
/* Verify that the priority values match on Unix, and are range mapped
on Windows. */
#ifndef _WIN32
ASSERT(priority == i);
#else
if (i < UV_PRIORITY_HIGH)
ASSERT(priority == UV_PRIORITY_HIGHEST);
else if (i < UV_PRIORITY_ABOVE_NORMAL)
ASSERT(priority == UV_PRIORITY_HIGH);
else if (i < UV_PRIORITY_NORMAL)
ASSERT(priority == UV_PRIORITY_ABOVE_NORMAL);
else if (i < UV_PRIORITY_BELOW_NORMAL)
ASSERT(priority == UV_PRIORITY_NORMAL);
else if (i < UV_PRIORITY_LOW)
ASSERT(priority == UV_PRIORITY_BELOW_NORMAL);
else
ASSERT(priority == UV_PRIORITY_LOW);
#endif
/* Verify that the current PID and 0 are equivalent. */
ASSERT(uv_os_getpriority(uv_os_getpid(), &r) == 0);
ASSERT(priority == r);
}
/* Verify that invalid priorities return UV_EINVAL. */
ASSERT(uv_os_setpriority(0, UV_PRIORITY_HIGHEST - 1) == UV_EINVAL);
ASSERT(uv_os_setpriority(0, UV_PRIORITY_LOW + 1) == UV_EINVAL);
return 0;
}

View File

@ -30,6 +30,7 @@
#endif
static int shutdown_cb_called = 0;
static int shutdown_requested = 0;
static int connect_cb_called = 0;
static int write_cb_called = 0;
static int close_cb_called = 0;
@ -37,6 +38,8 @@ static int close_cb_called = 0;
static uv_connect_t connect_req;
static uv_shutdown_t shutdown_req;
static uv_write_t write_req;
static uv_timer_t tm;
static uv_tcp_t client;
static void startup(void) {
@ -115,6 +118,20 @@ static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
ASSERT(memcmp("PING", buf->base, nread) == 0);
}
else {
ASSERT(nread == UV_EOF);
uv_close((uv_handle_t*)tcp, close_cb);
}
}
static void read1_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
int i;
ASSERT(tcp != NULL);
if (nread >= 0) {
for (i = 0; i < nread; ++i)
ASSERT(buf->base[i] == 'P');
} else {
ASSERT(nread == UV_EOF);
printf("GOT EOF\n");
uv_close((uv_handle_t*)tcp, close_cb);
@ -134,6 +151,37 @@ static void write_cb(uv_write_t* req, int status) {
}
static void write1_cb(uv_write_t* req, int status) {
uv_buf_t buf;
int r;
ASSERT(req != NULL);
if (status) {
ASSERT(shutdown_cb_called);
return;
}
if (shutdown_requested)
return;
buf = uv_buf_init("P", 1);
r = uv_write(&write_req, req->handle, &buf, 1, write1_cb);
ASSERT(r == 0);
write_cb_called++;
}
static void timer_cb(uv_timer_t* handle) {
int r;
/* Shutdown on drain. */
r = uv_shutdown(&shutdown_req, (uv_stream_t*) &client, shutdown_cb);
ASSERT(r == 0);
shutdown_requested++;
}
static void connect_cb(uv_connect_t* req, int status) {
uv_buf_t buf = uv_buf_init("PING", 4);
uv_stream_t* stream;
@ -158,9 +206,35 @@ static void connect_cb(uv_connect_t* req, int status) {
}
static void connect1_cb(uv_connect_t* req, int status) {
uv_buf_t buf;
uv_stream_t* stream;
int r;
ASSERT(req == &connect_req);
ASSERT(status == 0);
stream = req->handle;
connect_cb_called++;
r = uv_timer_init(uv_default_loop(), &tm);
ASSERT(r == 0);
r = uv_timer_start(&tm, timer_cb, 2000, 0);
ASSERT(r == 0);
buf = uv_buf_init("P", 1);
r = uv_write(&write_req, stream, &buf, 1, write1_cb);
ASSERT(r == 0);
/* Start reading */
r = uv_read_start(stream, alloc_cb, read1_cb);
ASSERT(r == 0);
}
TEST_IMPL(tcp_open) {
struct sockaddr_in addr;
uv_tcp_t client;
uv_os_sock_t sock;
int r;
@ -289,3 +363,38 @@ TEST_IMPL(tcp_open_connected) {
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(tcp_write_ready) {
struct sockaddr_in addr;
uv_os_sock_t sock;
int r;
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
startup();
sock = create_tcp_socket();
r = uv_tcp_init(uv_default_loop(), &client);
ASSERT(r == 0);
r = uv_tcp_open(&client, sock);
ASSERT(r == 0);
r = uv_tcp_connect(&connect_req,
&client,
(const struct sockaddr*) &addr,
connect1_cb);
ASSERT(r == 0);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(shutdown_cb_called == 1);
ASSERT(shutdown_requested == 1);
ASSERT(connect_cb_called == 1);
ASSERT(write_cb_called > 0);
ASSERT(close_cb_called == 1);
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -80,6 +80,7 @@
'test-poll-close-doesnt-corrupt-stack.c',
'test-poll-closesocket.c',
'test-poll-oob.c',
'test-process-priority.c',
'test-process-title.c',
'test-process-title-threadsafe.c',
'test-queue-foreach-delete.c',