From 1cff5b7557483164d980aa60e6e0225ecbbe7df1 Mon Sep 17 00:00:00 2001 From: John Barboza Date: Tue, 5 Jul 2016 18:37:45 -0400 Subject: [PATCH 01/35] zos: add support for new platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - zos: disable test cases not applicable - zos: build options - zos: semaphore implementation - zos: use compare and swap builtins - zos: struct rusage not the same as other platforms - zos: backlog<=0 produces undefined behaviour Will redefine backlog in the following way * if backlog == 0, set it to 1 * if backlog < 0, set it to SOMAXCONN - zos: define IMAXBEL as empty flag and implement uv__tty_make_raw - zos: use udp multicast operations from aix - zos: ESC in ebcdic - zos: use LIBPATH for dynamic linker path - zos: uv_udp_set_ttl only works for ipv6 - zos: increase pthread stack size by factor of 4 - zos: return ENODEV instead of ENXIO errors for setsockopt - zos: use uv_cond_init the same way as aix - test: enable oob test for zos - zos: return EINVAL for zos error code EOPNOTSUPP PR-URL: https://github.com/libuv/libuv/pull/937 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé --- Makefile.am | 38 +++++++++++++++ common.gypi | 7 ++- configure.ac | 5 +- include/pthread-barrier.h | 2 + include/uv-os390.h | 27 +++++++++++ src/unix/atomic-ops.h | 12 +++++ src/unix/core.c | 6 +++ src/unix/pipe.c | 8 +++ src/unix/tcp.c | 4 ++ src/unix/thread.c | 86 ++++++++++++++++++++++++++++++++- src/unix/tty.c | 6 ++- src/unix/udp.c | 33 ++++++++++--- test/runner-unix.c | 8 +++ test/test-emfile.c | 4 +- test/test-fs-event.c | 42 ++++++++++++++++ test/test-fs.c | 2 +- test/test-poll.c | 14 +++--- test/test-process-title.c | 2 +- test/test-ref.c | 3 ++ test/test-spawn.c | 5 ++ test/test-udp-multicast-join6.c | 2 +- test/test-udp-options.c | 11 +++++ test/test-watcher-cross-stop.c | 3 ++ uv.gyp | 79 ++++++++++++++++++++++-------- 24 files changed, 366 insertions(+), 43 deletions(-) create mode 100644 include/uv-os390.h diff --git a/Makefile.am b/Makefile.am index a0437359..aab6b0c8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -129,7 +129,11 @@ EXTRA_DIST = test/fixtures/empty_file \ TESTS = test/run-tests check_PROGRAMS = test/run-tests +if OS390 +test_run_tests_CFLAGS = +else test_run_tests_CFLAGS = -Wno-long-long +endif test_run_tests_LDFLAGS = test_run_tests_SOURCES = test/blackhole-server.c \ test/dns-server.c \ @@ -284,6 +288,21 @@ if SUNOS test_run_tests_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 endif +if OS390 +test_run_tests_CFLAGS += -D_UNIX03_THREADS \ + -D_UNIX03_SOURCE \ + -D_OPEN_SYS_IF_EXT=1 \ + -D_OPEN_SYS_SOCK_IPV6 \ + -D_OPEN_MSGQ_EXT \ + -D_XOPEN_SOURCE_EXTENDED \ + -D_ALL_SOURCE \ + -D_LARGE_TIME_API \ + -D_OPEN_SYS_FILE_EXT \ + -DPATH_MAX=255 \ + -qCHARS=signed \ + -qXPLINK \ + -qFLOAT=IEEE +endif if AIX libuv_la_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT -D_THREAD_SAFE @@ -354,6 +373,25 @@ libuv_la_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 libuv_la_SOURCES += src/unix/sunos.c endif +if OS390 +include_HEADERS += include/pthread-fixes.h include/pthread-barrier.h +libuv_la_CFLAGS += -D_UNIX03_THREADS \ + -D_UNIX03_SOURCE \ + -D_OPEN_SYS_IF_EXT=1 \ + -D_OPEN_MSGQ_EXT \ + -D_XOPEN_SOURCE_EXTENDED \ + -D_ALL_SOURCE \ + -D_LARGE_TIME_API \ + -D_OPEN_SYS_SOCK_IPV6 \ + -D_OPEN_SYS_FILE_EXT \ + -DUV_PLATFORM_SEM_T=int \ + -DPATH_MAX=255 \ + -qCHARS=signed \ + -qXPLINK \ + -qFLOAT=IEEE +libuv_la_LDFLAGS += -qXPLINK +endif + if HAVE_PKG_CONFIG pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = @PACKAGE_NAME@.pc diff --git a/common.gypi b/common.gypi index 56bca294..44db701d 100644 --- a/common.gypi +++ b/common.gypi @@ -11,7 +11,7 @@ 'configurations': { 'Debug': { 'defines': [ 'DEBUG', '_DEBUG' ], - 'cflags': [ '-g', '-O0', '-fwrapv' ], + 'cflags': [ '-g' ], 'msvs_settings': { 'VCCLCompilerTool': { 'target_conditions': [ @@ -35,6 +35,9 @@ 'OTHER_CFLAGS': [ '-Wno-strict-aliasing' ], }, 'conditions': [ + ['OS != "zos"', { + 'cflags': [ '-O0', '-fwrapv' ] + }], ['OS == "android"', { 'cflags': [ '-fPIE' ], 'ldflags': [ '-fPIE', '-pie' ] @@ -151,7 +154,7 @@ 'cflags': [ '-pthreads' ], 'ldflags': [ '-pthreads' ], }], - [ 'OS not in "solaris android"', { + [ 'OS not in "solaris android zos"', { 'cflags': [ '-pthread' ], 'ldflags': [ '-pthread' ], }], diff --git a/configure.ac b/configure.ac index 4a106bec..239e919c 100644 --- a/configure.ac +++ b/configure.ac @@ -24,10 +24,12 @@ AC_ENABLE_SHARED AC_ENABLE_STATIC AC_PROG_CC AM_PROG_CC_C_O +AS_IF([AS_CASE([$host_os],[openedition*], [false], [true])], [ + CC_CHECK_CFLAGS_APPEND([-pedantic]) +]) CC_FLAG_VISIBILITY #[-fvisibility=hidden] CC_CHECK_CFLAGS_APPEND([-g]) CC_CHECK_CFLAGS_APPEND([-std=gnu89]) -CC_CHECK_CFLAGS_APPEND([-pedantic]) CC_CHECK_CFLAGS_APPEND([-Wall]) CC_CHECK_CFLAGS_APPEND([-Wextra]) CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter]) @@ -56,6 +58,7 @@ AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[freebsd*], [true], [false]) AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])]) AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])]) AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])]) +AM_CONDITIONAL([OS390], [AS_CASE([$host_os],[openedition*], [true], [false])]) AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])]) AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])]) AS_CASE([$host_os],[mingw*], [ diff --git a/include/pthread-barrier.h b/include/pthread-barrier.h index 084e1c2d..68468ad2 100644 --- a/include/pthread-barrier.h +++ b/include/pthread-barrier.h @@ -39,6 +39,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2 * sizeof(sem_t) + \ 2 * sizeof(unsigned int) - \ sizeof(void *) +#elif defined(__MVS__) +# define UV_BARRIER_STRUCT_PADDING 0 #endif typedef struct { diff --git a/include/uv-os390.h b/include/uv-os390.h new file mode 100644 index 00000000..b0b068f4 --- /dev/null +++ b/include/uv-os390.h @@ -0,0 +1,27 @@ +/* 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. + */ + +#ifndef UV_MVS_H +#define UV_MVS_H + +#define UV_PLATFORM_SEM_T int + +#endif /* UV_MVS_H */ diff --git a/src/unix/atomic-ops.h b/src/unix/atomic-ops.h index 84e47183..334c343e 100644 --- a/src/unix/atomic-ops.h +++ b/src/unix/atomic-ops.h @@ -42,6 +42,10 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { const int out = (*(volatile int*) ptr); __compare_and_swap(ptr, &oldval, newval); return out; +#elif defined(__MVS__) + const int out = (*(volatile int*) ptr); + cs((cs_t*)&oldval, (cs_t*)ptr, *(cs_t*)(&newval)); + return out; #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif @@ -63,6 +67,14 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) { __compare_and_swap(ptr, &oldval, newval); # endif /* if defined(__64BIT__) */ return out; +#elif defined (__MVS__) + const long out = (*(volatile int*) ptr); +# ifdef _LP64 + cds((cds_t*)(&oldval), (cds_t*)ptr, *(cds_t*)(&newval)); +# else + cs((cs_t*)&oldval, (cs_t*)ptr, *(cs_t*)(&newval)); +# endif + return out; #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif diff --git a/src/unix/core.c b/src/unix/core.c index 64522383..3df966e2 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -74,6 +74,10 @@ # include /* for dlsym */ #endif +#if defined(__MVS__) +#include +#endif + static int uv__run_pending(uv_loop_t* loop); /* Verify that uv_buf_t is ABI-compatible with struct iovec. */ @@ -915,6 +919,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__) rusage->ru_maxrss = usage.ru_maxrss; rusage->ru_ixrss = usage.ru_ixrss; rusage->ru_idrss = usage.ru_idrss; @@ -929,6 +934,7 @@ int uv_getrusage(uv_rusage_t* rusage) { rusage->ru_nsignals = usage.ru_nsignals; rusage->ru_nvcsw = usage.ru_nvcsw; rusage->ru_nivcsw = usage.ru_nivcsw; +#endif return 0; } diff --git a/src/unix/pipe.c b/src/unix/pipe.c index c8d163dc..a3797dda 100644 --- a/src/unix/pipe.c +++ b/src/unix/pipe.c @@ -97,6 +97,14 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { if (uv__stream_fd(handle) == -1) return -EINVAL; +#if defined(__MVS__) + /* On zOS, backlog=0 has undefined behaviour */ + if (backlog == 0) + backlog = 1; + else if (backlog < 0) + backlog = SOMAXCONN; +#endif + if (listen(uv__stream_fd(handle), backlog)) return -errno; diff --git a/src/unix/tcp.c b/src/unix/tcp.c index 46d8cd25..fa52a137 100644 --- a/src/unix/tcp.c +++ b/src/unix/tcp.c @@ -115,6 +115,10 @@ int uv__tcp_bind(uv_tcp_t* tcp, IPV6_V6ONLY, &on, sizeof on) == -1) { +#if defined(__MVS__) + if (errno == EOPNOTSUPP) + return -EINVAL; +#endif return -errno; } } diff --git a/src/unix/thread.c b/src/unix/thread.c index 236f5913..52989f7f 100644 --- a/src/unix/thread.c +++ b/src/unix/thread.c @@ -32,6 +32,11 @@ #include +#ifdef __MVS__ +#include +#include +#endif + #undef NANOSEC #define NANOSEC ((uint64_t) 1e9) @@ -302,6 +307,85 @@ int uv_sem_trywait(uv_sem_t* sem) { return -EINVAL; /* Satisfy the compiler. */ } +#elif defined(__MVS__) + +int uv_sem_init(uv_sem_t* sem, unsigned int value) { + uv_sem_t semid; + struct sembuf buf; + int err; + + buf.sem_num = 0; + buf.sem_op = value; + buf.sem_flg = 0; + + semid = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR); + if (semid == -1) + return -errno; + + if (-1 == semop(semid, &buf, 1)) { + err = errno; + if (-1 == semctl(*sem, 0, IPC_RMID)) + abort(); + return -err; + } + + *sem = semid; + return 0; +} + +void uv_sem_destroy(uv_sem_t* sem) { + if (-1 == semctl(*sem, 0, IPC_RMID)) + abort(); +} + +void uv_sem_post(uv_sem_t* sem) { + struct sembuf buf; + + buf.sem_num = 0; + buf.sem_op = 1; + buf.sem_flg = 0; + + if (-1 == semop(*sem, &buf, 1)) + abort(); +} + +void uv_sem_wait(uv_sem_t* sem) { + struct sembuf buf; + int op_status; + + buf.sem_num = 0; + buf.sem_op = -1; + buf.sem_flg = 0; + + do + op_status = semop(*sem, &buf, 1); + while (op_status == -1 && errno == EINTR); + + if (op_status) + abort(); +} + +int uv_sem_trywait(uv_sem_t* sem) { + struct sembuf buf; + int op_status; + + buf.sem_num = 0; + buf.sem_op = -1; + buf.sem_flg = IPC_NOWAIT; + + do + op_status = semop(*sem, &buf, 1); + while (op_status == -1 && errno == EINTR); + + if (op_status) { + if (errno == EAGAIN) + return -EAGAIN; + abort(); + } + + return 0; +} + #else /* !(defined(__APPLE__) && defined(__MACH__)) */ int uv_sem_init(uv_sem_t* sem, unsigned int value) { @@ -354,7 +438,7 @@ int uv_sem_trywait(uv_sem_t* sem) { #endif /* defined(__APPLE__) && defined(__MACH__) */ -#if defined(__APPLE__) && defined(__MACH__) +#if defined(__APPLE__) && defined(__MACH__) || defined(__MVS__) int uv_cond_init(uv_cond_t* cond) { return -pthread_cond_init(cond, NULL); diff --git a/src/unix/tty.c b/src/unix/tty.c index a56afe18..fd4bcbcf 100644 --- a/src/unix/tty.c +++ b/src/unix/tty.c @@ -30,6 +30,10 @@ #include #include +#if defined(__MVS__) && !defined(IMAXBEL) +#define IMAXBEL 0 +#endif + static int orig_termios_fd = -1; static struct termios orig_termios; static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER; @@ -168,7 +172,7 @@ skip: static void uv__tty_make_raw(struct termios* tio) { assert(tio != NULL); -#ifdef __sun +#if defined __sun || defined __MVS__ /* * This implementation of cfmakeraw for Solaris and derivatives is taken from * http://www.perkin.org.uk/posts/solaris-portability-cfmakeraw.html. diff --git a/src/unix/udp.c b/src/unix/udp.c index f5d7ed14..7c9dae99 100644 --- a/src/unix/udp.c +++ b/src/unix/udp.c @@ -27,6 +27,9 @@ #include #include #include +#if defined(__MVS__) +#include +#endif #if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) # define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP @@ -508,6 +511,10 @@ static int uv__udp_set_membership4(uv_udp_t* handle, optname, &mreq, sizeof(mreq))) { +#if defined(__MVS__) + if (errno == ENXIO) + return -ENODEV; +#endif return -errno; } @@ -551,6 +558,10 @@ static int uv__udp_set_membership6(uv_udp_t* handle, optname, &mreq, sizeof(mreq))) { +#if defined(__MVS__) + if (errno == ENXIO) + return -ENODEV; +#endif return -errno; } @@ -669,7 +680,7 @@ static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option4, int option6, int val) { -#if defined(__sun) || defined(_AIX) +#if defined(__sun) || defined(_AIX) || defined(__MVS__) char arg = val; #elif defined(__OpenBSD__) unsigned char arg = val; @@ -701,19 +712,27 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { if (ttl < 1 || ttl > 255) return -EINVAL; +#if defined(__MVS__) + if (!(handle->flags & UV_HANDLE_IPV6)) + return -ENOTSUP; /* zOS does not support setting ttl for IPv4 */ +#endif + /* * On Solaris and derivatives such as SmartOS, the length of socket options * is sizeof(int) for IP_TTL and IPV6_UNICAST_HOPS, * so hardcode the size of these options on this platform, * and use the general uv__setsockopt_maybe_char call on other platforms. */ -#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) +#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \ + defined(__MVS__) + return uv__setsockopt(handle, IP_TTL, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); -#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) */ +#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) || + defined(__MVS__) */ return uv__setsockopt_maybe_char(handle, IP_TTL, @@ -729,14 +748,14 @@ int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { * IP_MULTICAST_TTL, so hardcode the size of the option in the IPv6 case, * and use the general uv__setsockopt_maybe_char call otherwise. */ -#if defined(__sun) || defined(_AIX) +#if defined(__sun) || defined(_AIX) || defined(__MVS__) if (handle->flags & UV_HANDLE_IPV6) return uv__setsockopt(handle, IP_MULTICAST_TTL, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); -#endif /* defined(__sun) || defined(_AIX) */ +#endif /* defined(__sun) || defined(_AIX) || defined(__MVS__) */ return uv__setsockopt_maybe_char(handle, IP_MULTICAST_TTL, @@ -752,14 +771,14 @@ int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { * IP_MULTICAST_LOOP, so hardcode the size of the option in the IPv6 case, * and use the general uv__setsockopt_maybe_char call otherwise. */ -#if defined(__sun) || defined(_AIX) +#if defined(__sun) || defined(_AIX) || defined(__MVS__) if (handle->flags & UV_HANDLE_IPV6) return uv__setsockopt(handle, IP_MULTICAST_LOOP, IPV6_MULTICAST_LOOP, &on, sizeof(on)); -#endif /* defined(__sun) || defined(_AIX) */ +#endif /* defined(__sun) || defined(_AIX) || defined(__MVS__) */ return uv__setsockopt_maybe_char(handle, IP_MULTICAST_LOOP, diff --git a/test/runner-unix.c b/test/runner-unix.c index 0edd671b..63f801b5 100644 --- a/test/runner-unix.c +++ b/test/runner-unix.c @@ -201,7 +201,11 @@ int process_wait(process_info_t* vec, int n, int timeout) { if (pthread_attr_init(&attr)) abort(); +#if defined(__MVS__) + if (pthread_attr_setstacksize(&attr, 1024 * 1024)) +#else if (pthread_attr_setstacksize(&attr, 256 * 1024)) +#endif abort(); r = pthread_create(&tid, &attr, dowait, &args); @@ -372,7 +376,11 @@ void process_cleanup(process_info_t *p) { /* Move the console cursor one line up and back to the first column. */ void rewind_cursor(void) { +#if defined(__MVS__) + fprintf(stderr, "\047[2K\r"); +#else fprintf(stderr, "\033[2K\r"); +#endif } diff --git a/test/test-emfile.c b/test/test-emfile.c index 5f4dd9ef..8e44ac5c 100644 --- a/test/test-emfile.c +++ b/test/test-emfile.c @@ -38,12 +38,12 @@ static uv_tcp_t client_handle; TEST_IMPL(emfile) { -#ifdef _AIX +#if defined(_AIX) || defined(__MVS__) /* On AIX, if a 'accept' call fails ECONNRESET is set on the socket * which causes uv__emfile_trick to not work as intended and this test * to fail. */ - RETURN_SKIP("uv__emfile_trick does not work on AIX"); + RETURN_SKIP("uv__emfile_trick does not work on this OS"); #endif struct sockaddr_in addr; struct rlimit limits; diff --git a/test/test-fs-event.c b/test/test-fs-event.c index 25eef07b..7dd2cb39 100644 --- a/test/test-fs-event.c +++ b/test/test-fs-event.c @@ -376,6 +376,10 @@ static void timer_cb_watch_twice(uv_timer_t* handle) { } TEST_IMPL(fs_event_watch_dir) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif + uv_loop_t* loop = uv_default_loop(); int r; @@ -455,6 +459,10 @@ TEST_IMPL(fs_event_watch_dir_recursive) { TEST_IMPL(fs_event_watch_file) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif + uv_loop_t* loop = uv_default_loop(); int r; @@ -495,6 +503,11 @@ TEST_IMPL(fs_event_watch_file_exact_path) { This test watches a file named "file.jsx" and modifies a file named "file.js". The test verifies that no events occur for file.jsx. */ + +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif + uv_loop_t* loop; int r; @@ -530,6 +543,9 @@ TEST_IMPL(fs_event_watch_file_exact_path) { } TEST_IMPL(fs_event_watch_file_twice) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif const char path[] = "test/fixtures/empty_file"; uv_fs_event_t watchers[2]; uv_timer_t timer; @@ -551,6 +567,9 @@ TEST_IMPL(fs_event_watch_file_twice) { } TEST_IMPL(fs_event_watch_file_current_dir) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_timer_t timer; uv_loop_t* loop; int r; @@ -621,6 +640,10 @@ TEST_IMPL(fs_event_watch_file_root_dir) { #endif TEST_IMPL(fs_event_no_callback_after_close) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif + uv_loop_t* loop = uv_default_loop(); int r; @@ -655,6 +678,10 @@ TEST_IMPL(fs_event_no_callback_after_close) { } TEST_IMPL(fs_event_no_callback_on_close) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif + uv_loop_t* loop = uv_default_loop(); int r; @@ -702,6 +729,9 @@ static void timer_cb(uv_timer_t* handle) { TEST_IMPL(fs_event_immediate_close) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_timer_t timer; uv_loop_t* loop; int r; @@ -724,6 +754,9 @@ TEST_IMPL(fs_event_immediate_close) { TEST_IMPL(fs_event_close_with_pending_event) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_loop_t* loop; int r; @@ -782,6 +815,9 @@ static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename, TEST_IMPL(fs_event_close_in_callback) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_loop_t* loop; int r; @@ -826,6 +862,9 @@ TEST_IMPL(fs_event_close_in_callback) { #endif /* HAVE_KQUEUE || _AIX */ TEST_IMPL(fs_event_start_and_close) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_loop_t* loop; uv_fs_event_t fs_event1; uv_fs_event_t fs_event2; @@ -858,6 +897,9 @@ TEST_IMPL(fs_event_start_and_close) { } TEST_IMPL(fs_event_getpath) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_loop_t* loop = uv_default_loop(); int r; char buf[1024]; diff --git a/test/test-fs.c b/test/test-fs.c index 250d1350..7c3c6f20 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -29,7 +29,7 @@ /* FIXME we shouldn't need to branch in this file */ #if defined(__unix__) || defined(__POSIX__) || \ - defined(__APPLE__) || defined(_AIX) + defined(__APPLE__) || defined(_AIX) || defined(__MVS__) #include /* unlink, rmdir, etc. */ #else # include diff --git a/test/test-poll.c b/test/test-poll.c index 33d0761a..848ce88a 100644 --- a/test/test-poll.c +++ b/test/test-poll.c @@ -82,9 +82,9 @@ static int closed_connections = 0; static int valid_writable_wakeups = 0; static int spurious_writable_wakeups = 0; -#ifndef _AIX +#if !defined(_AIX) && !defined(__MVS__) static int disconnects = 0; -#endif /* !_AIX */ +#endif /* !_AIX && !__MVS__ */ static int got_eagain(void) { #ifdef _WIN32 @@ -388,7 +388,7 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) { new_events &= ~UV_WRITABLE; } } -#ifndef _AIX +#if !defined(_AIX) && !defined(__MVS__) if (events & UV_DISCONNECT) { context->got_disconnect = 1; ++disconnects; @@ -396,9 +396,9 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) { } if (context->got_fin && context->sent_fin && context->got_disconnect) { -#else /* _AIX */ +#else /* _AIX && __MVS__ */ if (context->got_fin && context->sent_fin) { -#endif /* !_AIx */ +#endif /* !_AIX && !__MVS__ */ /* Sent and received FIN. Close and destroy context. */ close_socket(context->sock); destroy_connection_context(context); @@ -566,7 +566,7 @@ static void start_poll_test(void) { spurious_writable_wakeups > 20); ASSERT(closed_connections == NUM_CLIENTS * 2); -#ifndef _AIX +#if !defined(_AIX) && !defined(__MVS__) ASSERT(disconnects == NUM_CLIENTS * 2); #endif MAKE_VALGRIND_HAPPY(); @@ -594,7 +594,7 @@ TEST_IMPL(poll_unidirectional) { */ TEST_IMPL(poll_bad_fdtype) { #if !defined(__DragonFly__) && !defined(__FreeBSD__) && !defined(__sun) && \ - !defined(_AIX) + !defined(_AIX) && !defined(__MVS__) uv_poll_t poll_handle; int fd; diff --git a/test/test-process-title.c b/test/test-process-title.c index 00f164a4..21ab0ed4 100644 --- a/test/test-process-title.c +++ b/test/test-process-title.c @@ -60,7 +60,7 @@ static void uv_get_process_title_edge_cases() { TEST_IMPL(process_title) { -#if defined(__sun) || defined(_AIX) +#if defined(__sun) || defined(_AIX) || defined(__MVS__) RETURN_SKIP("uv_(get|set)_process_title is not implemented."); #else /* Check for format string vulnerabilities. */ diff --git a/test/test-ref.c b/test/test-ref.c index ddaa1738..39f4b0fc 100644 --- a/test/test-ref.c +++ b/test/test-ref.c @@ -194,6 +194,9 @@ TEST_IMPL(timer_ref2) { TEST_IMPL(fs_event_ref) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_fs_event_t h; uv_fs_event_init(uv_default_loop(), &h); uv_fs_event_start(&h, (uv_fs_event_cb)fail_cb, ".", 0); diff --git a/test/test-spawn.c b/test/test-spawn.c index eba54ae7..0e84ad6d 100644 --- a/test/test-spawn.c +++ b/test/test-spawn.c @@ -1431,6 +1431,9 @@ TEST_IMPL(spawn_fs_open) { #ifndef _WIN32 TEST_IMPL(closed_fd_events) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_stdio_container_t stdio[3]; uv_pipe_t pipe_handle; int fd[2]; @@ -1500,6 +1503,8 @@ TEST_IMPL(spawn_reads_child_path) { */ #if defined(__APPLE__) static const char dyld_path_var[] = "DYLD_LIBRARY_PATH"; +#elif defined __MVS__ + static const char dyld_path_var[] = "LIBPATH"; #else static const char dyld_path_var[] = "LD_LIBRARY_PATH"; #endif diff --git a/test/test-udp-multicast-join6.c b/test/test-udp-multicast-join6.c index f635bdb9..26a27d60 100644 --- a/test/test-udp-multicast-join6.c +++ b/test/test-udp-multicast-join6.c @@ -119,7 +119,7 @@ TEST_IMPL(udp_multicast_join6) { ASSERT(r == 0); /* join the multicast channel */ -#if defined(__APPLE__) || defined(_AIX) +#if defined(__APPLE__) || defined(_AIX) || defined(__MVS__) r = uv_udp_set_membership(&client, "ff02::1", "::1%lo0", UV_JOIN_GROUP); #else r = uv_udp_set_membership(&client, "ff02::1", NULL, UV_JOIN_GROUP); diff --git a/test/test-udp-options.c b/test/test-udp-options.c index 0da1786f..8f913675 100644 --- a/test/test-udp-options.c +++ b/test/test-udp-options.c @@ -52,7 +52,14 @@ static int udp_options_test(const struct sockaddr* addr) { /* values 1-255 should work */ for (i = 1; i <= 255; i++) { r = uv_udp_set_ttl(&h, i); +#if defined(__MVS__) + if (addr->sa_family == AF_INET6) + ASSERT(r == 0); + else + ASSERT(r == UV_ENOTSUP); +#else ASSERT(r == 0); +#endif } for (i = 0; i < (int) ARRAY_SIZE(invalid_ttls); i++) { @@ -113,7 +120,11 @@ TEST_IMPL(udp_no_autobind) { ASSERT(0 == uv_udp_init(loop, &h)); ASSERT(UV_EBADF == uv_udp_set_multicast_ttl(&h, 32)); ASSERT(UV_EBADF == uv_udp_set_broadcast(&h, 1)); +#if defined(__MVS__) + ASSERT(UV_ENOTSUP == uv_udp_set_ttl(&h, 1)); +#else ASSERT(UV_EBADF == uv_udp_set_ttl(&h, 1)); +#endif ASSERT(UV_EBADF == uv_udp_set_multicast_loop(&h, 1)); ASSERT(UV_EBADF == uv_udp_set_multicast_interface(&h, "0.0.0.0")); diff --git a/test/test-watcher-cross-stop.c b/test/test-watcher-cross-stop.c index 910ed0fb..6ff48d44 100644 --- a/test/test-watcher-cross-stop.c +++ b/test/test-watcher-cross-stop.c @@ -59,6 +59,9 @@ static void close_cb(uv_handle_t* handle) { TEST_IMPL(watcher_cross_stop) { +#if defined(__MVS__) + RETURN_SKIP("zOS does not allow address or port reuse when using UDP sockets"); +#endif uv_loop_t* loop = uv_default_loop(); unsigned int i; struct sockaddr_in addr; diff --git a/uv.gyp b/uv.gyp index 953a6fdc..3a480dea 100644 --- a/uv.gyp +++ b/uv.gyp @@ -10,9 +10,25 @@ ['OS=="solaris"', { 'cflags': [ '-pthreads' ], }], - ['OS not in "solaris android"', { + ['OS not in "solaris android zos"', { 'cflags': [ '-pthread' ], }], + ['OS in "zos"', { + 'defines': [ + '_UNIX03_THREADS', + '_UNIX03_SOURCE', + '_OPEN_SYS_IF_EXT', + '_OPEN_SYS_SOCK_IPV6', + '_OPEN_MSGQ_EXT', + '_XOPEN_SOURCE_EXTENDED', + '_ALL_SOURCE', + '_LARGE_TIME_API', + '_OPEN_SYS_FILE_EXT', + '_AE_BIMODAL', + 'PATH_MAX=255' + ], + 'cflags': [ '-qxplink' ], + }] ], }], ], @@ -119,15 +135,6 @@ ], }, }, { # Not Windows i.e. POSIX - 'cflags': [ - '-fvisibility=hidden', - '-g', - '--std=gnu89', - '-pedantic', - '-Wall', - '-Wextra', - '-Wno-unused-parameter', - ], 'sources': [ 'include/uv-unix.h', 'include/uv-linux.h', @@ -163,16 +170,25 @@ ['OS=="solaris"', { 'ldflags': [ '-pthreads' ], }], - ['OS != "solaris" and OS != "android"', { + [ 'OS=="zos" and uv_library=="shared_library"', { + 'ldflags': [ '-Wl,DLL' ], + }], + ['OS != "solaris" and OS != "android" and OS != "zos"', { 'ldflags': [ '-pthread' ], }], ], }, 'conditions': [ ['uv_library=="shared_library"', { - 'cflags': [ '-fPIC' ], + 'conditions': [ + ['OS=="zos"', { + 'cflags': [ '-qexportall' ], + }, { + 'cflags': [ '-fPIC' ], + }], + ], }], - ['uv_library=="shared_library" and OS!="mac"', { + ['uv_library=="shared_library" and OS!="mac" and OS!="zos"', { # This will cause gyp to set soname # Must correspond with UV_VERSION_MAJOR # in include/uv-version.h @@ -183,6 +199,17 @@ [ 'OS in "linux mac ios android"', { 'sources': [ 'src/unix/proctitle.c' ], }], + [ 'OS != "zos"', { + 'cflags': [ + '-fvisibility=hidden', + '-g', + '--std=gnu89', + '-pedantic', + '-Wall', + '-Wextra', + '-Wno-unused-parameter', + ], + }], [ 'OS in "mac ios"', { 'sources': [ 'src/unix/darwin.c', @@ -195,7 +222,7 @@ '_DARWIN_UNLIMITED_SELECT=1', ] }], - [ 'OS!="mac"', { + [ 'OS!="mac" and OS!="zos"', { # Enable on all platforms except OS X. The antique gcc/clang that # ships with Xcode emits waaaay too many false positives. 'cflags': [ '-Wstrict-aliasing' ], @@ -428,13 +455,17 @@ ], 'libraries': [ '-lws2_32' ] }, { # POSIX - 'defines': [ '_GNU_SOURCE' ], - 'cflags': [ '-Wno-long-long' ], 'sources': [ 'test/runner-unix.c', 'test/runner-unix.h', ], - }], + 'conditions': [ + [ 'OS != "zos"', { + 'defines': [ '_GNU_SOURCE' ], + 'cflags': [ '-Wno-long-long' ], + }], + ]}, + ], [ 'OS in "mac dragonflybsd freebsd linux netbsd openbsd".split()', { 'link_settings': { 'libraries': [ '-lutil' ], @@ -453,7 +484,12 @@ ], }], ['uv_library=="shared_library"', { - 'defines': [ 'USING_UV_SHARED=1' ] + 'defines': [ 'USING_UV_SHARED=1' ], + 'conditions': [ + [ 'OS == "zos"', { + 'cflags': [ '-Wc,DLL' ], + }], + ], }], ], 'msvs-settings': { @@ -509,7 +545,12 @@ ] }], ['uv_library=="shared_library"', { - 'defines': [ 'USING_UV_SHARED=1' ] + 'defines': [ 'USING_UV_SHARED=1' ], + 'conditions': [ + [ 'OS == "zos"', { + 'cflags': [ '-Wc,DLL' ], + }], + ], }], ], 'msvs-settings': { From e9940008349d2e7dcb1bde2fe9cf08d3ea806d41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Thu, 18 Aug 2016 13:02:57 +0100 Subject: [PATCH 02/35] test: make tcp_close_while_connecting more resilient It's not impossible for connect() to succeed before the handle is fully closed, so handle that case too. PR-URL: https://github.com/libuv/libuv/pull/1005 Reviewed-By: Ben Noordhuis --- test/test-tcp-close-while-connecting.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-tcp-close-while-connecting.c b/test/test-tcp-close-while-connecting.c index 60df7a57..90a31f31 100644 --- a/test/test-tcp-close-while-connecting.c +++ b/test/test-tcp-close-while-connecting.c @@ -37,7 +37,7 @@ static void close_cb(uv_handle_t* handle) { static void connect_cb(uv_connect_t* req, int status) { - ASSERT(status == UV_ECANCELED); + ASSERT(status == UV_ECANCELED || status == 0); uv_timer_stop(&timer2_handle); connect_cb_called++; } From e5c93a1589fd1d39336854356f23b5cfa5cada52 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 11 Aug 2016 09:08:57 +0100 Subject: [PATCH 03/35] build: use '${prefix}' for pkg-config 'exec_prefix' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This follows common pkg-config configuration files and allows for certain pkg-config overrides to work. For example, when cross-compiling it is common to have to set a different pkg-config prefix through either '--define-prefix' or a 'PKG_CONFIG_LIBUV_PREFIX' environment variable. If the 'exec_prefix' is hardcoded to '@prefix@' then it will not pick up those pkg-config overrides. PR-URL: https://github.com/libuv/libuv/pull/993 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé --- libuv.pc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libuv.pc.in b/libuv.pc.in index 2933ec22..9174fe15 100644 --- a/libuv.pc.in +++ b/libuv.pc.in @@ -1,5 +1,5 @@ prefix=@prefix@ -exec_prefix=@prefix@ +exec_prefix=${prefix} libdir=@libdir@ includedir=@includedir@ From 0a4b51fcb408c47c6dfa2f5e04d8da44920772c4 Mon Sep 17 00:00:00 2001 From: Jeffrey Clark Date: Thu, 28 Jul 2016 14:26:01 -0500 Subject: [PATCH 04/35] build: GNU/kFreeBSD support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit autotools support only, gvp does not support kfreebsd detection. PR-URL: https://github.com/libuv/libuv/pull/960 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé --- configure.ac | 2 +- include/uv-errno.h | 1 + include/uv-unix.h | 7 ++++--- src/unix/core.c | 4 +++- src/unix/fs.c | 22 ++++++++++++++++++---- src/unix/internal.h | 1 + src/unix/process.c | 2 +- src/unix/tty.c | 2 +- test/test-embed.c | 1 + test/test-fs-event.c | 1 + test/test-poll.c | 2 +- test/test-tty.c | 12 +++++++++--- test/test-udp-ipv6.c | 6 +++--- test/test-udp-multicast-interface6.c | 2 +- test/test-udp-multicast-join6.c | 5 ++++- 15 files changed, 50 insertions(+), 20 deletions(-) diff --git a/configure.ac b/configure.ac index 239e919c..90335b4a 100644 --- a/configure.ac +++ b/configure.ac @@ -54,7 +54,7 @@ AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false]) AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[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([FREEBSD], [AS_CASE([$host_os],[*freebsd*], [true], [false])]) AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])]) AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])]) AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])]) diff --git a/include/uv-errno.h b/include/uv-errno.h index 53f30296..f1371517 100644 --- a/include/uv-errno.h +++ b/include/uv-errno.h @@ -408,6 +408,7 @@ #elif defined(__APPLE__) || \ defined(__DragonFly__) || \ defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || \ defined(__NetBSD__) || \ defined(__OpenBSD__) # define UV__EHOSTDOWN (-64) diff --git a/include/uv-unix.h b/include/uv-unix.h index a852c40e..bca27144 100644 --- a/include/uv-unix.h +++ b/include/uv-unix.h @@ -50,9 +50,10 @@ # include "uv-sunos.h" #elif defined(__APPLE__) # include "uv-darwin.h" -#elif defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ +#elif defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || \ + defined(__OpenBSD__) || \ defined(__NetBSD__) # include "uv-bsd.h" #endif diff --git a/src/unix/core.c b/src/unix/core.c index 3df966e2..d88fc1de 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -55,7 +55,9 @@ # endif #endif -#if defined(__FreeBSD__) || defined(__DragonFly__) +#if defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) # include # include # include diff --git a/src/unix/fs.c b/src/unix/fs.c index 0b2505e4..37f8e3b6 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -46,9 +46,10 @@ #include #include -#if defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ +#if defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel_) || \ + defined(__OpenBSD__) || \ defined(__NetBSD__) # define HAVE_PREADV 1 #else @@ -193,6 +194,7 @@ skip: #elif defined(__APPLE__) \ || defined(__DragonFly__) \ || defined(__FreeBSD__) \ + || defined(__FreeBSD_kernel__) \ || defined(__NetBSD__) \ || defined(__OpenBSD__) \ || defined(__sun) @@ -595,7 +597,10 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) { return -1; } -#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__) +#elif defined(__APPLE__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) { off_t len; ssize_t r; @@ -608,6 +613,15 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) { #if defined(__FreeBSD__) || defined(__DragonFly__) len = 0; r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0); +#elif defined(__FreeBSD_kernel__) + len = 0; + r = bsd_sendfile(in_fd, + out_fd, + req->off, + req->bufsml[0].len, + NULL, + &len, + 0); #else /* The darwin sendfile takes len as an input for the length to send, * so make sure to initialize it with the caller's value. */ diff --git a/src/unix/internal.h b/src/unix/internal.h index 4cae7376..7cc8ee8b 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -156,6 +156,7 @@ struct uv__stream_queued_fds_s { defined(__APPLE__) || \ defined(__DragonFly__) || \ defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || \ defined(__linux__) #define uv__cloexec uv__cloexec_ioctl #define uv__nonblock uv__nonblock_ioctl diff --git a/src/unix/process.c b/src/unix/process.c index 8a010edc..45f5b452 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -40,7 +40,7 @@ extern char **environ; #endif -#ifdef __linux__ +#if defined(__linux__) || defined(__GLIBC__) # include #endif diff --git a/src/unix/tty.c b/src/unix/tty.c index fd4bcbcf..b2d37f4c 100644 --- a/src/unix/tty.c +++ b/src/unix/tty.c @@ -40,7 +40,7 @@ static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER; static int uv__tty_is_slave(const int fd) { int result; -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) int dummy; result = ioctl(fd, TIOCGPTN, &dummy) != 0; diff --git a/test/test-embed.c b/test/test-embed.c index 06137456..c6ddceb1 100644 --- a/test/test-embed.c +++ b/test/test-embed.c @@ -29,6 +29,7 @@ # if defined(__APPLE__) || \ defined(__DragonFly__) || \ defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || \ defined(__OpenBSD__) || \ defined(__NetBSD__) # define HAVE_KQUEUE 1 diff --git a/test/test-fs-event.c b/test/test-fs-event.c index 7dd2cb39..fc6e8ad9 100644 --- a/test/test-fs-event.c +++ b/test/test-fs-event.c @@ -29,6 +29,7 @@ # if defined(__APPLE__) || \ defined(__DragonFly__) || \ defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || \ defined(__OpenBSD__) || \ defined(__NetBSD__) # define HAVE_KQUEUE 1 diff --git a/test/test-poll.c b/test/test-poll.c index 848ce88a..6c1f98b7 100644 --- a/test/test-poll.c +++ b/test/test-poll.c @@ -594,7 +594,7 @@ TEST_IMPL(poll_unidirectional) { */ TEST_IMPL(poll_bad_fdtype) { #if !defined(__DragonFly__) && !defined(__FreeBSD__) && !defined(__sun) && \ - !defined(_AIX) && !defined(__MVS__) + !defined(_AIX) && !defined(__MVS__) && !defined(__FreeBSD_kernel__) uv_poll_t poll_handle; int fd; diff --git a/test/test-tty.c b/test/test-tty.c index c93fe75a..780968c4 100644 --- a/test/test-tty.c +++ b/test/test-tty.c @@ -28,7 +28,7 @@ #else /* Unix */ # include # include -# if defined(__linux__) && !defined(__ANDROID__) +# if (defined(__linux__) || defined(__GLIBC__)) && !defined(__ANDROID__) # include # elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) # include @@ -260,8 +260,14 @@ TEST_IMPL(tty_file) { } TEST_IMPL(tty_pty) { -# if defined(__linux__) && !defined(__ANDROID__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ - defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) +#if defined(__ANDROID__) || \ + defined(__APPLE__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || \ + defined(__linux__) || \ + defined(__NetBSD__) || \ + defined(__OpenBSD__) int master_fd, slave_fd, r; struct winsize w; uv_loop_t loop; diff --git a/test/test-udp-ipv6.c b/test/test-udp-ipv6.c index 1b0db78b..a65f09e0 100644 --- a/test/test-udp-ipv6.c +++ b/test/test-udp-ipv6.c @@ -26,7 +26,7 @@ #include #include -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include #endif @@ -47,7 +47,7 @@ static int send_cb_called; static int recv_cb_called; static int close_cb_called; -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) static int can_ipv6_ipv4_dual() { int v6only; size_t size = sizeof(int); @@ -166,7 +166,7 @@ TEST_IMPL(udp_dual_stack) { if (!can_ipv6()) RETURN_SKIP("IPv6 not supported"); -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) if (!can_ipv6_ipv4_dual()) RETURN_SKIP("IPv6-IPv4 dual stack not supported"); #endif diff --git a/test/test-udp-multicast-interface6.c b/test/test-udp-multicast-interface6.c index d3881e83..40b05536 100644 --- a/test/test-udp-multicast-interface6.c +++ b/test/test-udp-multicast-interface6.c @@ -72,7 +72,7 @@ TEST_IMPL(udp_multicast_interface6) { r = uv_udp_bind(&server, (const struct sockaddr*)&baddr, 0); ASSERT(r == 0); -#if defined(__APPLE__) || defined(__FreeBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) r = uv_udp_set_multicast_interface(&server, "::1%lo0"); #else r = uv_udp_set_multicast_interface(&server, NULL); diff --git a/test/test-udp-multicast-join6.c b/test/test-udp-multicast-join6.c index 26a27d60..2eb9e920 100644 --- a/test/test-udp-multicast-join6.c +++ b/test/test-udp-multicast-join6.c @@ -119,7 +119,10 @@ TEST_IMPL(udp_multicast_join6) { ASSERT(r == 0); /* join the multicast channel */ -#if defined(__APPLE__) || defined(_AIX) || defined(__MVS__) +#if defined(__APPLE__) || \ + defined(_AIX) || \ + defined(__MVS__) || \ + defined(__FreeBSD_kernel__) r = uv_udp_set_membership(&client, "ff02::1", "::1%lo0", UV_JOIN_GROUP); #else r = uv_udp_set_membership(&client, "ff02::1", NULL, UV_JOIN_GROUP); From 841edfcd40fb2243ca434f7b87c0e10d1a40c7c1 Mon Sep 17 00:00:00 2001 From: John Barboza Date: Sun, 21 Aug 2016 13:53:29 -0400 Subject: [PATCH 05/35] zos: use PLO instruction for atomic operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use builtins provided that perform compare and swap operations using the PLO instruction. PR-URL: https://github.com/libuv/libuv/pull/1008 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé --- src/unix/atomic-ops.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/unix/atomic-ops.h b/src/unix/atomic-ops.h index 334c343e..815e3552 100644 --- a/src/unix/atomic-ops.h +++ b/src/unix/atomic-ops.h @@ -43,9 +43,8 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { __compare_and_swap(ptr, &oldval, newval); return out; #elif defined(__MVS__) - const int out = (*(volatile int*) ptr); - cs((cs_t*)&oldval, (cs_t*)ptr, *(cs_t*)(&newval)); - return out; + return __plo_CS(ptr, (unsigned int*) ptr, + oldval, (unsigned int*) &newval); #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif @@ -68,13 +67,13 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) { # endif /* if defined(__64BIT__) */ return out; #elif defined (__MVS__) - const long out = (*(volatile int*) ptr); # ifdef _LP64 - cds((cds_t*)(&oldval), (cds_t*)ptr, *(cds_t*)(&newval)); + return __plo_CSGR(ptr, (unsigned long long*) ptr, + oldval, (unsigned long long*) &newval); # else - cs((cs_t*)&oldval, (cs_t*)ptr, *(cs_t*)(&newval)); + return __plo_CS(ptr, (unsigned int*) ptr, + oldval, (unsigned int*) &newval); # endif - return out; #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif From 00c0ff149d7a33801853f08dfcb6f175a8b6b576 Mon Sep 17 00:00:00 2001 From: John Barboza Date: Sun, 24 Jul 2016 18:11:18 -0400 Subject: [PATCH 06/35] zos: use pthread helper functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit zOS does not implement some pthread_barrier functions. So we will use the provided helper functions in src/unix/pthread*. PR-URL: https://github.com/libuv/libuv/pull/954 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé --- Makefile.am | 2 ++ uv.gyp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/Makefile.am b/Makefile.am index aab6b0c8..8d5e68b5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -390,6 +390,8 @@ libuv_la_CFLAGS += -D_UNIX03_THREADS \ -qXPLINK \ -qFLOAT=IEEE libuv_la_LDFLAGS += -qXPLINK +libuv_la_SOURCES += src/unix/pthread-fixes.c \ + src/unix/pthread-barrier.c endif if HAVE_PKG_CONFIG diff --git a/uv.gyp b/uv.gyp index 3a480dea..a2edc9ec 100644 --- a/uv.gyp +++ b/uv.gyp @@ -302,6 +302,12 @@ ['uv_library=="shared_library"', { 'defines': [ 'BUILDING_UV_SHARED=1' ] }], + ['OS=="zos"', { + 'sources': [ + 'src/unix/pthread-fixes.c', + 'src/unix/pthread-barrier.c' + ] + }], ] }, From 404025721fe13d631c3fb65ddbf54d6263deeaf1 Mon Sep 17 00:00:00 2001 From: John Barboza Date: Mon, 25 Jul 2016 09:14:17 -0400 Subject: [PATCH 07/35] zos: implement uv__fs_futime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We do this using __fchattr syscall to change file attributes. PR-URL: https://github.com/libuv/libuv/pull/956 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé --- src/unix/fs.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/unix/fs.c b/src/unix/fs.c index 37f8e3b6..216ef970 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -215,6 +215,14 @@ skip: ts[1].tv_sec = req->mtime; ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; return futimens(req->file, ts); +#elif defined(__MVS__) + attrib_t atr; + memset(&atr, 0, sizeof(atr)); + atr.att_mtimechg = 1; + atr.att_atimechg = 1; + atr.att_mtime = req->mtime; + atr.att_atime = req->atime; + return __fchattr(req->file, &atr, sizeof(atr)); #else errno = ENOSYS; return -1; From e37f25d7762ca7f5cc71bf661bc06f405beb7309 Mon Sep 17 00:00:00 2001 From: John Barboza Date: Tue, 19 Jul 2016 08:11:30 -0400 Subject: [PATCH 08/35] unix: expand range of values for usleep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit uv_sleep uses only usleep which can only take integers in the range [0,1000000]. Avoid using boundary parameters such as 1000000 for portability reasons. Use sleep and usleep together to expand the acceptable range of values for uv_sleep. PR-URL: https://github.com/libuv/libuv/pull/950 Reviewed-By: Imran Iqbal Reviewed-By: Saúl Ibarra Corretgé --- test/runner-unix.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/runner-unix.c b/test/runner-unix.c index 63f801b5..2ff18ce7 100644 --- a/test/runner-unix.c +++ b/test/runner-unix.c @@ -386,5 +386,13 @@ void rewind_cursor(void) { /* Pause the calling thread for a number of milliseconds. */ void uv_sleep(int msec) { - usleep(msec * 1000); + int sec; + int usec; + + sec = msec / 1000; + usec = (msec % 1000) * 1000; + if (sec > 0) + sleep(sec); + if (usec > 0) + usleep(usec); } From f4ef8976666db685a22379e76b397ac6aefed900 Mon Sep 17 00:00:00 2001 From: John Barboza Date: Tue, 19 Jul 2016 09:07:28 -0400 Subject: [PATCH 09/35] zos: track unbound handles and bind before listen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On zOS the listen call does not bind automatically if the socket is unbound. Hence the manual binding to an arbitrary port is required to be done manually. PR-URL: https://github.com/libuv/libuv/pull/949 Reviewed-By: Saúl Ibarra Corretgé --- src/unix/internal.h | 3 ++- src/unix/pipe.c | 1 + src/unix/stream.c | 2 ++ src/unix/tcp.c | 23 +++++++++++++++++++++++ src/unix/udp.c | 2 ++ 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/unix/internal.h b/src/unix/internal.h index 7cc8ee8b..c7b6019e 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -132,7 +132,8 @@ enum { UV_TCP_KEEPALIVE = 0x800, /* Turn on keep-alive. */ UV_TCP_SINGLE_ACCEPT = 0x1000, /* Only accept() when idle. */ UV_HANDLE_IPV6 = 0x10000, /* Handle is bound to a IPv6 socket. */ - UV_UDP_PROCESSING = 0x20000 /* Handle is running the send callback queue. */ + UV_UDP_PROCESSING = 0x20000, /* Handle is running the send callback queue. */ + UV_HANDLE_BOUND = 0x40000 /* Handle is bound to an address and port */ }; /* loop flags */ diff --git a/src/unix/pipe.c b/src/unix/pipe.c index a3797dda..b73994cb 100644 --- a/src/unix/pipe.c +++ b/src/unix/pipe.c @@ -80,6 +80,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { } /* Success. */ + handle->flags |= UV_HANDLE_BOUND; handle->pipe_fname = pipe_fname; /* Is a strdup'ed copy. */ handle->io_watcher.fd = sockfd; return 0; diff --git a/src/unix/stream.c b/src/unix/stream.c index 5dc2f83f..d20d0bcb 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -604,6 +604,8 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) { return -EINVAL; } + client->flags |= UV_HANDLE_BOUND; + done: /* Process queued fds */ if (server->queued_fds != NULL) { diff --git a/src/unix/tcp.c b/src/unix/tcp.c index fa52a137..c423dcb1 100644 --- a/src/unix/tcp.c +++ b/src/unix/tcp.c @@ -134,6 +134,7 @@ int uv__tcp_bind(uv_tcp_t* tcp, } tcp->delayed_error = -errno; + tcp->flags |= UV_HANDLE_BOUND; if (addr->sa_family == AF_INET6) tcp->flags |= UV_HANDLE_IPV6; @@ -276,10 +277,32 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { if (err) return err; +#ifdef __MVS__ + /* on zOS the listen call does not bind automatically + if the socket is unbound. Hence the manual binding to + an arbitrary port is required to be done manually + */ + + if (!(tcp->flags & UV_HANDLE_BOUND)) { + struct sockaddr_storage saddr; + socklen_t slen = sizeof(saddr); + memset(&saddr, 0, sizeof(saddr)); + + if (getsockname(tcp->io_watcher.fd, (struct sockaddr*) &saddr, &slen)) + return -errno; + + if (bind(tcp->io_watcher.fd, (struct sockaddr*) &saddr, slen)) + return -errno; + + tcp->flags |= UV_HANDLE_BOUND; + } +#endif + if (listen(tcp->io_watcher.fd, backlog)) return -errno; tcp->connection_cb = cb; + tcp->flags |= UV_HANDLE_BOUND; /* Start listening for connections. */ tcp->io_watcher.cb = uv__server_io; diff --git a/src/unix/udp.c b/src/unix/udp.c index 7c9dae99..1cd49257 100644 --- a/src/unix/udp.c +++ b/src/unix/udp.c @@ -335,6 +335,8 @@ int uv__udp_bind(uv_udp_t* handle, if (addr->sa_family == AF_INET6) handle->flags |= UV_HANDLE_IPV6; + handle->flags |= UV_HANDLE_BOUND; + return 0; out: From 282dc7bc227eed61df2c3b657de4be351995e972 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Mon, 22 Aug 2016 13:30:52 +0200 Subject: [PATCH 10/35] test: improve tap output on test failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print `errmsg` on TAP output. After making the TAP output the default, the info in `errmsg` was not being used anymore. PR-URL: https://github.com/libuv/libuv/pull/1012 Reviewed-By: Colin Ihrig Reviewed-By: Imran Iqbal Reviewed-By: Saúl Ibarra Corretgé --- test/runner.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/runner.c b/test/runner.c index 5e22c18f..4f54f85e 100644 --- a/test/runner.c +++ b/test/runner.c @@ -145,7 +145,7 @@ void log_tap_result(int test_count, int run_test(const char* test, int benchmark_output, int test_count) { - char errmsg[1024] = "no error"; + char errmsg[1024] = ""; process_info_t processes[1024]; process_info_t *main_proc; task_entry_t* task; @@ -274,6 +274,8 @@ out: /* Show error and output from processes if the test failed. */ if ((status != TEST_OK && status != TEST_SKIP) || task->show_output) { + if (strlen(errmsg) > 0) + fprintf(stderr, "# %s\n", errmsg); fprintf(stderr, "# "); fflush(stderr); From ad20b96a8f258db79f67d7465a7373737e253802 Mon Sep 17 00:00:00 2001 From: Julien Gilli Date: Mon, 22 Aug 2016 10:08:45 -0700 Subject: [PATCH 11/35] test: refactor fs_event_close_in_callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change refactors the `fs_event_close_in_callback` test so that: 1. It creates directory entries instead of modifying them. This allows the test to work on operating systems that use event ports to handle fs events (e.g SmartOS and Solaris). When using event ports, watching only a directory does not allow to receive events for files modified within that directory, but events will be received for files _created_ within that directory. 2. it generates fs events _after_ the process entered the libuv event loop. This is also needed to make the test work on operating systems that use event ports to handle fs events (e.g SmartOS and Solaris), because events are polled as part of running the event loop. That also makes the test work on systems based on Kqueue and on AIX. Fixes: https://github.com/libuv/libuv/pull/808 PR-URL: https://github.com/libuv/libuv/pull/1011 Reviewed-By: Saúl Ibarra Corretgé --- test/test-fs-event.c | 45 +++++++++++--------------------------------- 1 file changed, 11 insertions(+), 34 deletions(-) diff --git a/test/test-fs-event.c b/test/test-fs-event.c index fc6e8ad9..5b7774b6 100644 --- a/test/test-fs-event.c +++ b/test/test-fs-event.c @@ -788,20 +788,6 @@ TEST_IMPL(fs_event_close_with_pending_event) { return 0; } -#if defined(HAVE_KQUEUE) || defined(_AIX) - -/* kqueue doesn't register fs events if you don't have an active watcher. - * The file descriptor needs to be part of the kqueue set of interest and - * that's not the case until we actually enter the event loop. - * This is also observed on AIX with ahafs. - */ -TEST_IMPL(fs_event_close_in_callback) { - fprintf(stderr, "Skipping test, doesn't work with kqueue and AIX.\n"); - return 0; -} - -#else /* !HAVE_KQUEUE || !_AIX */ - static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename, int events, int status) { ASSERT(status == 0); @@ -814,7 +800,6 @@ static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename, } } - TEST_IMPL(fs_event_close_in_callback) { #if defined(__MVS__) RETURN_SKIP("Filesystem watching not supported on this platform."); @@ -824,44 +809,36 @@ TEST_IMPL(fs_event_close_in_callback) { loop = uv_default_loop(); + fs_event_unlink_files(NULL); create_dir("watch_dir"); - create_file("watch_dir/file1"); - create_file("watch_dir/file2"); - create_file("watch_dir/file3"); - create_file("watch_dir/file4"); - create_file("watch_dir/file5"); r = uv_fs_event_init(loop, &fs_event); ASSERT(r == 0); r = uv_fs_event_start(&fs_event, fs_event_cb_close, "watch_dir", 0); ASSERT(r == 0); - /* Generate a couple of fs events. */ - touch_file("watch_dir/file1"); - touch_file("watch_dir/file2"); - touch_file("watch_dir/file3"); - touch_file("watch_dir/file4"); - touch_file("watch_dir/file5"); + r = uv_timer_init(loop, &timer); + ASSERT(r == 0); + r = uv_timer_start(&timer, fs_event_create_files, 100, 0); + ASSERT(r == 0); uv_run(loop, UV_RUN_DEFAULT); - ASSERT(close_cb_called == 1); + uv_close((uv_handle_t*)&timer, close_cb); + + uv_run(loop, UV_RUN_ONCE); + + ASSERT(close_cb_called == 2); ASSERT(fs_event_cb_called == 3); /* Clean up */ - remove("watch_dir/file1"); - remove("watch_dir/file2"); - remove("watch_dir/file3"); - remove("watch_dir/file4"); - remove("watch_dir/file5"); + fs_event_unlink_files(NULL); remove("watch_dir/"); MAKE_VALGRIND_HAPPY(); return 0; } -#endif /* HAVE_KQUEUE || _AIX */ - TEST_IMPL(fs_event_start_and_close) { #if defined(__MVS__) RETURN_SKIP("Filesystem watching not supported on this platform."); From 9e641d251fa48c74faabd2b5506f8d972bdb93f3 Mon Sep 17 00:00:00 2001 From: John Barboza Date: Sun, 24 Jul 2016 21:54:08 -0400 Subject: [PATCH 12/35] zos: implement uv__io_check_fd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This method uses the poll syscall to determine whether POLLNVAL is flagged or not. PR-URL: https://github.com/libuv/libuv/pull/957 Reviewed-By: Saúl Ibarra Corretgé --- Makefile.am | 1 + src/unix/os390.c | 42 ++++++++++++++++++++++++++++++++++++++++++ uv.gyp | 1 + 3 files changed, 44 insertions(+) create mode 100644 src/unix/os390.c diff --git a/Makefile.am b/Makefile.am index 8d5e68b5..adda2218 100644 --- a/Makefile.am +++ b/Makefile.am @@ -392,6 +392,7 @@ libuv_la_CFLAGS += -D_UNIX03_THREADS \ libuv_la_LDFLAGS += -qXPLINK libuv_la_SOURCES += src/unix/pthread-fixes.c \ src/unix/pthread-barrier.c +libuv_la_SOURCES += src/unix/os390.c endif if HAVE_PKG_CONFIG diff --git a/src/unix/os390.c b/src/unix/os390.c new file mode 100644 index 00000000..bcdbc4b6 --- /dev/null +++ b/src/unix/os390.c @@ -0,0 +1,42 @@ +/* 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 "internal.h" + +int uv__io_check_fd(uv_loop_t* loop, int fd) { + struct pollfd p[1]; + int rv; + + p[0].fd = fd; + p[0].events = POLLIN; + + do + rv = poll(p, 1, 0); + while (rv == -1 && errno == EINTR); + + if (rv == -1) + abort(); + + if (p[0].revents & POLLNVAL) + return -1; + + return 0; +} diff --git a/uv.gyp b/uv.gyp index a2edc9ec..4d1a0346 100644 --- a/uv.gyp +++ b/uv.gyp @@ -306,6 +306,7 @@ 'sources': [ 'src/unix/pthread-fixes.c', 'src/unix/pthread-barrier.c' + 'src/unix/os390.c' ] }], ] From afc93d1ed607822f7ae77386f48d7226286d62c0 Mon Sep 17 00:00:00 2001 From: John Barboza Date: Mon, 18 Jul 2016 15:46:55 -0400 Subject: [PATCH 13/35] unix: unneccessary use const qualifier in container_of MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The type parameter in the "container_of(ptr, type, member)" macro which uses builtin "offsetof(type, member)" should not require cv qualifier. Also note that for some platforms, the "offsetof" builtin does not recognize the cv qualifier in the type. PR-URL: https://github.com/libuv/libuv/pull/948 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé --- src/unix/timer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/unix/timer.c b/src/unix/timer.c index ca3ec3db..f46bdf4b 100644 --- a/src/unix/timer.c +++ b/src/unix/timer.c @@ -31,8 +31,8 @@ static int timer_less_than(const struct heap_node* ha, const uv_timer_t* a; const uv_timer_t* b; - a = container_of(ha, const uv_timer_t, heap_node); - b = container_of(hb, const uv_timer_t, heap_node); + a = container_of(ha, uv_timer_t, heap_node); + b = container_of(hb, uv_timer_t, heap_node); if (a->timeout < b->timeout) return 1; @@ -135,7 +135,7 @@ int uv__next_timeout(const uv_loop_t* loop) { if (heap_node == NULL) return -1; /* block indefinitely */ - handle = container_of(heap_node, const uv_timer_t, heap_node); + handle = container_of(heap_node, uv_timer_t, heap_node); if (handle->timeout <= loop->time) return 0; From 58ccfd4c210d3cc1a36dd82474976aac296589f2 Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Tue, 17 May 2016 15:46:34 -0400 Subject: [PATCH 14/35] win,tty: add support for ANSI codes in win10 v1511 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/889 Reviewed-By: Saúl Ibarra Corretgé --- src/win/tty.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/win/tty.c b/src/win/tty.c index 9bb7879d..2a58a6f7 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -57,6 +57,9 @@ #define MAX_INPUT_BUFFER_LENGTH 8192 +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 +#endif static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info); static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info); @@ -121,6 +124,14 @@ static char uv_tty_default_fg_bright = 0; static char uv_tty_default_bg_bright = 0; static char uv_tty_default_inverse = 0; +typedef enum { + UV_SUPPORTED, + UV_UNCHECKED, + UV_UNSUPPORTED +} uv_vtermstate_t; +/* Determine whether or not ANSI support is enabled. */ +static vtermstate_t uv__vterm_state = UV_UNCHECKED; +static void uv__determine_vterm_state(HANDLE handle); void uv_console_init() { InitializeCriticalSection(&uv_tty_output_lock); @@ -163,6 +174,9 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { /* shared between all uv_tty_t handles. */ EnterCriticalSection(&uv_tty_output_lock); + if (uv__vterm_state == UV_UNCHECKED) + uv__determine_vterm_state(handle); + /* Store the global tty output handle. This handle is used by TTY read */ /* streams to update the virtual window when a CONSOLE_BUFFER_SIZE_EVENT */ /* is received. */ @@ -1616,6 +1630,33 @@ static int uv_tty_write_bufs(uv_tty_t* handle, uv_buf_t buf = bufs[i]; unsigned int j; + if (uv__vterm_state == UV_SUPPORTED) { + utf16_buf_used = MultiByteToWideChar(CP_UTF8, + 0, + buf.base, + buf.len, + NULL, + 0); + + if (utf16_buf_used == 0) { + *error = GetLastError(); + break; + } + + if (!MultiByteToWideChar(CP_UTF8, + 0, + buf.base, + buf.len, + utf16_buf, + utf16_buf_used)) { + *error = GetLastError(); + break; + } + + FLUSH_TEXT(); + continue; + } + for (j = 0; j < buf.len; j++) { unsigned char c = buf.base[j]; @@ -2173,3 +2214,24 @@ int uv_tty_reset_mode(void) { /* Not necessary to do anything. */ return 0; } + +/* Determine whether or not this version of windows supports + * proper ANSI color codes. Should be supported as of windows + * 10 version 1511, build number 10.0.10586. + */ +static void uv__determine_vterm_state(HANDLE handle) { + DWORD dwMode = 0; + + if (!GetConsoleMode(handle, &dwMode)) { + uv__vterm_state = UV_UNSUPPORTED; + return; + } + + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (!SetConsoleMode(handle, dwMode)) { + uv__vterm_state = UV_UNSUPPORTED; + return; + } + + uv__vterm_state = UV_SUPPORTED; +} From ee111770068fecb7e3d151cb59c851cddc9bea72 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Fri, 26 Aug 2016 00:18:48 +0200 Subject: [PATCH 15/35] doc: add santigimeno to maintainers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/1016 Reviewed-By: Saúl Ibarra Corretgé Reviewed-By: Imran Iqbal Reviewed-By: Colin Ihrig Reviewed-By: Ben Noordhuis --- MAINTAINERS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 5974d9d3..f2f3db5a 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -12,6 +12,8 @@ libuv is currently managed by the following individuals: - GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny) * **Imran Iqbal** ([@iWuzHere](https://github.com/iWuzHere)) - GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere) +* **Santiago Gimeno** ([@santigimeno](https://github.com/santigimeno)) + - GPG key: 612F 0EAD 9401 6223 79DF 4402 F28C 3C8D A33C 03BE (pubkey-santigimeno) * **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul)) - GPG key: FDF5 1936 4458 319F A823 3DC9 410E 5553 AE9B C059 (pubkey-saghul) From 0895ccfc8ced0c2442c8aab75ccef1f1a6b3938e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Fri, 26 Aug 2016 14:49:37 +0100 Subject: [PATCH 16/35] win: fix typo in type name Introduced in 58ccfd4c210d3cc1a36dd82474976aac296589f2, reviewed by yours truly :-( PR-URL: https://github.com/libuv/libuv/pull/1018 Reviewed-By: Ben Noordhuis Reviewed-By: Santiago Gimeno --- src/win/tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/tty.c b/src/win/tty.c index 2a58a6f7..0975b33d 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -130,7 +130,7 @@ typedef enum { UV_UNSUPPORTED } uv_vtermstate_t; /* Determine whether or not ANSI support is enabled. */ -static vtermstate_t uv__vterm_state = UV_UNCHECKED; +static uv_vtermstate_t uv__vterm_state = UV_UNCHECKED; static void uv__determine_vterm_state(HANDLE handle); void uv_console_init() { From 5d962778349e357e3b14ea92eb7d1844f301da93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Sat, 27 Aug 2016 10:25:52 +0200 Subject: [PATCH 17/35] unix: always define pthread barrier fallback pad Fixes: https://github.com/libuv/libuv/issues/1019 PR-URL: https://github.com/libuv/libuv/pull/1020 Reviewed-By: Ben Noordhuis --- include/pthread-barrier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pthread-barrier.h b/include/pthread-barrier.h index 68468ad2..3e01705d 100644 --- a/include/pthread-barrier.h +++ b/include/pthread-barrier.h @@ -39,7 +39,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2 * sizeof(sem_t) + \ 2 * sizeof(unsigned int) - \ sizeof(void *) -#elif defined(__MVS__) +#else # define UV_BARRIER_STRUCT_PADDING 0 #endif From 897738b160cd5950503a96c9fd5b1e9aab92b0ff Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Mon, 29 Aug 2016 11:29:28 +0200 Subject: [PATCH 18/35] test: use RETURN_SKIP in spawn_setuid_setgid test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/1021 Reviewed-By: Saúl Ibarra Corretgé Reviewed-By: Imran Iqbal Reviewed-By: Colin Ihrig --- test/test-spawn.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/test-spawn.c b/test/test-spawn.c index 0e84ad6d..5df12420 100644 --- a/test/test-spawn.c +++ b/test/test-spawn.c @@ -1230,8 +1230,7 @@ TEST_IMPL(spawn_setuid_setgid) { /* if not root, then this will fail. */ uv_uid_t uid = getuid(); if (uid != 0) { - fprintf(stderr, "spawn_setuid_setgid skipped: not root\n"); - return 0; + RETURN_SKIP("It should be run as root user"); } init_process_options("spawn_helper1", exit_cb); From a7dfee3b02c70ca872c750fc60860d238623be69 Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Tue, 30 Aug 2016 15:53:41 -0400 Subject: [PATCH 19/35] win: add disk read/write count to uv_getrusage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs: https://github.com/libuv/libuv/issues/342 PR-URL: https://github.com/libuv/libuv/pull/1023 Reviewed-By: Saúl Ibarra Corretgé --- src/win/util.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/win/util.c b/src/win/util.c index 4a2e5012..050058af 100644 --- a/src/win/util.c +++ b/src/win/util.c @@ -1078,6 +1078,7 @@ int uv_getrusage(uv_rusage_t *uv_rusage) { FILETIME createTime, exitTime, kernelTime, userTime; SYSTEMTIME kernelSystemTime, userSystemTime; PROCESS_MEMORY_COUNTERS memCounters; + IO_COUNTERS ioCounters; int ret; ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime); @@ -1102,6 +1103,11 @@ int uv_getrusage(uv_rusage_t *uv_rusage) { return uv_translate_sys_error(GetLastError()); } + ret = GetProcessIoCounters(GetCurrentProcess(), &ioCounters); + if (ret == 0) { + return uv_translate_sys_error(GetLastError()); + } + memset(uv_rusage, 0, sizeof(*uv_rusage)); uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 + @@ -1117,6 +1123,9 @@ int uv_getrusage(uv_rusage_t *uv_rusage) { uv_rusage->ru_majflt = (uint64_t) memCounters.PageFaultCount; uv_rusage->ru_maxrss = (uint64_t) memCounters.PeakWorkingSetSize / 1024; + uv_rusage->ru_oublock = (uint64_t) ioCounters.WriteOperationCount; + uv_rusage->ru_inblock = (uint64_t) ioCounters.ReadOperationCount; + return 0; } From 6938f6b0bdbcfd40d7e0cdd3ff298cf46b3dca0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Thu, 1 Sep 2016 10:18:47 +0200 Subject: [PATCH 20/35] doc: document uv_fs_realpath caveats Fixes: https://github.com/libuv/libuv/issues/1017 PR-URL: https://github.com/libuv/libuv/pull/1026 Reviewed-By: Colin Ihrig Reviewed-By: Imran Iqbal --- docs/src/fs.rst | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/src/fs.rst b/docs/src/fs.rst index 50c0de46..8e4a98f2 100644 --- a/docs/src/fs.rst +++ b/docs/src/fs.rst @@ -288,7 +288,26 @@ API .. c:function:: int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) - Equivalent to :man:`realpath(3)` on Unix. Windows uses ``GetFinalPathNameByHandle()``. + Equivalent to :man:`realpath(3)` on Unix. Windows uses `GetFinalPathNameByHandle `_. + + .. warning:: + This function has certain platform specific caveats that were discovered when used in Node. + + * macOS and other BSDs: this function will fail with UV_ELOOP if more than 32 symlinks are + found while resolving the given path. This limit is hardcoded and cannot be sidestepped. + * Windows: while this function works in the common case, there are a number of corner cases + where it doesn't: + + - Paths in ramdisk volumes created by tools which sidestep the Volume Manager (such as ImDisk) + cannot be resolved. + - Inconsistent casing when using drive letters. + - Resolved path bypasses subst'd drives. + + While this function can still be used, it's not recommended if scenarios such as the + above need to be supported. + + The background story and some more details on these issues can be checked + `here `_. .. note:: This function is not implemented on Windows XP and Windows Server 2003. From 4a71e7747a4a2acc888a914033e648e5d8521024 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Tue, 30 Aug 2016 23:41:47 +0200 Subject: [PATCH 21/35] test: improve spawn_setuid_setgid test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check that the child process' uid and gid are correctly set. PR-URL: https://github.com/libuv/libuv/pull/1024 Reviewed-By: Saúl Ibarra Corretgé Reviewed-By: Colin Ihrig --- test/run-tests.c | 13 +++++++++++++ test/test-spawn.c | 12 ++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/test/run-tests.c b/test/run-tests.c index b4be01f6..1e344f05 100644 --- a/test/run-tests.c +++ b/test/run-tests.c @@ -56,6 +56,7 @@ int main(int argc, char **argv) { case 1: return run_tests(0); case 2: return maybe_run_test(argc, argv); case 3: return run_test_part(argv[1], argv[2]); + case 4: return maybe_run_test(argc, argv); default: fprintf(stderr, "Too many arguments.\n"); fflush(stderr); @@ -177,5 +178,17 @@ static int maybe_run_test(int argc, char **argv) { return spawn_stdin_stdout(); } +#ifndef _WIN32 + if (strcmp(argv[1], "spawn_helper_setuid_setgid") == 0) { + uv_uid_t uid = atoi(argv[2]); + uv_gid_t gid = atoi(argv[3]); + + ASSERT(uid == getuid()); + ASSERT(gid == getgid()); + + return 1; + } +#endif /* !_WIN32 */ + return run_test(argv[1], 0, 1); } diff --git a/test/test-spawn.c b/test/test-spawn.c index 5df12420..53a03696 100644 --- a/test/test-spawn.c +++ b/test/test-spawn.c @@ -46,7 +46,7 @@ static uv_timer_t timer; static uv_process_options_t options; static char exepath[1024]; static size_t exepath_size = 1024; -static char* args[3]; +static char* args[5]; static int no_term_signal; static int timer_counter; @@ -147,6 +147,8 @@ static void init_process_options(char* test, uv_exit_cb exit_cb) { args[0] = exepath; args[1] = test; args[2] = NULL; + args[3] = NULL; + args[4] = NULL; options.file = exepath; options.args = args; options.exit_cb = exit_cb; @@ -1226,6 +1228,8 @@ TEST_IMPL(spawn_with_an_odd_path) { TEST_IMPL(spawn_setuid_setgid) { int r; struct passwd* pw; + char uidstr[10]; + char gidstr[10]; /* if not root, then this will fail. */ uv_uid_t uid = getuid(); @@ -1233,13 +1237,17 @@ TEST_IMPL(spawn_setuid_setgid) { RETURN_SKIP("It should be run as root user"); } - init_process_options("spawn_helper1", exit_cb); + init_process_options("spawn_helper_setuid_setgid", exit_cb); /* become the "nobody" user. */ pw = getpwnam("nobody"); ASSERT(pw != NULL); options.uid = pw->pw_uid; options.gid = pw->pw_gid; + snprintf(uidstr, sizeof(uidstr), "%d", pw->pw_uid); + snprintf(gidstr, sizeof(gidstr), "%d", pw->pw_gid); + options.args[2] = uidstr; + options.args[3] = gidstr; options.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID; r = uv_spawn(uv_default_loop(), &process, &options); From 2112e7a67c390f9b183bf69fa9d49345cc4a32af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Sun, 4 Sep 2016 20:46:59 +0200 Subject: [PATCH 22/35] test: fix building pty test on Android Fixes: https://github.com/libuv/libuv/issues/1029 PR-URL: https://github.com/libuv/libuv/pull/1030 Reviewed-By: Ben Noordhuis --- test/test-tty.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test/test-tty.c b/test/test-tty.c index 780968c4..d03f07a4 100644 --- a/test/test-tty.c +++ b/test/test-tty.c @@ -260,13 +260,12 @@ TEST_IMPL(tty_file) { } TEST_IMPL(tty_pty) { -#if defined(__ANDROID__) || \ - defined(__APPLE__) || \ - defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || \ - defined(__linux__) || \ - defined(__NetBSD__) || \ +#if defined(__APPLE__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || \ + (defined(__linux__) && !defined(__ANDROID__)) || \ + defined(__NetBSD__) || \ defined(__OpenBSD__) int master_fd, slave_fd, r; struct winsize w; From f046ebb4092f371f46b6f4edc4e9b109081136a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Wed, 7 Sep 2016 09:39:02 +0200 Subject: [PATCH 23/35] doc: uv_buf_t members are not readonly This is probably a reminiscent of the usage in libuv 0.x, where alloc_cb used to return a uv_buf_t. Refs: https://github.com/libuv/libuv/issues/1027#issuecomment-244386298 PR-URL: https://github.com/libuv/libuv/pull/1033 Reviewed-By: Ben Noordhuis Reviewed-By: Fedor Indutny Reviewed-By: Imran Iqbal Reviewed-By: Santiago Gimeno --- docs/src/misc.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/misc.rst b/docs/src/misc.rst index 3b7f31aa..d377cc8e 100644 --- a/docs/src/misc.rst +++ b/docs/src/misc.rst @@ -17,11 +17,11 @@ Data types .. c:member:: char* uv_buf_t.base - Pointer to the base of the buffer. Readonly. + Pointer to the base of the buffer. .. c:member:: size_t uv_buf_t.len - Total bytes in the buffer. Readonly. + Total bytes in the buffer. .. note:: On Windows this field is ULONG. From bf0301c33ca7494eb0ac231dfee74e5690cbed3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Wed, 7 Sep 2016 09:48:36 +0200 Subject: [PATCH 24/35] doc: improve documentation on uv_alloc_cb Refs: https://github.com/libuv/libuv/issues/1027#issuecomment-244386298 PR-URL: https://github.com/libuv/libuv/pull/1033 Reviewed-By: Ben Noordhuis Reviewed-By: Fedor Indutny Reviewed-By: Imran Iqbal Reviewed-By: Santiago Gimeno --- docs/src/handle.rst | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/docs/src/handle.rst b/docs/src/handle.rst index 6ba597a2..b0a123cf 100644 --- a/docs/src/handle.rst +++ b/docs/src/handle.rst @@ -24,12 +24,28 @@ Data types .. c:type:: void (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) Type definition for callback passed to :c:func:`uv_read_start` and - :c:func:`uv_udp_recv_start`. The user must fill the supplied :c:type:`uv_buf_t` - structure with whatever size, as long as it's > 0. A suggested size (65536 at the moment) - is provided, but it doesn't need to be honored. Setting the buffer's length to 0 - will trigger a ``UV_ENOBUFS`` error in the :c:type:`uv_udp_recv_cb` or + :c:func:`uv_udp_recv_start`. The user must allocate memory and fill the supplied + :c:type:`uv_buf_t` structure. If NULL is assigned as the buffer's base or 0 as its length, + a ``UV_ENOBUFS`` error will be triggered in the :c:type:`uv_udp_recv_cb` or the :c:type:`uv_read_cb` callback. + A suggested size (65536 at the moment in most cases) is provided, but it's just an indication, + not related in any way to the pending data to be read. The user is free to allocate the amount + of memory they decide. + + As an example, applications with custom allocation schemes such as using freelists, allocation + pools or slab based allocators may decide to use a different size which matches the memory + chunks they already have. + + Example: + + :: + + static void my_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { + buf->base = malloc(suggested_size); + buf->len = suggested_size; + } + .. c:type:: void (*uv_close_cb)(uv_handle_t* handle) Type definition for callback passed to :c:func:`uv_close`. From 0d7f72f219d379a6f42ec96ffd8a90493a0d4210 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Thu, 8 Sep 2016 20:16:38 +0200 Subject: [PATCH 25/35] fs: fix uv_fs_fstat on platforms using musl libc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In `musl` libc, defining `_GNU_SOURCE` doesn't automatically define the other feature definitions, causing that `uv_fs_fstat` would not fill the `nsec` fields. For the same reason, compile the tests on linux with `-D_GNU_SOURCE` so the `fs_fstat` tests passes on `musl` platforms. PR-URL: https://github.com/libuv/libuv/pull/1039 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé --- Makefile.am | 4 ++++ src/unix/fs.c | 1 + test/test-fs.c | 1 + 3 files changed, 6 insertions(+) diff --git a/Makefile.am b/Makefile.am index adda2218..86500f76 100644 --- a/Makefile.am +++ b/Makefile.am @@ -284,6 +284,10 @@ if AIX test_run_tests_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT endif +if LINUX +test_run_tests_CFLAGS += -D_GNU_SOURCE +endif + if SUNOS test_run_tests_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 endif diff --git a/src/unix/fs.c b/src/unix/fs.c index 216ef970..39495e31 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -790,6 +790,7 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) { dst->st_flags = 0; dst->st_gen = 0; #elif !defined(_AIX) && ( \ + defined(_GNU_SOURCE) || \ defined(_BSD_SOURCE) || \ defined(_SVID_SOURCE) || \ defined(_XOPEN_SOURCE) || \ diff --git a/test/test-fs.c b/test/test-fs.c index 7c3c6f20..4249ee72 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -1135,6 +1135,7 @@ TEST_IMPL(fs_fstat) { ASSERT(s->st_ctim.tv_sec == t.st_ctime); ASSERT(s->st_ctim.tv_nsec == 0); #elif defined(__sun) || \ + defined(_GNU_SOURCE) || \ defined(_BSD_SOURCE) || \ defined(_SVID_SOURCE) || \ defined(_XOPEN_SOURCE) || \ From 30d852f9e0070c7334a8a5eae7a7b1bc38ad9050 Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Thu, 8 Sep 2016 23:22:32 -0400 Subject: [PATCH 26/35] doc: update supported fields for uv_rusage_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/libuv/libuv/issues/342 PR-URL: https://github.com/libuv/libuv/pull/1041 Reviewed-By: Saúl Ibarra Corretgé Reviewed-By: Colin Ihrig --- docs/src/misc.rst | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/src/misc.rst b/docs/src/misc.rst index d377cc8e..95237f49 100644 --- a/docs/src/misc.rst +++ b/docs/src/misc.rst @@ -69,21 +69,24 @@ Data types uv_timeval_t ru_utime; /* user CPU time used */ uv_timeval_t ru_stime; /* system CPU time used */ uint64_t ru_maxrss; /* maximum resident set size */ - uint64_t ru_ixrss; /* integral shared memory size */ - uint64_t ru_idrss; /* integral unshared data size */ - uint64_t ru_isrss; /* integral unshared stack size */ - uint64_t ru_minflt; /* page reclaims (soft page faults) */ + uint64_t ru_ixrss; /* integral shared memory size (X) */ + uint64_t ru_idrss; /* integral unshared data size (X) */ + uint64_t ru_isrss; /* integral unshared stack size (X) */ + uint64_t ru_minflt; /* page reclaims (soft page faults) (X) */ uint64_t ru_majflt; /* page faults (hard page faults) */ - uint64_t ru_nswap; /* swaps */ + uint64_t ru_nswap; /* swaps (X) */ uint64_t ru_inblock; /* block input operations */ uint64_t ru_oublock; /* block output operations */ - uint64_t ru_msgsnd; /* IPC messages sent */ - uint64_t ru_msgrcv; /* IPC messages received */ - uint64_t ru_nsignals; /* signals received */ - uint64_t ru_nvcsw; /* voluntary context switches */ - uint64_t ru_nivcsw; /* involuntary context switches */ + uint64_t ru_msgsnd; /* IPC messages sent (X) */ + uint64_t ru_msgrcv; /* IPC messages received (X) */ + uint64_t ru_nsignals; /* signals received (X) */ + uint64_t ru_nvcsw; /* voluntary context switches (X) */ + uint64_t ru_nivcsw; /* involuntary context switches (X) */ } uv_rusage_t; + Members marked with `(X)` are unsupported on Windows. + See :man:`getrusage(2)` for supported fields on Unix + .. c:type:: uv_cpu_info_t Data type for CPU information. @@ -205,6 +208,7 @@ API .. note:: On Windows not all fields are set, the unsupported fields are filled with zeroes. + See :c:type:`uv_rusage_t` for more details. .. c:function:: int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) From 6d7d57a983c6054bca2730586f96d809bc64d867 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Sat, 3 Sep 2016 14:26:31 +0200 Subject: [PATCH 27/35] test: fix test-tcp-writealot flakiness on arm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decrease the data sent for `arm` so the test doesn't timeout in the arm CI bots. PR-URL: https://github.com/libuv/libuv/pull/1038 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé Reviewed-By: Colin Ihrig --- test/test-tcp-writealot.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/test-tcp-writealot.c b/test/test-tcp-writealot.c index 6cfe2ebb..7206fdc2 100644 --- a/test/test-tcp-writealot.c +++ b/test/test-tcp-writealot.c @@ -26,7 +26,11 @@ #define WRITES 3 +#if defined(__arm__) /* Decrease the chunks so the test passes on arm CI bots */ +#define CHUNKS_PER_WRITE 2048 +#else #define CHUNKS_PER_WRITE 4096 +#endif #define CHUNK_SIZE 10024 /* 10 kb */ #define TOTAL_BYTES (WRITES * CHUNKS_PER_WRITE * CHUNK_SIZE) From 29138058a5a51c6e9e187d1109494d29a948d529 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Sun, 4 Sep 2016 23:09:23 +0200 Subject: [PATCH 28/35] test: fix fs_event_watch_dir flakiness on arm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Increase the time between file creations, so all the events are emitted. PR-URL: https://github.com/libuv/libuv/pull/1038 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé Reviewed-By: Colin Ihrig --- test/test-fs-event.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/test-fs-event.c b/test/test-fs-event.c index 5b7774b6..aa4fcf19 100644 --- a/test/test-fs-event.c +++ b/test/test-fs-event.c @@ -36,6 +36,12 @@ # endif #endif +#if defined(__arm__)/* Increase the timeout so the test passes on arm CI bots */ +# define CREATE_TIMEOUT 100 +#else +# define CREATE_TIMEOUT 1 +#endif + static uv_fs_event_t fs_event; static const char file_prefix[] = "fsevent-"; static const int fs_event_file_count = 16; @@ -152,7 +158,10 @@ static void fs_event_create_files(uv_timer_t* handle) { if (++fs_event_created < fs_event_file_count) { /* Create another file on a different event loop tick. We do it this way * to avoid fs events coalescing into one fs event. */ - ASSERT(0 == uv_timer_start(&timer, fs_event_create_files, 1, 0)); + ASSERT(0 == uv_timer_start(&timer, + fs_event_create_files, + CREATE_TIMEOUT, + 0)); } } From e7bc260c4260658517cab4de077e2195c0c7c235 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Mon, 12 Sep 2016 13:01:17 +0200 Subject: [PATCH 29/35] unix: don't use alphasort in uv_fs_scandir() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit alphasort() uses strcoll() in some libcs (notably glibc and musl) which makes it locale-sensitive. Replace it with a simple strcmp-based lexicographic comparison for consistent behavior across platforms. Remove the special-casing for OpenBSD. It has been exporting function prototypes conforming to POSIX.1-2008 since OpenBSD 5.3 and that was released more than three years ago. OS X 10.7 is now the only special case left. Fixes: https://github.com/libuv/libuv/issues/1045 PR-URL: https://github.com/libuv/libuv/pull/1046 Reviewed-By: Santiago Gimeno Reviewed-By: Saúl Ibarra Corretgé --- src/unix/fs.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/unix/fs.c b/src/unix/fs.c index 39495e31..3d478b79 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -346,22 +346,30 @@ done: } -#if defined(__OpenBSD__) || (defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)) -static int uv__fs_scandir_filter(uv__dirent_t* dent) { +#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8) +#define UV_CONST_DIRENT uv__dirent_t #else -static int uv__fs_scandir_filter(const uv__dirent_t* dent) { +#define UV_CONST_DIRENT const uv__dirent_t #endif + + +static int uv__fs_scandir_filter(UV_CONST_DIRENT* dent) { return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0; } +static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) { + return strcmp((*a)->d_name, (*b)->d_name); +} + + static ssize_t uv__fs_scandir(uv_fs_t* req) { uv__dirent_t **dents; int saved_errno; int n; dents = NULL; - n = scandir(req->path, &dents, uv__fs_scandir_filter, alphasort); + n = scandir(req->path, &dents, uv__fs_scandir_filter, uv__fs_scandir_sort); /* NOTE: We will use nbufs as an index field */ req->nbufs = 0; From d38edefc73b2f14d592b6585462a0732deb3ee1e Mon Sep 17 00:00:00 2001 From: Bart Robinson Date: Wed, 14 Sep 2016 11:10:36 -0700 Subject: [PATCH 30/35] doc: fix confusing doc of uv_tcp_nodelay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous description implied enabling nodelay enabled Nagle, but it is the other way around. PR-URL: https://github.com/libuv/libuv/pull/1050 Reviewed-By: Saúl Ibarra Corretgé --- docs/src/tcp.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/tcp.rst b/docs/src/tcp.rst index ca0c9b4a..a1a58245 100644 --- a/docs/src/tcp.rst +++ b/docs/src/tcp.rst @@ -53,7 +53,7 @@ API .. c:function:: int uv_tcp_nodelay(uv_tcp_t* handle, int enable) - Enable / disable Nagle's algorithm. + Enable `TCP_NODELAY`, which disables Nagle's algorithm. .. c:function:: int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) From 1a96fe33343f82721ba8bc93adb5a67ddcf70ec4 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Tue, 13 Sep 2016 20:44:27 +0200 Subject: [PATCH 31/35] build,osx: fix warnings on tests compilation with gyp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add `-Wno-long-long` to `WARNING_CFLAGS`. PR-URL: https://github.com/libuv/libuv/pull/1049 Reviewed-By: Saúl Ibarra Corretgé --- uv.gyp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/uv.gyp b/uv.gyp index 4d1a0346..b969a8cd 100644 --- a/uv.gyp +++ b/uv.gyp @@ -470,6 +470,9 @@ [ 'OS != "zos"', { 'defines': [ '_GNU_SOURCE' ], 'cflags': [ '-Wno-long-long' ], + 'xcode_settings': { + 'WARNING_CFLAGS': [ '-Wno-long-long' ] + } }], ]}, ], From 79e80e0f125b44b1a12b409259d5f01e94dafb89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Thu, 15 Sep 2016 10:32:48 +0200 Subject: [PATCH 32/35] doc: add ABI tracker link to README PR-URL: https://github.com/libuv/libuv/pull/1053 Reviewed-By: Colin Ihrig Reviewed-By: Fedor Indutny --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 29b94db1..284dfb47 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,8 @@ Starting with version 1.0.0 libuv follows the [semantic versioning](http://semve scheme. The API change and backwards compatibility rules are those indicated by SemVer. libuv will keep a stable ABI across major releases. +The ABI/API changes can be tracked [here](http://abi-laboratory.pro/tracker/timeline/libuv/). + ## Licensing libuv is licensed under the MIT license. Check the [LICENSE file](LICENSE). From 84144036ce5f76f39bb042fa4fb45c24aa9473f4 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Thu, 15 Sep 2016 16:16:11 +0200 Subject: [PATCH 33/35] win,tty: fix uv_tty_set_mode race conditions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Additional synchronization is needed to ensure that the program cannot modify the screen state while a line read is getting cancelled. Also, we need to stop any pending reads *before* calling SetConsoleMode, or a call to ReadConsole could start while the console is still in raw mode. Credit: @orangemocha - Alexis Campailla Fixes: https://github.com/nodejs/node/issues/7837 PR-URL: https://github.com/libuv/libuv/pull/1054 Reviewed-By: Saúl Ibarra Corretgé --- src/win/tty.c | 90 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 35 deletions(-) diff --git a/src/win/tty.c b/src/win/tty.c index 0975b33d..18d68d09 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -111,7 +111,11 @@ static int uv_tty_virtual_offset = -1; static int uv_tty_virtual_height = -1; static int uv_tty_virtual_width = -1; -static CRITICAL_SECTION uv_tty_output_lock; +/* We use a semaphore rather than a mutex or critical section because in some + cases (uv__cancel_read_console) we need take the lock in the main thread and + release it in another thread. Using a semaphore ensures that in such + scenario the main thread will still block when trying to acquire the lock. */ +static uv_sem_t uv_tty_output_lock; static HANDLE uv_tty_output_handle = INVALID_HANDLE_VALUE; @@ -134,7 +138,8 @@ static uv_vtermstate_t uv__vterm_state = UV_UNCHECKED; static void uv__determine_vterm_state(HANDLE handle); void uv_console_init() { - InitializeCriticalSection(&uv_tty_output_lock); + if (uv_sem_init(&uv_tty_output_lock, 1)) + abort(); } @@ -172,7 +177,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { /* Obtain the the tty_output_lock because the virtual window state is */ /* shared between all uv_tty_t handles. */ - EnterCriticalSection(&uv_tty_output_lock); + uv_sem_wait(&uv_tty_output_lock); if (uv__vterm_state == UV_UNCHECKED) uv__determine_vterm_state(handle); @@ -187,7 +192,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { uv_tty_update_virtual_window(&screen_buffer_info); - LeaveCriticalSection(&uv_tty_output_lock); + uv_sem_post(&uv_tty_output_lock); } @@ -315,10 +320,6 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { return UV_EINVAL; } - if (!SetConsoleMode(tty->handle, flags)) { - return uv_translate_sys_error(GetLastError()); - } - /* If currently reading, stop, and restart reading. */ if (tty->flags & UV_HANDLE_READING) { was_reading = 1; @@ -332,6 +333,14 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { was_reading = 0; } + uv_sem_wait(&uv_tty_output_lock); + if (!SetConsoleMode(tty->handle, flags)) { + err = uv_translate_sys_error(GetLastError()); + uv_sem_post(&uv_tty_output_lock); + return err; + } + uv_sem_post(&uv_tty_output_lock); + /* Update flag. */ tty->flags &= ~UV_HANDLE_TTY_RAW; tty->flags |= mode ? UV_HANDLE_TTY_RAW : 0; @@ -361,9 +370,9 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) { return uv_translate_sys_error(GetLastError()); } - EnterCriticalSection(&uv_tty_output_lock); + uv_sem_wait(&uv_tty_output_lock); uv_tty_update_virtual_window(&info); - LeaveCriticalSection(&uv_tty_output_lock); + uv_sem_post(&uv_tty_output_lock); *width = uv_tty_virtual_width; *height = uv_tty_virtual_height; @@ -432,6 +441,7 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) { DWORD chars, read_chars; LONG status; COORD pos; + BOOL read_console_success; assert(data); @@ -461,11 +471,13 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) { return 0; } - if (ReadConsoleW(handle->handle, - (void*) utf16, - chars, - &read_chars, - NULL)) { + read_console_success = ReadConsoleW(handle->handle, + (void*) utf16, + chars, + &read_chars, + NULL); + + if (read_console_success) { read_bytes = WideCharToMultiByte(CP_UTF8, 0, utf16, @@ -480,33 +492,36 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) { SET_REQ_ERROR(req, GetLastError()); } - InterlockedExchange(&uv__read_console_status, COMPLETED); + status = InterlockedExchange(&uv__read_console_status, COMPLETED); - /* If we canceled the read by sending a VK_RETURN event, restore the screen - state to undo the visual effect of the VK_RETURN*/ - if (InterlockedOr(&uv__restore_screen_state, 0)) { - HANDLE active_screen_buffer = CreateFileA("conout$", + if (status == TRAP_REQUESTED) { + /* If we canceled the read by sending a VK_RETURN event, restore the + screen state to undo the visual effect of the VK_RETURN */ + if (read_console_success && InterlockedOr(&uv__restore_screen_state, 0)) { + HANDLE active_screen_buffer; + active_screen_buffer = CreateFileA("conout$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (active_screen_buffer != INVALID_HANDLE_VALUE) { - pos = uv__saved_screen_state.dwCursorPosition; + if (active_screen_buffer != INVALID_HANDLE_VALUE) { + pos = uv__saved_screen_state.dwCursorPosition; - /* If the cursor was at the bottom line of the screen buffer, the - VK_RETURN would have caused the buffer contents to scroll up by - one line. The right position to reset the cursor to is therefore one - line higher */ - if (pos.Y == uv__saved_screen_state.dwSize.Y - 1) - pos.Y--; + /* If the cursor was at the bottom line of the screen buffer, the + VK_RETURN would have caused the buffer contents to scroll up by one + line. The right position to reset the cursor to is therefore one line + higher */ + if (pos.Y == uv__saved_screen_state.dwSize.Y - 1) + pos.Y--; - SetConsoleCursorPosition(active_screen_buffer, pos); - CloseHandle(active_screen_buffer); + SetConsoleCursorPosition(active_screen_buffer, pos); + CloseHandle(active_screen_buffer); + } } + uv_sem_post(&uv_tty_output_lock); } - POST_COMPLETION_FOR_REQ(loop, req); return 0; } @@ -694,14 +709,14 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, if (handle->tty.rd.last_input_record.EventType == WINDOW_BUFFER_SIZE_EVENT) { CONSOLE_SCREEN_BUFFER_INFO info; - EnterCriticalSection(&uv_tty_output_lock); + uv_sem_wait(&uv_tty_output_lock); if (uv_tty_output_handle != INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo(uv_tty_output_handle, &info)) { uv_tty_update_virtual_window(&info); } - LeaveCriticalSection(&uv_tty_output_lock); + uv_sem_post(&uv_tty_output_lock); continue; } @@ -1035,11 +1050,16 @@ static int uv__cancel_read_console(uv_tty_t* handle) { assert(!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)); + /* Hold the output lock during the cancellation, to ensure that further + writes don't interfere with the screen state. It will be the ReadConsole + thread's responsibility to release the lock. */ + uv_sem_wait(&uv_tty_output_lock); status = InterlockedExchange(&uv__read_console_status, TRAP_REQUESTED); if (status != IN_PROGRESS) { /* Either we have managed to set a trap for the other thread before ReadConsole is called, or ReadConsole has returned because the user has pressed ENTER. In either case, there is nothing else to do. */ + uv_sem_post(&uv_tty_output_lock); return 0; } @@ -1624,7 +1644,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, /* state. */ *error = ERROR_SUCCESS; - EnterCriticalSection(&uv_tty_output_lock); + uv_sem_wait(&uv_tty_output_lock); for (i = 0; i < nbufs; i++) { uv_buf_t buf = bufs[i]; @@ -2061,7 +2081,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, handle->tty.wr.previous_eol = previous_eol; handle->tty.wr.ansi_parser_state = ansi_parser_state; - LeaveCriticalSection(&uv_tty_output_lock); + uv_sem_post(&uv_tty_output_lock); if (*error == STATUS_SUCCESS) { return 0; From fa81a1b2d760528db46ec655b53f75ec3ef83dc4 Mon Sep 17 00:00:00 2001 From: Vit Gottwald Date: Sat, 17 Sep 2016 11:07:27 +0200 Subject: [PATCH 34/35] test: fix fs_fstat on Android MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/libuv/libuv/issues/1051 PR-URL: https://github.com/libuv/libuv/pull/1056 Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- test/test-fs.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/test-fs.c b/test/test-fs.c index 4249ee72..74abaf34 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -1134,6 +1134,13 @@ TEST_IMPL(fs_fstat) { ASSERT(s->st_mtim.tv_nsec == 0); ASSERT(s->st_ctim.tv_sec == t.st_ctime); ASSERT(s->st_ctim.tv_nsec == 0); +#elif defined(__ANDROID__) + ASSERT(s->st_atim.tv_sec == t.st_atime); + ASSERT(s->st_atim.tv_nsec == t.st_atimensec); + ASSERT(s->st_mtim.tv_sec == t.st_mtime); + ASSERT(s->st_mtim.tv_nsec == t.st_mtimensec); + ASSERT(s->st_ctim.tv_sec == t.st_ctime); + ASSERT(s->st_ctim.tv_nsec == t.st_ctimensec); #elif defined(__sun) || \ defined(_GNU_SOURCE) || \ defined(_BSD_SOURCE) || \ From 468d44620a13447e3521ca7a6ad544100e6a0c5e Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Wed, 31 Aug 2016 16:03:49 +0200 Subject: [PATCH 35/35] win, test: fix fs_event_watch_dir_recursive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Under Windows uv_fs_event_start with UV_FS_EVENT_RECURSIVE will report new file creation and file deletion twice - once with the name of the file, and second time with the name of the directory itself. This will filter out callbacks with directory name, making observed callbacks count match expected values. Fixes: https://github.com/libuv/libuv/issues/1009 PR-URL: https://github.com/libuv/libuv/pull/1061 Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- test/test-fs-event.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test-fs-event.c b/test/test-fs-event.c index aa4fcf19..df8dc4c2 100644 --- a/test/test-fs-event.c +++ b/test/test-fs-event.c @@ -272,6 +272,14 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle, const char* filename, int events, int status) { +#ifdef _WIN32 + /* Each file created (or deleted) will cause this callback to be called twice + * under Windows: once with the name of the file, and second time with the + * name of the directory. We will ignore the callback for the directory + * itself. */ + if (filename && strcmp(filename, file_prefix_in_subdir) == 0) + return; +#endif fs_event_cb_called++; ASSERT(handle == &fs_event); ASSERT(status == 0);