From 43677325e1925c04156f97ebf8a9226f2bae5d79 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Thu, 27 Jun 2019 10:31:58 -0400 Subject: [PATCH] deps: upgrade to libuv 1.30.0 Notable changes: - Support for the Haiku platform has been added. - The maximum UV_THREADPOOL_SIZE has been increased from 128 to 1024. - uv_fs_copyfile() now works properly when the source and destination files are the same. PR-URL: https://github.com/nodejs/node/pull/28449 Fixes: https://github.com/nodejs/node/issues/27746 Reviewed-By: Trivikram Kamat Reviewed-By: Jiawen Geng Reviewed-By: Rich Trott Reviewed-By: Ben Noordhuis --- deps/uv/.gitattributes | 1 + deps/uv/AUTHORS | 7 + deps/uv/CMakeLists.txt | 9 +- deps/uv/ChangeLog | 37 +++++ deps/uv/Makefile.am | 17 +++ deps/uv/configure.ac | 6 +- deps/uv/docs/src/design.rst | 4 +- deps/uv/docs/src/threadpool.rst | 4 +- deps/uv/include/uv/unix.h | 2 + deps/uv/include/uv/version.h | 4 +- deps/uv/src/threadpool.c | 2 +- deps/uv/src/unix/bsd-ifaddrs.c | 7 +- deps/uv/src/unix/core.c | 37 ++++- deps/uv/src/unix/fs.c | 103 ++++++++++---- deps/uv/src/unix/haiku.c | 176 ++++++++++++++++++++++++ deps/uv/src/unix/internal.h | 9 ++ deps/uv/src/unix/process.c | 7 +- deps/uv/src/unix/signal.c | 2 +- deps/uv/src/unix/stream.c | 2 +- deps/uv/src/unix/thread.c | 17 ++- deps/uv/src/win/fs.c | 60 +++++--- deps/uv/test/fixtures/lorem_ipsum.txt | 1 + deps/uv/test/test-cwd-and-chdir.c | 7 + deps/uv/test/test-fs-copyfile.c | 10 +- deps/uv/test/test-fs.c | 60 +++++++- deps/uv/test/test-list.h | 6 +- deps/uv/test/test-tcp-try-write-error.c | 109 +++++++++++++++ deps/uv/test/test.gyp | 1 + 28 files changed, 644 insertions(+), 63 deletions(-) create mode 100644 deps/uv/.gitattributes create mode 100644 deps/uv/src/unix/haiku.c create mode 100644 deps/uv/test/fixtures/lorem_ipsum.txt create mode 100644 deps/uv/test/test-tcp-try-write-error.c diff --git a/deps/uv/.gitattributes b/deps/uv/.gitattributes new file mode 100644 index 00000000000000..89297cb79e3ace --- /dev/null +++ b/deps/uv/.gitattributes @@ -0,0 +1 @@ +test/fixtures/lorem_ipsum.txt text eol=lf diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index af91fde4b239c0..4db18540d46a77 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -382,3 +382,10 @@ George Zhao Kyle Edwards ken-cunningham-webuse Kelvin Jin +Leorize +Vlad A +Niels Lohmann +Jenil Christo +Evgeny Ermakov +gengjiawen +Leo Chung diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt index b3890ddf57d219..f2ed3722c47329 100644 --- a/deps/uv/CMakeLists.txt +++ b/deps/uv/CMakeLists.txt @@ -1,7 +1,6 @@ # TODO: determine CMAKE_SYSTEM_NAME on OS/390. Currently assumes "OS/390". cmake_minimum_required(VERSION 3.0) project(libuv) -enable_testing() if(MSVC) list(APPEND uv_cflags /W4) @@ -137,6 +136,7 @@ set(uv_test_sources test/test-tcp-read-stop.c test/test-tcp-shutdown-after-write.c test/test-tcp-try-write.c + test/test-tcp-try-write-error.c test/test-tcp-unexpected-read.c test/test-tcp-write-after-connect.c test/test-tcp-write-fail.c @@ -350,8 +350,11 @@ target_compile_options(uv_a PRIVATE ${uv_cflags}) target_include_directories(uv_a PRIVATE include src) target_link_libraries(uv_a ${uv_libraries}) -if(BUILD_TESTING) - include(CTest) +option(libuv_buildtests "Build the unit tests when BUILD_TESTING is enabled." ON) + +include(CTest) +if(BUILD_TESTING AND libuv_buildtests) + enable_testing() add_executable(uv_run_tests ${uv_test_sources}) target_compile_definitions(uv_run_tests PRIVATE ${uv_defines} USING_UV_SHARED=1) diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 51ed5a223a1d83..b9ed7484a50a32 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,40 @@ +2019.06.28, Version 1.30.0 (Stable), 365b6f2a0eacda1ff52be8e57ab9381cfddc5dbb + +Changes since version 1.29.1: + +* darwin: fall back to F_BARRIERFSYNC (Ben Noordhuis) + +* darwin: add 32 bit close$NOCANCEL implementation (ken-cunningham-webuse) + +* build, core, unix: add support for Haiku (Leorize) + +* darwin,linux: more conservative minimum stack size (Ben Noordhuis) + +* threadpool: increase UV_THREADPOOL_SIZE limit (Vlad A) + +* unix: return actual error from `uv_try_write()` (Anna Henningsen) + +* darwin: fix build error with macos 10.10 (Ben Noordhuis) + +* unix: make uv_cwd() report UV_ENOBUFS (Ben Noordhuis) + +* unix: make uv_fs_read() fill all buffers (Ben Noordhuis) + +* test: give hrtime test a custom 10s timeout (Ben Noordhuis) + +* fs: fix uv_fs_copyfile if same src and dst (Santiago Gimeno) + +* build: add cmake option to skip building tests (Niels Lohmann) + +* doc: add link to nodejs.org (Jenil Christo) + +* unix: fix a comment typo in signal.c (Evgeny Ermakov) + +* unix: remove redundant cast in process.c (gengjiawen) + +* doc: fix wrong mutex function prototypes (Leo Chung) + + 2019.05.22, Version 1.29.1 (Stable), d16e6094e1eb3b0b5981ef1dd7e03ec4d466944d Changes since version 1.29.0: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 07224f32b48e96..d213d8f4faec67 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -117,6 +117,7 @@ endif # WINNT EXTRA_DIST = test/fixtures/empty_file \ test/fixtures/load_error.node \ + test/fixtures/lorem_ipsum.txt \ include \ docs \ img \ @@ -272,6 +273,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-tcp-writealot.c \ test/test-tcp-write-fail.c \ test/test-tcp-try-write.c \ + test/test-tcp-try-write-error.c \ test/test-tcp-write-queue-order.c \ test/test-thread-equal.c \ test/test-thread.c \ @@ -320,6 +322,10 @@ test_run_tests_CFLAGS += -D_ALL_SOURCE \ -D_LINUX_SOURCE_COMPAT endif +if HAIKU +test_run_tests_CFLAGS += -D_BSD_SOURCE +endif + if LINUX test_run_tests_CFLAGS += -D_GNU_SOURCE endif @@ -409,6 +415,17 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ test_run_tests_LDFLAGS += -lutil endif +if HAIKU +uvinclude_HEADERS += include/uv/posix.h +libuv_la_CFLAGS += -D_BSD_SOURCE +libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ + src/unix/haiku.c \ + src/unix/no-fsevents.c \ + src/unix/no-proctitle.c \ + src/unix/posix-hrtime.c \ + src/unix/posix-poll.c +endif + if HURD uvinclude_HEADERS += include/uv/posix.h libuv_la_SOURCES += src/unix/no-fsevents.c \ diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index ad99f9ad380cdb..626ad4c7b0d975 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.29.1], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.30.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]) @@ -56,6 +56,7 @@ AM_CONDITIONAL([CYGWIN], [AS_CASE([$host_os],[cygwin*], [true], [false]) AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])]) AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])]) AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[*freebsd*], [true], [false])]) +AM_CONDITIONAL([HAIKU], [AS_CASE([$host_os],[haiku], [true], [false])]) AM_CONDITIONAL([HURD], [AS_CASE([$host_os],[gnu*], [true], [false])]) AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])]) AM_CONDITIONAL([MSYS], [AS_CASE([$host_os],[msys*], [true], [false])]) @@ -71,6 +72,9 @@ AS_CASE([$host_os], [netbsd*], [AC_CHECK_LIB([kvm], [kvm_open])]) AS_CASE([$host_os], [kfreebsd*], [ LIBS="$LIBS -lfreebsd-glue" ]) +AS_CASE([$host_os], [haiku], [ + LIBS="$LIBS -lnetwork" +]) AC_CHECK_HEADERS([sys/ahafs_evProds.h]) AC_CONFIG_FILES([Makefile libuv.pc]) AC_CONFIG_LINKS([test/fixtures/empty_file:test/fixtures/empty_file]) diff --git a/deps/uv/docs/src/design.rst b/deps/uv/docs/src/design.rst index 001b12334d2354..9594bd1a77edbd 100644 --- a/deps/uv/docs/src/design.rst +++ b/deps/uv/docs/src/design.rst @@ -4,9 +4,11 @@ Design overview =============== -libuv is cross-platform support library which was originally written for NodeJS. It's designed +libuv is cross-platform support library which was originally written for `Node.js`_. It's designed around the event-driven asynchronous I/O model. +.. _Node.js: https://nodejs.org + The library provides much more than a simple abstraction over different I/O polling mechanisms: 'handles' and 'streams' provide a high level abstraction for sockets and other entities; cross-platform file I/O and threading functionality is also provided, amongst other things. diff --git a/deps/uv/docs/src/threadpool.rst b/deps/uv/docs/src/threadpool.rst index 93bd236d35e9f5..ed41c37fe327d2 100644 --- a/deps/uv/docs/src/threadpool.rst +++ b/deps/uv/docs/src/threadpool.rst @@ -10,7 +10,9 @@ operations, as well as getaddrinfo and getnameinfo requests. Its default size is 4, but it can be changed at startup time by setting the ``UV_THREADPOOL_SIZE`` environment variable to any value (the absolute maximum -is 128). +is 1024). + +.. versionchanged:: 1.29.2 the maximum UV_THREADPOOL_SIZE allowed was increased from 128 to 1024. The threadpool is global and shared across all event loops. When a particular function makes use of the threadpool (i.e. when using :c:func:`uv_queue_work`) diff --git a/deps/uv/include/uv/unix.h b/deps/uv/include/uv/unix.h index f73b7b04408d0c..6c93ee97de27a6 100644 --- a/deps/uv/include/uv/unix.h +++ b/deps/uv/include/uv/unix.h @@ -66,6 +66,8 @@ defined(__MSYS__) || \ defined(__GNU__) # include "uv/posix.h" +#elif defined(__HAIKU__) +# include "uv/posix.h" #endif #ifndef NI_MAXHOST diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index 6d3072c73596e6..eb1f0c6597eeee 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 29 -#define UV_VERSION_PATCH 1 +#define UV_VERSION_MINOR 30 +#define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/src/threadpool.c b/deps/uv/src/threadpool.c index 4258933c724782..7aa575508fa8c4 100644 --- a/deps/uv/src/threadpool.c +++ b/deps/uv/src/threadpool.c @@ -27,7 +27,7 @@ #include -#define MAX_THREADPOOL_SIZE 128 +#define MAX_THREADPOOL_SIZE 1024 static uv_once_t once = UV_ONCE_INIT; static uv_cond_t cond; diff --git a/deps/uv/src/unix/bsd-ifaddrs.c b/deps/uv/src/unix/bsd-ifaddrs.c index a4c6bf9d11c7f4..0d7bbe662a5c53 100644 --- a/deps/uv/src/unix/bsd-ifaddrs.c +++ b/deps/uv/src/unix/bsd-ifaddrs.c @@ -31,6 +31,10 @@ #include #endif +#if defined(__HAIKU__) +#define IFF_RUNNING IFF_LINK +#endif + static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) return 1; @@ -45,7 +49,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { if (exclude_type == UV__EXCLUDE_IFPHYS) return (ent->ifa_addr->sa_family != AF_LINK); #endif -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) || \ + defined(__HAIKU__) /* * On BSD getifaddrs returns information related to the raw underlying * devices. We're not interested in this information. diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 3bada900ebdc41..202c75bbb5e94c 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -526,8 +526,13 @@ int uv__close_nocancel(int fd) { #if defined(__APPLE__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension" +#if defined(__LP64__) extern int close$NOCANCEL(int); return close$NOCANCEL(fd); +#else + extern int close$NOCANCEL$UNIX2003(int); + return close$NOCANCEL$UNIX2003(fd); +#endif #pragma GCC diagnostic pop #elif defined(__linux__) return syscall(SYS_close, fd); @@ -579,7 +584,7 @@ int uv__nonblock_ioctl(int fd, int set) { } -#if !defined(__CYGWIN__) && !defined(__MSYS__) +#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__HAIKU__) int uv__cloexec_ioctl(int fd, int set) { int r; @@ -696,16 +701,38 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) { int uv_cwd(char* buffer, size_t* size) { + char scratch[1 + UV__PATH_MAX]; + if (buffer == NULL || size == NULL) return UV_EINVAL; - if (getcwd(buffer, *size) == NULL) + /* Try to read directly into the user's buffer first... */ + if (getcwd(buffer, *size) != NULL) + goto fixup; + + if (errno != ERANGE) + return UV__ERR(errno); + + /* ...or into scratch space if the user's buffer is too small + * so we can report how much space to provide on the next try. + */ + if (getcwd(scratch, sizeof(scratch)) == NULL) return UV__ERR(errno); + buffer = scratch; + +fixup: + *size = strlen(buffer); + if (*size > 1 && buffer[*size - 1] == '/') { - buffer[*size-1] = '\0'; - (*size)--; + *size -= 1; + buffer[*size] = '\0'; + } + + if (buffer == scratch) { + *size += 1; + return UV_ENOBUFS; } return 0; @@ -947,7 +974,7 @@ int uv_getrusage(uv_rusage_t* rusage) { rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec; rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec; -#if !defined(__MVS__) +#if !defined(__MVS__) && !defined(__HAIKU__) rusage->ru_maxrss = usage.ru_maxrss; rusage->ru_ixrss = usage.ru_ixrss; rusage->ru_idrss = usage.ru_idrss; diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 24a130f5433d6e..5138c619b02f1d 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -160,12 +160,15 @@ static ssize_t uv__fs_fsync(uv_fs_t* req) { * to the drive platters. This is in contrast to Linux's fdatasync and fsync * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent * for flushing buffered data to permanent storage. If F_FULLFSYNC is not - * supported by the file system we should fall back to fsync(). This is the - * same approach taken by sqlite. + * supported by the file system we fall back to F_BARRIERFSYNC or fsync(). + * This is the same approach taken by sqlite, except sqlite does not issue + * an F_BARRIERFSYNC call. */ int r; r = fcntl(req->file, F_FULLFSYNC); + if (r != 0) + r = fcntl(req->file, 85 /* F_BARRIERFSYNC */); /* fsync + barrier */ if (r != 0) r = fsync(req->file); return r; @@ -189,7 +192,8 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) { static ssize_t uv__fs_futime(uv_fs_t* req) { #if defined(__linux__) \ - || defined(_AIX71) + || defined(_AIX71) \ + || defined(__HAIKU__) /* utimesat() has nanosecond resolution but we stick to microseconds * for the sake of consistency with other platforms. */ @@ -274,6 +278,54 @@ static ssize_t uv__fs_open(uv_fs_t* req) { } +static ssize_t uv__fs_preadv(uv_file fd, + uv_buf_t* bufs, + unsigned int nbufs, + off_t off) { + uv_buf_t* buf; + uv_buf_t* end; + ssize_t result; + ssize_t rc; + size_t pos; + + assert(nbufs > 0); + + result = 0; + pos = 0; + buf = bufs + 0; + end = bufs + nbufs; + + for (;;) { + do + rc = pread(fd, buf->base + pos, buf->len - pos, off + result); + while (rc == -1 && errno == EINTR); + + if (rc == 0) + break; + + if (rc == -1 && result == 0) + return UV__ERR(errno); + + if (rc == -1) + break; /* We read some data so return that, ignore the error. */ + + pos += rc; + result += rc; + + if (pos < buf->len) + continue; + + pos = 0; + buf += 1; + + if (buf == end) + break; + } + + return result; +} + + static ssize_t uv__fs_read(uv_fs_t* req) { #if defined(__linux__) static int no_preadv; @@ -303,7 +355,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) { if (no_preadv) retry: # endif { - result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off); + result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off); } # if defined(__linux__) else { @@ -467,22 +519,13 @@ static int uv__fs_closedir(uv_fs_t* req) { return 0; } -#if defined(_POSIX_PATH_MAX) -# define UV__FS_PATH_MAX _POSIX_PATH_MAX -#elif defined(PATH_MAX) -# define UV__FS_PATH_MAX PATH_MAX -#else -# define UV__FS_PATH_MAX_FALLBACK 8192 -# define UV__FS_PATH_MAX UV__FS_PATH_MAX_FALLBACK -#endif - static ssize_t uv__fs_pathmax_size(const char* path) { ssize_t pathmax; pathmax = pathconf(path, _PC_PATH_MAX); if (pathmax == -1) - pathmax = UV__FS_PATH_MAX; + pathmax = UV__PATH_MAX; return pathmax; } @@ -493,7 +536,9 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { char* buf; char* newbuf; -#if defined(UV__FS_PATH_MAX_FALLBACK) +#if defined(_POSIX_PATH_MAX) || defined(PATH_MAX) + maxlen = uv__fs_pathmax_size(req->path); +#else /* We may not have a real PATH_MAX. Read size of link. */ struct stat st; int ret; @@ -511,8 +556,6 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { for some symlinks, such as those in /proc or /sys. */ if (maxlen == 0) maxlen = uv__fs_pathmax_size(req->path); -#else - maxlen = uv__fs_pathmax_size(req->path); #endif buf = uv__malloc(maxlen); @@ -796,7 +839,8 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) { static ssize_t uv__fs_utime(uv_fs_t* req) { #if defined(__linux__) \ || defined(_AIX71) \ - || defined(__sun) + || defined(__sun) \ + || defined(__HAIKU__) /* utimesat() has nanosecond resolution but we stick to microseconds * for the sake of consistency with other platforms. */ @@ -903,7 +947,8 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { uv_fs_t fs_req; uv_file srcfd; uv_file dstfd; - struct stat statsbuf; + struct stat src_statsbuf; + struct stat dst_statsbuf; int dst_flags; int result; int err; @@ -921,7 +966,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { return srcfd; /* Get the source file's mode. */ - if (fstat(srcfd, &statsbuf)) { + if (fstat(srcfd, &src_statsbuf)) { err = UV__ERR(errno); goto out; } @@ -936,7 +981,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { &fs_req, req->new_path, dst_flags, - statsbuf.st_mode, + src_statsbuf.st_mode, NULL); uv_fs_req_cleanup(&fs_req); @@ -945,7 +990,19 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { goto out; } - if (fchmod(dstfd, statsbuf.st_mode) == -1) { + /* Get the destination file's mode. */ + if (fstat(dstfd, &dst_statsbuf)) { + err = UV__ERR(errno); + goto out; + } + + /* Check if srcfd and dstfd refer to the same file */ + if (src_statsbuf.st_dev == dst_statsbuf.st_dev && + src_statsbuf.st_ino == dst_statsbuf.st_ino) { + goto out; + } + + if (fchmod(dstfd, src_statsbuf.st_mode) == -1) { err = UV__ERR(errno); goto out; } @@ -975,7 +1032,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { } #endif - bytes_to_send = statsbuf.st_size; + bytes_to_send = src_statsbuf.st_size; in_offset = 0; while (bytes_to_send != 0) { err = uv_fs_sendfile(NULL, diff --git a/deps/uv/src/unix/haiku.c b/deps/uv/src/unix/haiku.c new file mode 100644 index 00000000000000..7708851c2a5fa9 --- /dev/null +++ b/deps/uv/src/unix/haiku.c @@ -0,0 +1,176 @@ +/* Copyright libuv project 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 "internal.h" + +#include /* find_path() */ +#include + + +void uv_loadavg(double avg[3]) { + avg[0] = 0; + avg[1] = 0; + avg[2] = 0; +} + + +int uv_exepath(char* buffer, size_t* size) { + char abspath[B_PATH_NAME_LENGTH]; + status_t status; + ssize_t abspath_len; + + if (buffer == NULL || size == NULL || *size == 0) + return UV_EINVAL; + + status = find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, abspath, + sizeof(abspath)); + if (status != B_OK) + return UV__ERR(status); + + abspath_len = uv__strscpy(buffer, abspath, *size); + *size -= 1; + if (abspath_len >= 0 && *size > (size_t)abspath_len) + *size = (size_t)abspath_len; + + return 0; +} + + +uint64_t uv_get_free_memory(void) { + status_t status; + system_info sinfo; + + status = get_system_info(&sinfo); + if (status != B_OK) + return 0; + + return (sinfo.max_pages - sinfo.used_pages) * B_PAGE_SIZE; +} + + +uint64_t uv_get_total_memory(void) { + status_t status; + system_info sinfo; + + status = get_system_info(&sinfo); + if (status != B_OK) + return 0; + + return sinfo.max_pages * B_PAGE_SIZE; +} + + +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + +int uv_resident_set_memory(size_t* rss) { + area_info area; + ssize_t cookie; + status_t status; + thread_info thread; + + status = get_thread_info(find_thread(NULL), &thread); + if (status != B_OK) + return UV__ERR(status); + + cookie = 0; + *rss = 0; + while (get_next_area_info(thread.team, &cookie, &area) == B_OK) + *rss += area.ram_size; + + return 0; +} + + +int uv_uptime(double* uptime) { + /* system_time() returns time since booting in microseconds */ + *uptime = (double)system_time() / 1000000; + return 0; +} + + +int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { + cpu_topology_node_info* topology_infos; + int i; + status_t status; + system_info system; + uint32_t topology_count; + uint64_t cpuspeed; + uv_cpu_info_t* cpu_info; + + if (cpu_infos == NULL || count == NULL) + return UV_EINVAL; + + status = get_cpu_topology_info(NULL, &topology_count); + if (status != B_OK) + return UV__ERR(status); + + topology_infos = uv__malloc(topology_count * sizeof(*topology_infos)); + if (topology_infos == NULL) + return UV_ENOMEM; + + status = get_cpu_topology_info(topology_infos, &topology_count); + if (status != B_OK) { + uv__free(topology_infos); + return UV__ERR(status); + } + + cpuspeed = 0; + for (i = 0; i < (int)topology_count; i++) { + if (topology_infos[i].type == B_TOPOLOGY_CORE) { + cpuspeed = topology_infos[i].data.core.default_frequency; + break; + } + } + + uv__free(topology_infos); + + status = get_system_info(&system); + if (status != B_OK) + return UV__ERR(status); + + *cpu_infos = uv__calloc(system.cpu_count, sizeof(**cpu_infos)); + if (*cpu_infos == NULL) + return UV_ENOMEM; + + /* CPU time and model are not exposed by Haiku. */ + cpu_info = *cpu_infos; + for (i = 0; i < (int)system.cpu_count; i++) { + cpu_info->model = uv__strdup("unknown"); + cpu_info->speed = (int)(cpuspeed / 1000000); + cpu_info++; + } + *count = system.cpu_count; + + return 0; +} + +void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { + int i; + + for (i = 0; i < count; i++) + uv__free(cpu_infos[i].model); + + uv__free(cpu_infos); +} diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 8c8ddc868ec800..260616474ec151 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -25,6 +25,7 @@ #include "uv-common.h" #include +#include /* _POSIX_PATH_MAX, PATH_MAX */ #include /* abort */ #include /* strrchr */ #include /* O_CLOEXEC, may be */ @@ -60,6 +61,14 @@ # include #endif +#if defined(_POSIX_PATH_MAX) +# define UV__PATH_MAX _POSIX_PATH_MAX +#elif defined(PATH_MAX) +# define UV__PATH_MAX PATH_MAX +#else +# define UV__PATH_MAX 8192 +#endif + #if defined(__ANDROID__) int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); # ifdef pthread_sigmask diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index b284308dd0694f..bb6b76c9fa7005 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -249,7 +249,7 @@ static int uv__process_open_stream(uv_stdio_container_t* container, static void uv__process_close_stream(uv_stdio_container_t* container) { if (!(container->flags & UV_CREATE_PIPE)) return; - uv__stream_close((uv_stream_t*)container->data.stream); + uv__stream_close(container->data.stream); } @@ -385,6 +385,11 @@ static void uv__process_child_init(const uv_process_options_t* options, if (n == SIGKILL || n == SIGSTOP) continue; /* Can't be changed. */ +#if defined(__HAIKU__) + if (n == SIGKILLTHR) + continue; /* Can't be changed. */ +#endif + if (SIG_ERR != signal(n, SIG_DFL)) continue; diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c index 01aa55f3fe7c66..5e89ded2d842ce 100644 --- a/deps/uv/src/unix/signal.c +++ b/deps/uv/src/unix/signal.c @@ -375,7 +375,7 @@ static int uv__signal_start(uv_signal_t* handle, /* Short circuit: if the signal watcher is already watching {signum} don't * go through the process of deregistering and registering the handler. - * Additionally, this avoids pending signals getting lost in the small time + * Additionally, this avoids pending signals getting lost in the small * time frame that handle->signum == 0. */ if (signum == handle->signum) { diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 7e4d5fc7ffd429..17b06a39a772b0 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -1541,7 +1541,7 @@ int uv_try_write(uv_stream_t* stream, } if (written == 0 && req_size != 0) - return UV_EAGAIN; + return req.error < 0 ? req.error : UV_EAGAIN; else return written; } diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index 9a50448e62ce58..cd0b7aa6aaf923 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -178,8 +178,21 @@ static size_t thread_stack_size(void) { if (lim.rlim_cur != RLIM_INFINITY) { /* pthread_attr_setstacksize() expects page-aligned values. */ lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize(); - if (lim.rlim_cur >= PTHREAD_STACK_MIN) - return lim.rlim_cur; + + /* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is + * too small to safely receive signals on. + * + * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has + * the largest MINSIGSTKSZ of the architectures that musl supports) so + * let's use that as a lower bound. + * + * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ + * is between 28 and 133 KB when compiling against glibc, depending + * on the architecture. + */ + if (lim.rlim_cur >= 8192) + if (lim.rlim_cur >= PTHREAD_STACK_MIN) + return lim.rlim_cur; } #endif diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 9e2f084c8d0e9c..7d78d466c8738f 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -1409,47 +1409,57 @@ INLINE static void fs__stat_prepare_path(WCHAR* pathw) { } -INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) { +INLINE static DWORD fs__stat_impl_from_path(WCHAR* path, + int do_lstat, + uv_stat_t* statbuf) { HANDLE handle; DWORD flags; + DWORD ret; flags = FILE_FLAG_BACKUP_SEMANTICS; - if (do_lstat) { + if (do_lstat) flags |= FILE_FLAG_OPEN_REPARSE_POINT; - } - handle = CreateFileW(req->file.pathw, + handle = CreateFileW(path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, flags, NULL); - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - if (fs__stat_handle(handle, &req->statbuf, do_lstat) != 0) { - DWORD error = GetLastError(); + if (handle == INVALID_HANDLE_VALUE) + ret = GetLastError(); + else if (fs__stat_handle(handle, statbuf, do_lstat) != 0) + ret = GetLastError(); + else + ret = 0; + + CloseHandle(handle); + return ret; +} + + +INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) { + DWORD error; + + error = fs__stat_impl_from_path(req->file.pathw, do_lstat, &req->statbuf); + if (error != 0) { if (do_lstat && (error == ERROR_SYMLINK_NOT_SUPPORTED || error == ERROR_NOT_A_REPARSE_POINT)) { /* We opened a reparse point but it was not a symlink. Try again. */ fs__stat_impl(req, 0); - } else { /* Stat failed. */ - SET_REQ_WIN32_ERROR(req, GetLastError()); + SET_REQ_WIN32_ERROR(req, error); } - CloseHandle(handle); return; } req->ptr = &req->statbuf; req->result = 0; - CloseHandle(handle); } @@ -1553,6 +1563,9 @@ static void fs__ftruncate(uv_fs_t* req) { static void fs__copyfile(uv_fs_t* req) { int flags; int overwrite; + DWORD error; + uv_stat_t statbuf; + uv_stat_t new_statbuf; flags = req->fs.info.file_flags; @@ -1563,12 +1576,25 @@ static void fs__copyfile(uv_fs_t* req) { overwrite = flags & UV_FS_COPYFILE_EXCL; - if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) == 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); + if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) != 0) { + SET_REQ_RESULT(req, 0); return; } - SET_REQ_RESULT(req, 0); + SET_REQ_WIN32_ERROR(req, GetLastError()); + if (req->result != UV_EBUSY) + return; + + /* if error UV_EBUSY check if src and dst file are the same */ + if (fs__stat_impl_from_path(req->file.pathw, 0, &statbuf) != 0 || + fs__stat_impl_from_path(req->fs.info.new_pathw, 0, &new_statbuf) != 0) { + return; + } + + if (statbuf.st_dev == new_statbuf.st_dev && + statbuf.st_ino == new_statbuf.st_ino) { + SET_REQ_RESULT(req, 0); + } } diff --git a/deps/uv/test/fixtures/lorem_ipsum.txt b/deps/uv/test/fixtures/lorem_ipsum.txt new file mode 100644 index 00000000000000..1b376877f435b1 --- /dev/null +++ b/deps/uv/test/fixtures/lorem_ipsum.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. diff --git a/deps/uv/test/test-cwd-and-chdir.c b/deps/uv/test/test-cwd-and-chdir.c index 1e95043c1775a9..5d43524c921cdd 100644 --- a/deps/uv/test/test-cwd-and-chdir.c +++ b/deps/uv/test/test-cwd-and-chdir.c @@ -33,9 +33,16 @@ TEST_IMPL(cwd_and_chdir) { size_t size2; int err; + size1 = 1; + err = uv_cwd(buffer_orig, &size1); + ASSERT(err == UV_ENOBUFS); + ASSERT(size1 > 1); + size1 = sizeof buffer_orig; err = uv_cwd(buffer_orig, &size1); ASSERT(err == 0); + ASSERT(size1 > 0); + ASSERT(buffer_orig[size1] != '/'); err = uv_chdir(buffer_orig); ASSERT(err == 0); diff --git a/deps/uv/test/test-fs-copyfile.c b/deps/uv/test/test-fs-copyfile.c index cd8a2ea7c07b08..def3d967e74f5b 100644 --- a/deps/uv/test/test-fs-copyfile.c +++ b/deps/uv/test/test-fs-copyfile.c @@ -24,7 +24,8 @@ #if defined(__unix__) || defined(__POSIX__) || \ defined(__APPLE__) || defined(__sun) || \ - defined(_AIX) || defined(__MVS__) + defined(_AIX) || defined(__MVS__) || \ + defined(__HAIKU__) #include /* unlink, etc. */ #else # include @@ -119,6 +120,13 @@ TEST_IMPL(fs_copyfile) { ASSERT(r != 0); uv_fs_req_cleanup(&req); + /* Succeeds if src and dst files are identical. */ + touch_file(src, 12); + r = uv_fs_copyfile(NULL, &req, src, src, 0, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&req); + unlink(src); + /* Copies file synchronously. Creates new file. */ unlink(dst); r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL); diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index c3153c717b7cd3..2cf8f287fe331d 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -31,7 +31,8 @@ /* FIXME we shouldn't need to branch in this file */ #if defined(__unix__) || defined(__POSIX__) || \ defined(__APPLE__) || defined(__sun) || \ - defined(_AIX) || defined(__MVS__) + defined(_AIX) || defined(__MVS__) || \ + defined(__HAIKU__) #include /* unlink, rmdir, etc. */ #else # include @@ -1653,6 +1654,8 @@ TEST_IMPL(fs_chown) { uv_run(loop, UV_RUN_DEFAULT); ASSERT(fchown_cb_count == 1); +#ifndef __HAIKU__ + /* Haiku doesn't support hardlink */ /* sync link */ r = uv_fs_link(NULL, &req, "test_file", "test_file_link", NULL); ASSERT(r == 0); @@ -1670,6 +1673,7 @@ TEST_IMPL(fs_chown) { ASSERT(r == 0); uv_run(loop, UV_RUN_DEFAULT); ASSERT(lchown_cb_count == 1); +#endif /* Close file */ r = uv_fs_close(NULL, &req, file, NULL); @@ -2717,6 +2721,60 @@ TEST_IMPL(fs_rename_to_existing_file) { } +TEST_IMPL(fs_read_bufs) { + char scratch[768]; + uv_buf_t bufs[4]; + + ASSERT(0 <= uv_fs_open(NULL, &open_req1, + "test/fixtures/lorem_ipsum.txt", + O_RDONLY, 0, NULL)); + ASSERT(open_req1.result >= 0); + uv_fs_req_cleanup(&open_req1); + + ASSERT(UV_EINVAL == uv_fs_read(NULL, &read_req, open_req1.result, + NULL, 0, 0, NULL)); + ASSERT(UV_EINVAL == uv_fs_read(NULL, &read_req, open_req1.result, + NULL, 1, 0, NULL)); + ASSERT(UV_EINVAL == uv_fs_read(NULL, &read_req, open_req1.result, + bufs, 0, 0, NULL)); + + bufs[0] = uv_buf_init(scratch + 0, 256); + bufs[1] = uv_buf_init(scratch + 256, 256); + bufs[2] = uv_buf_init(scratch + 512, 128); + bufs[3] = uv_buf_init(scratch + 640, 128); + + ASSERT(446 == uv_fs_read(NULL, + &read_req, + open_req1.result, + bufs + 0, + 2, /* 2x 256 bytes. */ + 0, /* Positional read. */ + NULL)); + ASSERT(read_req.result == 446); + uv_fs_req_cleanup(&read_req); + + ASSERT(190 == uv_fs_read(NULL, + &read_req, + open_req1.result, + bufs + 2, + 2, /* 2x 128 bytes. */ + 256, /* Positional read. */ + NULL)); + ASSERT(read_req.result == /* 446 - 256 */ 190); + uv_fs_req_cleanup(&read_req); + + ASSERT(0 == memcmp(bufs[1].base + 0, bufs[2].base, 128)); + ASSERT(0 == memcmp(bufs[1].base + 128, bufs[3].base, 190 - 128)); + + ASSERT(0 == uv_fs_close(NULL, &close_req, open_req1.result, NULL)); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(fs_read_file_eof) { #if defined(__CYGWIN__) || defined(__MSYS__) RETURN_SKIP("Cygwin pread at EOF may (incorrectly) return data!"); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 8886b07c8a7473..a48f6f3806806a 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -91,6 +91,7 @@ TEST_DECLARE (tcp_write_after_connect) TEST_DECLARE (tcp_writealot) TEST_DECLARE (tcp_write_fail) TEST_DECLARE (tcp_try_write) +TEST_DECLARE (tcp_try_write_error) TEST_DECLARE (tcp_write_queue_order) TEST_DECLARE (tcp_open) TEST_DECLARE (tcp_open_twice) @@ -325,6 +326,7 @@ TEST_DECLARE (fs_utime) TEST_DECLARE (fs_futime) TEST_DECLARE (fs_file_open_append) TEST_DECLARE (fs_stat_missing_path) +TEST_DECLARE (fs_read_bufs) TEST_DECLARE (fs_read_file_eof) TEST_DECLARE (fs_event_watch_dir) TEST_DECLARE (fs_event_watch_dir_recursive) @@ -582,6 +584,7 @@ TASK_LIST_START TEST_HELPER (tcp_write_fail, tcp4_echo_server) TEST_ENTRY (tcp_try_write) + TEST_ENTRY (tcp_try_write_error) TEST_ENTRY (tcp_write_queue_order) @@ -776,7 +779,7 @@ TASK_LIST_START TEST_ENTRY (tmpdir) - TEST_ENTRY (hrtime) + TEST_ENTRY_CUSTOM (hrtime, 0, 0, 10000) TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000) TEST_ENTRY_CUSTOM (getaddrinfo_fail_sync, 0, 0, 10000) @@ -911,6 +914,7 @@ TASK_LIST_START TEST_ENTRY (fs_non_symlink_reparse_point) #endif TEST_ENTRY (fs_stat_missing_path) + TEST_ENTRY (fs_read_bufs) TEST_ENTRY (fs_read_file_eof) TEST_ENTRY (fs_file_open_append) TEST_ENTRY (fs_event_watch_dir) diff --git a/deps/uv/test/test-tcp-try-write-error.c b/deps/uv/test/test-tcp-try-write-error.c new file mode 100644 index 00000000000000..58d4723c0903ef --- /dev/null +++ b/deps/uv/test/test-tcp-try-write-error.c @@ -0,0 +1,109 @@ +/* Copyright libuv contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include +#include +#include + +static uv_tcp_t server; +static uv_tcp_t client; +static uv_tcp_t incoming; +static int connect_cb_called; +static int close_cb_called; +static int connection_cb_called; + + +static void close_cb(uv_handle_t* handle) { + close_cb_called++; +} + +static void incoming_close_cb(uv_handle_t* handle) { + uv_buf_t buf; + int r = 1; + + close_cb_called++; + + buf = uv_buf_init("meow", 4); + while (r > 0) + r = uv_try_write((uv_stream_t*) &client, &buf, 1); + fprintf(stderr, "uv_try_write error: %d %s\n", r, uv_strerror(r)); + ASSERT(r == UV_EPIPE || r == UV_ECONNABORTED); + ASSERT(client.write_queue_size == 0); +} + + +static void connect_cb(uv_connect_t* req, int status) { + ASSERT(status == 0); + connect_cb_called++; +} + + +static void connection_cb(uv_stream_t* tcp, int status) { + ASSERT(status == 0); + + ASSERT(0 == uv_tcp_init(tcp->loop, &incoming)); + ASSERT(0 == uv_accept(tcp, (uv_stream_t*) &incoming)); + + connection_cb_called++; + uv_close((uv_handle_t*) &incoming, incoming_close_cb); + uv_close((uv_handle_t*) tcp, close_cb); +} + + +static void start_server(void) { + struct sockaddr_in addr; + + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + + ASSERT(0 == uv_tcp_init(uv_default_loop(), &server)); + ASSERT(0 == uv_tcp_bind(&server, (struct sockaddr*) &addr, 0)); + ASSERT(0 == uv_listen((uv_stream_t*) &server, 128, connection_cb)); +} + + +TEST_IMPL(tcp_try_write_error) { + uv_connect_t connect_req; + struct sockaddr_in addr; + + start_server(); + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + + ASSERT(0 == uv_tcp_init(uv_default_loop(), &client)); + ASSERT(0 == uv_tcp_connect(&connect_req, + &client, + (struct sockaddr*) &addr, + connect_cb)); + + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + uv_close((uv_handle_t*) &client, close_cb); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + ASSERT(connect_cb_called == 1); + ASSERT(close_cb_called == 3); + ASSERT(connection_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test.gyp b/deps/uv/test/test.gyp index ff64ef0be8d4b4..a4083e917834b5 100644 --- a/deps/uv/test/test.gyp +++ b/deps/uv/test/test.gyp @@ -120,6 +120,7 @@ 'test-tcp-writealot.c', 'test-tcp-write-fail.c', 'test-tcp-try-write.c', + 'test-tcp-try-write-error.c', 'test-tcp-unexpected-read.c', 'test-tcp-oob.c', 'test-tcp-read-stop.c',