summaryrefslogtreecommitdiff
path: root/deps/uv
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2018-08-16 22:14:55 -0400
committercjihrig <cjihrig@gmail.com>2018-08-20 08:39:30 -0400
commit4e7d82945dfc3f9e264c258ef29c45910b7fd8bc (patch)
tree5f0cd0d759bc8e5075b672b3d410757103330ca8 /deps/uv
parent95b0e2c1331415e18d171d60d843a2c1328ffbe3 (diff)
downloadandroid-node-v8-4e7d82945dfc3f9e264c258ef29c45910b7fd8bc.tar.gz
android-node-v8-4e7d82945dfc3f9e264c258ef29c45910b7fd8bc.tar.bz2
android-node-v8-4e7d82945dfc3f9e264c258ef29c45910b7fd8bc.zip
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>
Diffstat (limited to 'deps/uv')
-rw-r--r--deps/uv/AUTHORS1
-rw-r--r--deps/uv/CMakeLists.txt1
-rw-r--r--deps/uv/ChangeLog22
-rw-r--r--deps/uv/Makefile.am1
-rw-r--r--deps/uv/README.md2
-rw-r--r--deps/uv/configure.ac2
-rw-r--r--deps/uv/docs/src/fs.rst9
-rw-r--r--deps/uv/docs/src/misc.rst28
-rw-r--r--deps/uv/include/uv.h11
-rw-r--r--deps/uv/include/uv/version.h2
-rw-r--r--deps/uv/src/unix/core.c31
-rw-r--r--deps/uv/src/unix/stream.c12
-rw-r--r--deps/uv/src/win/core.c4
-rw-r--r--deps/uv/src/win/getnameinfo.c49
-rw-r--r--deps/uv/src/win/handle.c4
-rw-r--r--deps/uv/src/win/internal.h12
-rw-r--r--deps/uv/src/win/pipe.c172
-rw-r--r--deps/uv/src/win/tcp.c34
-rw-r--r--deps/uv/src/win/util.c94
-rw-r--r--deps/uv/test/test-fs.c46
-rw-r--r--deps/uv/test/test-list.h7
-rw-r--r--deps/uv/test/test-process-priority.c81
-rw-r--r--deps/uv/test/test-tcp-open.c111
-rw-r--r--deps/uv/test/test.gyp1
24 files changed, 633 insertions, 104 deletions
diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS
index ef3d5e181a..0ba7c06768 100644
--- a/deps/uv/AUTHORS
+++ b/deps/uv/AUTHORS
@@ -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>
diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt
index a133edb850..4f13efc8e6 100644
--- a/deps/uv/CMakeLists.txt
+++ b/deps/uv/CMakeLists.txt
@@ -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
diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog
index acf42e0123..b57cea4baf 100644
--- a/deps/uv/ChangeLog
+++ b/deps/uv/ChangeLog
@@ -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:
diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am
index 04aecab555..a217faab3c 100644
--- a/deps/uv/Makefile.am
+++ b/deps/uv/Makefile.am
@@ -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 \
diff --git a/deps/uv/README.md b/deps/uv/README.md
index f6e7288ded..cb9e26c1e0 100644
--- a/deps/uv/README.md
+++ b/deps/uv/README.md
@@ -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
diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac
index aa6e6d16a8..6e084fd04d 100644
--- a/deps/uv/configure.ac
+++ b/deps/uv/configure.ac
@@ -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])
diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst
index f383e5b10c..fcf70a35a1 100644
--- a/deps/uv/docs/src/fs.rst
+++ b/deps/uv/docs/src/fs.rst
@@ -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
-------------------
diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst
index 07908c98ff..529d588c5d 100644
--- a/deps/uv/docs/src/misc.rst
+++ b/deps/uv/docs/src/misc.rst
@@ -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
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index a8b305793d..717c2e570b 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -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);
diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h
index a990137f85..30e1d5a6f9 100644
--- a/deps/uv/include/uv/version.h
+++ b/deps/uv/include/uv/version.h
@@ -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 ""
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 066c9bee32..f92446ff42 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -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;
+}
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 4d62a23f1b..5a96b66b17 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -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));
}
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
index 5a76c90033..afdf01e787 100644
--- a/deps/uv/src/win/core.c
+++ b/deps/uv/src/win/core.c
@@ -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);
diff --git a/deps/uv/src/win/getnameinfo.c b/deps/uv/src/win/getnameinfo.c
index 9f10cd2a5a..71785a9fa6 100644
--- a/deps/uv/src/win/getnameinfo.c
+++ b/deps/uv/src/win/getnameinfo.c
@@ -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;
+ }
+
+ 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;
+ }
+
+ ret = WideCharToMultiByte(CP_UTF8,
+ 0,
+ service,
+ -1,
+ req->service,
+ sizeof(req->service),
+ NULL,
+ NULL);
+ if (ret == 0) {
+ req->retcode = uv_translate_sys_error(GetLastError());
}
- 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);
-
- WideCharToMultiByte(CP_UTF8,
- 0,
- service,
- -1,
- req->service,
- sizeof(req->service),
- NULL,
- NULL);
}
diff --git a/deps/uv/src/win/handle.c b/deps/uv/src/win/handle.c
index 738d7ff324..9d76c3f542 100644
--- a/deps/uv/src/win/handle.c
+++ b/deps/uv/src/win/handle.c
@@ -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);
+}
diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h
index b37b4c0c9b..634b9f776c 100644
--- a/deps/uv/src/win/internal.h
+++ b/deps/uv/src/win/internal.h
@@ -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);
/*
diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c
index 42380f6599..382290e69f 100644
--- a/deps/uv/src/win/pipe.c
+++ b/deps/uv/src/win/pipe.c
@@ -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;
+
+ /* 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;
+ }
- /* Return number of bytes read. */
- return sizeof frame_header;
+ /* 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;
+ }
- } 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;
+ /* 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. */
- /* Store the pending socket info. */
- uv__pipe_queue_ipc_xfer_info(handle, &xfer_info);
+ /* Read transferred socket information. */
+ err = uv__pipe_read_exactly(handle->handle, &xfer_info, sizeof xfer_info);
+ if (err)
+ goto error;
- /* Return number of bytes read. */
- return sizeof frame_header + sizeof xfer_info;
- }
+ /* Store the pending socket info. */
+ uv__pipe_queue_ipc_xfer_info(handle, xfer_type, &xfer_info);
- /* Invalid frame. */
- err = WSAECONNABORTED; /* Maps to UV_ECONNABORTED. */
+ /* 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. */
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c
index a97ab2a518..8b6f0a5c99 100644
--- a/deps/uv/src/win/tcp.c
+++ b/deps/uv/src/win/tcp.c
@@ -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;
}
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
index 3e86ff1504..c994984fe6 100644
--- a/deps/uv/src/win/util.c
+++ b/deps/uv/src/win/util.c
@@ -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;
+}
diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c
index 57da39891a..9c1e8bec20 100644
--- a/deps/uv/test/test-fs.c
+++ b/deps/uv/test/test-fs.c
@@ -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;
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index 24ba37461e..b501722d4d 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -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)
diff --git a/deps/uv/test/test-process-priority.c b/deps/uv/test/test-process-priority.c
new file mode 100644
index 0000000000..ebee6b90af
--- /dev/null
+++ b/deps/uv/test/test-process-priority.c
@@ -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;
+}
diff --git a/deps/uv/test/test-tcp-open.c b/deps/uv/test/test-tcp-open.c
index f5d8f136b1..0d92886d61 100644
--- a/deps/uv/test/test-tcp-open.c
+++ b/deps/uv/test/test-tcp-open.c
@@ -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) {
@@ -116,6 +119,20 @@ static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
}
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;
+}
diff --git a/deps/uv/test/test.gyp b/deps/uv/test/test.gyp
index 917533618b..855eda1c50 100644
--- a/deps/uv/test/test.gyp
+++ b/deps/uv/test/test.gyp
@@ -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',