mirror of https://github.com/nodejs/node.git
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
parent
95b0e2c133
commit
4e7d82945d
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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
|
||||
-------------------
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 ""
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue