From b614b59c3f755b9bba0f9ea718997cc21040a48d Mon Sep 17 00:00:00 2001 From: cjihrig Date: Tue, 31 Jan 2017 20:06:00 -0500 Subject: [PATCH] deps: upgrade libuv to 1.11.0 Fixes: https://github.com/nodejs/node/issues/10165 Fixes: https://github.com/nodejs/node/issues/9856 Fixes: https://github.com/nodejs/node/issues/10607 Fixes: https://github.com/nodejs/node/issues/11104 PR-URL: https://github.com/nodejs/node/pull/11094 Reviewed-By: James M Snell Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Santiago Gimeno Reviewed-By: Michael Dawson --- deps/uv/.mailmap | 1 + deps/uv/AUTHORS | 5 + deps/uv/ChangeLog | 39 ++ deps/uv/Makefile.am | 12 +- deps/uv/appveyor.yml | 2 +- deps/uv/common.gypi | 4 +- deps/uv/configure.ac | 2 +- deps/uv/docs/src/conf.py | 6 +- deps/uv/docs/src/misc.rst | 6 +- deps/uv/include/pthread-barrier.h | 2 + deps/uv/include/uv-os390.h | 3 + deps/uv/include/uv-unix.h | 4 + deps/uv/include/uv-version.h | 4 +- deps/uv/include/uv-win.h | 1 + deps/uv/src/unix/aix.c | 86 ++- deps/uv/src/unix/atomic-ops.h | 27 +- deps/uv/src/unix/core.c | 3 + deps/uv/src/unix/darwin.c | 10 - deps/uv/src/unix/fs.c | 28 +- deps/uv/src/unix/internal.h | 4 + deps/uv/src/unix/os390-syscalls.c | 334 ++++++++++++ deps/uv/src/unix/os390-syscalls.h | 69 +++ deps/uv/src/unix/os390.c | 823 +++++++++++++++++++++++++++++ deps/uv/src/unix/process.c | 4 +- deps/uv/src/unix/proctitle.c | 6 + deps/uv/src/unix/pthread-barrier.c | 3 +- deps/uv/src/unix/stream.c | 28 +- deps/uv/src/unix/sunos.c | 11 +- deps/uv/src/uv-common.c | 12 +- deps/uv/src/win/signal.c | 118 +---- deps/uv/src/win/winapi.h | 4 + deps/uv/test/test-error.c | 3 + deps/uv/test/test-fs.c | 45 ++ deps/uv/test/test-list.h | 4 + deps/uv/test/test-process-title.c | 2 +- deps/uv/test/test-signal.c | 35 +- deps/uv/test/test-tty.c | 3 + deps/uv/uv.gyp | 34 +- 38 files changed, 1589 insertions(+), 198 deletions(-) create mode 100644 deps/uv/src/unix/os390-syscalls.c create mode 100644 deps/uv/src/unix/os390-syscalls.h diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index 4966caf5fab085..8acf8fecd14003 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.mailmap @@ -1,6 +1,7 @@ Aaron Bieber Alan Gutierrez Andrius Bentkus +Bert Belder Bert Belder Bert Belder Brandon Philips diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 49c8e17f23b35c..4719d2368aec9d 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -279,3 +279,8 @@ Philippe Laferriere Will Speak Hitesh Kanwathirtha Eric Sciple +jBarz +muflub +Daniel Bevenius +Howard Hellyer +Chris Araman diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index d865f22667ec39..da4c3b13f14eb2 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,42 @@ +2017.02.02, Version 1.11.0 (Stable), 7452ef4e06a4f99ee26b694c65476401534f2725 + +Changes since version 1.10.2: + +* Now working on version 1.10.3 (cjihrig) + +* win: added fcntl.h to uv-win.h (Michele Caini) + +* unix: move function call out of assert (jBarz) + +* fs: cleanup uv__fs_scandir (Santiago Gimeno) + +* fs: fix crash in uv_fs_scandir_next (muflub) + +* win,signal: fix potential deadlock (Bartosz Sosnowski) + +* unix: use async-signal safe functions between fork and exec (jBarz) + +* sunos: fix SUNOS_NO_IFADDRS build (Ben Noordhuis) + +* zos: make platform functional (John Barboza) + +* doc: add repitition qualifier to version regexs (Daniel Bevenius) + +* zos: use gyp OS label "os390" on z/OS (John Barboza) + +* aix: enable uv_get/set_process_title (Howard Hellyer) + +* zos: use built-in proctitle implementation (John Barboza) + +* Revert "darwin: use clock_gettime in macOS 10.12" (Chris Araman) + +* win,test: don't write uninitialized buffer to tty (Bert Belder) + +* win: define ERROR_ELEVATION_REQUIRED for MinGW (Richard Lau) + +* aix: re-enable fs watch facility (Gireesh Punathil) + + 2017.01.10, Version 1.10.2 (Stable), cb9f579a454b8db592030ffa274ae58df78dbe20 Changes since version 1.10.1: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index c232b6dbdc8cca..036464e71ecc48 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -316,7 +316,11 @@ test_run_tests_CFLAGS += -D_UNIX03_THREADS \ endif if AIX -libuv_la_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT -D_THREAD_SAFE +libuv_la_CFLAGS += -D_ALL_SOURCE \ + -D_XOPEN_SOURCE=500 \ + -D_LINUX_SOURCE_COMPAT \ + -D_THREAD_SAFE \ + -DHAVE_SYS_AHAFS_EVPRODS_H include_HEADERS += include/uv-aix.h libuv_la_SOURCES += src/unix/aix.c endif @@ -402,8 +406,10 @@ libuv_la_CFLAGS += -D_UNIX03_THREADS \ -qFLOAT=IEEE libuv_la_LDFLAGS += -qXPLINK libuv_la_SOURCES += src/unix/pthread-fixes.c \ - src/unix/pthread-barrier.c -libuv_la_SOURCES += src/unix/os390.c + src/unix/pthread-barrier.c \ + src/unix/os390.c \ + src/unix/os390-syscalls.c \ + src/unix/proctitle.c endif if HAVE_PKG_CONFIG diff --git a/deps/uv/appveyor.yml b/deps/uv/appveyor.yml index 63294137833fb7..e8e79f051e89dc 100644 --- a/deps/uv/appveyor.yml +++ b/deps/uv/appveyor.yml @@ -1,4 +1,4 @@ -version: v1.10.2.build{build} +version: v1.11.0.build{build} install: - cinst -y nsis diff --git a/deps/uv/common.gypi b/deps/uv/common.gypi index 44db701d68df61..470b73385d8398 100644 --- a/deps/uv/common.gypi +++ b/deps/uv/common.gypi @@ -35,7 +35,7 @@ 'OTHER_CFLAGS': [ '-Wno-strict-aliasing' ], }, 'conditions': [ - ['OS != "zos"', { + ['OS != "os390"', { 'cflags': [ '-O0', '-fwrapv' ] }], ['OS == "android"', { @@ -154,7 +154,7 @@ 'cflags': [ '-pthreads' ], 'ldflags': [ '-pthreads' ], }], - [ 'OS not in "solaris android zos"', { + [ 'OS not in "solaris android os390"', { 'cflags': [ '-pthread' ], 'ldflags': [ '-pthread' ], }], diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index abaf971772ffe7..360652198e5acb 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.10.2], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.11.0], [https://github.com/libuv/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/as_case.m4]) diff --git a/deps/uv/docs/src/conf.py b/deps/uv/docs/src/conf.py index b9eaa137432dea..3f8689d2e5c699 100644 --- a/deps/uv/docs/src/conf.py +++ b/deps/uv/docs/src/conf.py @@ -21,11 +21,11 @@ def get_libuv_version(): with open('../../include/uv-version.h') as f: data = f.read() try: - m = re.search(r"""^#define UV_VERSION_MAJOR (\d)$""", data, re.MULTILINE) + m = re.search(r"""^#define UV_VERSION_MAJOR (\d+)$""", data, re.MULTILINE) major = int(m.group(1)) - m = re.search(r"""^#define UV_VERSION_MINOR (\d)$""", data, re.MULTILINE) + m = re.search(r"""^#define UV_VERSION_MINOR (\d+)$""", data, re.MULTILINE) minor = int(m.group(1)) - m = re.search(r"""^#define UV_VERSION_PATCH (\d)$""", data, re.MULTILINE) + m = re.search(r"""^#define UV_VERSION_PATCH (\d+)$""", data, re.MULTILINE) patch = int(m.group(1)) m = re.search(r"""^#define UV_VERSION_IS_RELEASE (\d)$""", data, re.MULTILINE) is_release = int(m.group(1)) diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index 95237f49c7ba61..71934694623d9b 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -192,7 +192,11 @@ API .. c:function:: int uv_set_process_title(const char* title) - Sets the current process title. + Sets the current process title. On platforms with a fixed size buffer for the + process title the contents of `title` will be copied to the buffer and + truncated if larger than the available space. Other platforms will return + `UV_ENOMEM` if they cannot allocate enough space to duplicate the contents of + `title`. .. c:function:: int uv_resident_set_memory(size_t* rss) diff --git a/deps/uv/include/pthread-barrier.h b/deps/uv/include/pthread-barrier.h index 3e01705d9c31b8..900ebedd308b26 100644 --- a/deps/uv/include/pthread-barrier.h +++ b/deps/uv/include/pthread-barrier.h @@ -18,7 +18,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define _UV_PTHREAD_BARRIER_ #include #include +#if !defined(__MVS__) #include /* sem_t */ +#endif #define PTHREAD_BARRIER_SERIAL_THREAD 0x12345 diff --git a/deps/uv/include/uv-os390.h b/deps/uv/include/uv-os390.h index b0b068f44e86af..58f926111aa6af 100644 --- a/deps/uv/include/uv-os390.h +++ b/deps/uv/include/uv-os390.h @@ -24,4 +24,7 @@ #define UV_PLATFORM_SEM_T int +#define UV_PLATFORM_LOOP_FIELDS \ + void* ep; \ + #endif /* UV_MVS_H */ diff --git a/deps/uv/include/uv-unix.h b/deps/uv/include/uv-unix.h index bca271447677f4..3030f719a27148 100644 --- a/deps/uv/include/uv-unix.h +++ b/deps/uv/include/uv-unix.h @@ -36,7 +36,9 @@ #include #include +#if !defined(__MVS__) #include +#endif #include #include @@ -44,6 +46,8 @@ #if defined(__linux__) # include "uv-linux.h" +#elif defined (__MVS__) +# include "uv-os390.h" #elif defined(_AIX) # include "uv-aix.h" #elif defined(__sun) diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h index 99f7eb8c1fae1d..cf000487909477 100644 --- a/deps/uv/include/uv-version.h +++ b/deps/uv/include/uv-version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 10 -#define UV_VERSION_PATCH 2 +#define UV_VERSION_MINOR 11 +#define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/include/uv-win.h b/deps/uv/include/uv-win.h index e8b9b15e2fc38c..9677ff164b71e0 100644 --- a/deps/uv/include/uv-win.h +++ b/deps/uv/include/uv-win.h @@ -49,6 +49,7 @@ typedef struct pollfd { #include #include +#include #include #if defined(_MSC_VER) && _MSC_VER < 1600 diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c index 652cd980f513ab..1d2cd4a80e97f6 100644 --- a/deps/uv/src/unix/aix.c +++ b/deps/uv/src/unix/aix.c @@ -64,6 +64,11 @@ #define RDWR_BUF_SIZE 4096 #define EQ(a,b) (strcmp(a,b) == 0) +static void* args_mem = NULL; +static char** process_argv = NULL; +static int process_argc = 0; +static char* process_title_ptr = NULL; + int uv__platform_loop_init(uv_loop_t* loop) { loop->fs_fd = -1; @@ -753,6 +758,13 @@ static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file"); + /* In file / directory move cases, AIX Event infrastructure + * produces a second event with no data. + * Ignore it and return gracefully. + */ + if(bytes == 0) + return; + /* Parse the data */ if(bytes > 0) rc = uv__parse_data(result_data, &events, handle); @@ -881,24 +893,94 @@ void uv__fs_event_close(uv_fs_event_t* handle) { char** uv_setup_args(int argc, char** argv) { - return argv; + char** new_argv; + size_t size; + char* s; + int i; + + if (argc <= 0) + return argv; + + /* Save the original pointer to argv. + * AIX uses argv to read the process name. + * (Not the memory pointed to by argv[0..n] as on Linux.) + */ + process_argv = argv; + process_argc = argc; + + /* Calculate how much memory we need for the argv strings. */ + size = 0; + for (i = 0; i < argc; i++) + size += strlen(argv[i]) + 1; + + /* Add space for the argv pointers. */ + size += (argc + 1) * sizeof(char*); + + new_argv = uv__malloc(size); + if (new_argv == NULL) + return argv; + args_mem = new_argv; + + /* Copy over the strings and set up the pointer table. */ + s = (char*) &new_argv[argc + 1]; + for (i = 0; i < argc; i++) { + size = strlen(argv[i]) + 1; + memcpy(s, argv[i], size); + new_argv[i] = s; + s += size; + } + new_argv[i] = NULL; + + return new_argv; } int uv_set_process_title(const char* title) { + char* new_title; + + /* We cannot free this pointer when libuv shuts down, + * the process may still be using it. + */ + new_title = uv__strdup(title); + if (new_title == NULL) + return -ENOMEM; + + /* If this is the first time this is set, + * don't free and set argv[1] to NULL. + */ + if (process_title_ptr != NULL) + uv__free(process_title_ptr); + + process_title_ptr = new_title; + + process_argv[0] = process_title_ptr; + if (process_argc > 1) + process_argv[1] = NULL; + return 0; } int uv_get_process_title(char* buffer, size_t size) { + size_t len; + len = strlen(process_argv[0]); if (buffer == NULL || size == 0) return -EINVAL; + else if (size <= len) + return -ENOBUFS; + + memcpy(buffer, process_argv[0], len + 1); - buffer[0] = '\0'; return 0; } +UV_DESTRUCTOR(static void free_args_mem(void)) { + uv__free(args_mem); /* Keep valgrind happy. */ + args_mem = NULL; +} + + int uv_resident_set_memory(size_t* rss) { char pp[64]; psinfo_t psinfo; diff --git a/deps/uv/src/unix/atomic-ops.h b/deps/uv/src/unix/atomic-ops.h index 815e355238b121..9dac2557f867e5 100644 --- a/deps/uv/src/unix/atomic-ops.h +++ b/deps/uv/src/unix/atomic-ops.h @@ -43,8 +43,12 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { __compare_and_swap(ptr, &oldval, newval); return out; #elif defined(__MVS__) - return __plo_CS(ptr, (unsigned int*) ptr, - oldval, (unsigned int*) &newval); + unsigned int op4; + if (__plo_CSST(ptr, (unsigned int*) &oldval, newval, + (unsigned int*) ptr, *ptr, &op4)) + return oldval; + else + return op4; #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif @@ -67,13 +71,18 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) { # endif /* if defined(__64BIT__) */ return out; #elif defined (__MVS__) -# ifdef _LP64 - return __plo_CSGR(ptr, (unsigned long long*) ptr, - oldval, (unsigned long long*) &newval); -# else - return __plo_CS(ptr, (unsigned int*) ptr, - oldval, (unsigned int*) &newval); -# endif +#ifdef _LP64 + unsigned long long op4; + if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval, + (unsigned long long*) ptr, *ptr, &op4)) +#else + unsigned long op4; + if (__plo_CSST(ptr, (unsigned int*) &oldval, newval, + (unsigned int*) ptr, *ptr, &op4)) +#endif + return oldval; + else + return op4; #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 6283ed3ec28c0a..1ec549cccb5cfe 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -517,6 +517,9 @@ int uv__close_nocheckstdio(int fd) { int uv__close(int fd) { assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */ +#if defined(__MVS__) + epoll_file_close(fd); +#endif return uv__close_nocheckstdio(fd); } diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c index b1ffbc37b47b78..cf95da21693b9a 100644 --- a/deps/uv/src/unix/darwin.c +++ b/deps/uv/src/unix/darwin.c @@ -34,12 +34,8 @@ #include /* _NSGetExecutablePath */ #include #include -#include #include /* sysconf */ -#undef NANOSEC -#define NANOSEC ((uint64_t) 1e9) - int uv__platform_loop_init(uv_loop_t* loop) { loop->cf_state = NULL; @@ -57,11 +53,6 @@ void uv__platform_loop_delete(uv_loop_t* loop) { uint64_t uv__hrtime(uv_clocktype_t type) { -#ifdef MAC_OS_X_VERSION_10_12 - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec); -#else static mach_timebase_info_data_t info; if ((ACCESS_ONCE(uint32_t, info.numer) == 0 || @@ -70,7 +61,6 @@ uint64_t uv__hrtime(uv_clocktype_t type) { abort(); return mach_absolute_time() * info.numer / info.denom; -#endif } diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index e047b671651466..f9513ea55a03eb 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -380,7 +380,6 @@ static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) { static ssize_t uv__fs_scandir(uv_fs_t* req) { uv__dirent_t **dents; - int saved_errno; int n; dents = NULL; @@ -389,28 +388,17 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) { /* NOTE: We will use nbufs as an index field */ req->nbufs = 0; - if (n == 0) - goto out; /* osx still needs to deallocate some memory */ - else if (n == -1) - return n; - - req->ptr = dents; - - return n; - -out: - saved_errno = errno; - if (dents != NULL) { - int i; - - /* Memory was allocated using the system allocator, so use free() here. */ - for (i = 0; i < n; i++) - free(dents[i]); + if (n == 0) { + /* OS X still needs to deallocate some memory. + * Memory was allocated using the system allocator, so use free() here. + */ free(dents); + dents = NULL; + } else if (n == -1) { + return n; } - errno = saved_errno; - req->ptr = NULL; + req->ptr = dents; return n; } diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index ee76c837c43ed2..1188e8fe70998a 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -38,6 +38,10 @@ # include "linux-syscalls.h" #endif /* __linux__ */ +#if defined(__MVS__) +# include "os390-syscalls.h" +#endif /* __MVS__ */ + #if defined(__sun) # include # include diff --git a/deps/uv/src/unix/os390-syscalls.c b/deps/uv/src/unix/os390-syscalls.c new file mode 100644 index 00000000000000..2bf3b73815a5f4 --- /dev/null +++ b/deps/uv/src/unix/os390-syscalls.c @@ -0,0 +1,334 @@ +/* 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 "os390-syscalls.h" +#include +#include +#include +#include + +#define CW_CONDVAR 32 + +#pragma linkage(BPX4CTW, OS) +#pragma linkage(BPX1CTW, OS) + +static int number_of_epolls; +static QUEUE global_epoll_queue; +static uv_mutex_t global_epoll_lock; +static uv_once_t once = UV_ONCE_INIT; + +int scandir(const char* maindir, struct dirent*** namelist, + int (*filter)(const struct dirent*), + int (*compar)(const struct dirent**, + const struct dirent **)) { + struct dirent** nl; + struct dirent* dirent; + unsigned count; + size_t allocated; + DIR* mdir; + + nl = NULL; + count = 0; + allocated = 0; + mdir = opendir(maindir); + if (!mdir) + return -1; + + while (1) { + dirent = readdir(mdir); + if (!dirent) + break; + if (!filter || filter(dirent)) { + struct dirent* copy; + copy = uv__malloc(sizeof(*copy)); + if (!copy) { + while (count) { + dirent = nl[--count]; + uv__free(dirent); + } + uv__free(nl); + closedir(mdir); + errno = ENOMEM; + return -1; + } + memcpy(copy, dirent, sizeof(*copy)); + + nl = uv__realloc(nl, sizeof(*copy) * (count + 1)); + nl[count++] = copy; + } + } + + qsort(nl, count, sizeof(struct dirent *), + (int (*)(const void *, const void *)) compar); + + closedir(mdir); + + *namelist = nl; + return count; +} + + +static unsigned int next_power_of_two(unsigned int val) { + val -= 1; + val |= val >> 1; + val |= val >> 2; + val |= val >> 4; + val |= val >> 8; + val |= val >> 16; + val += 1; + return val; +} + + +static void maybe_resize(uv__os390_epoll* lst, unsigned int len) { + unsigned int newsize; + unsigned int i; + struct pollfd* newlst; + + if (len <= lst->size) + return; + + newsize = next_power_of_two(len); + newlst = uv__realloc(lst->items, newsize * sizeof(lst->items[0])); + + if (newlst == NULL) + abort(); + for (i = lst->size; i < newsize; ++i) + newlst[i].fd = -1; + + lst->items = newlst; + lst->size = newsize; +} + + +static void epoll_init() { + QUEUE_INIT(&global_epoll_queue); + if (uv_mutex_init(&global_epoll_lock)) + abort(); +} + + +uv__os390_epoll* epoll_create1(int flags) { + uv__os390_epoll* lst; + + uv_once(&once, epoll_init); + uv_mutex_lock(&global_epoll_lock); + lst = uv__malloc(sizeof(*lst)); + if (lst == -1) + return NULL; + QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member); + uv_mutex_unlock(&global_epoll_lock); + + /* initialize list */ + lst->size = 0; + lst->items = NULL; + return lst; +} + + +int epoll_ctl(uv__os390_epoll* lst, + int op, + int fd, + struct epoll_event *event) { + if(op == EPOLL_CTL_DEL) { + if (fd >= lst->size || lst->items[fd].fd == -1) { + errno = ENOENT; + return -1; + } + lst->items[fd].fd = -1; + } else if(op == EPOLL_CTL_ADD) { + maybe_resize(lst, fd + 1); + if (lst->items[fd].fd != -1) { + errno = EEXIST; + return -1; + } + lst->items[fd].fd = fd; + lst->items[fd].events = event->events; + } else if(op == EPOLL_CTL_MOD) { + if (fd >= lst->size || lst->items[fd].fd == -1) { + errno = ENOENT; + return -1; + } + lst->items[fd].events = event->events; + } else + abort(); + + return 0; +} + + +int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, + int maxevents, int timeout) { + size_t size; + struct pollfd* pfds; + int pollret; + int reventcount; + + uv_mutex_lock(&global_epoll_lock); + uv_mutex_unlock(&global_epoll_lock); + size = lst->size; + pfds = lst->items; + pollret = poll(pfds, size, timeout); + if(pollret == -1) + return pollret; + + reventcount = 0; + for (int i = 0; i < lst->size && i < maxevents; ++i) { + struct epoll_event ev; + + ev.events = 0; + ev.fd = pfds[i].fd; + if(!pfds[i].revents) + continue; + + if(pfds[i].revents & POLLRDNORM) + ev.events = ev.events | POLLIN; + + if(pfds[i].revents & POLLWRNORM) + ev.events = ev.events | POLLOUT; + + if(pfds[i].revents & POLLHUP) + ev.events = ev.events | POLLHUP; + + pfds[i].revents = 0; + events[reventcount++] = ev; + } + + return reventcount; +} + + +int epoll_file_close(int fd) { + QUEUE* q; + + uv_once(&once, epoll_init); + uv_mutex_lock(&global_epoll_lock); + QUEUE_FOREACH(q, &global_epoll_queue) { + uv__os390_epoll* lst; + + lst = QUEUE_DATA(q, uv__os390_epoll, member); + if (fd < lst->size && lst->items != NULL && lst->items[fd].fd != -1) + lst->items[fd].fd = -1; + } + + uv_mutex_unlock(&global_epoll_lock); + return 0; +} + +void epoll_queue_close(uv__os390_epoll* lst) { + uv_mutex_lock(&global_epoll_lock); + QUEUE_REMOVE(&lst->member); + uv_mutex_unlock(&global_epoll_lock); + uv__free(lst->items); + lst->items = NULL; +} + + +int nanosleep(const struct timespec* req, struct timespec* rem) { + unsigned nano; + unsigned seconds; + unsigned events; + unsigned secrem; + unsigned nanorem; + int rv; + int rc; + int rsn; + + nano = (int)req->tv_nsec; + seconds = req->tv_sec; + events = CW_CONDVAR; + +#if defined(_LP64) + BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn); +#else + BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn); +#endif + + assert(rv == -1 && errno == EAGAIN); + + if(rem != NULL) { + rem->tv_nsec = nanorem; + rem->tv_sec = secrem; + } + + return 0; +} + + +char* mkdtemp(char* path) { + static const char* tempchars = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + static const size_t num_chars = 62; + static const size_t num_x = 6; + char *ep, *cp; + unsigned int tries, i; + size_t len; + uint64_t v; + int fd; + int retval; + int saved_errno; + + len = strlen(path); + ep = path + len; + if (len < num_x || strncmp(ep - num_x, "XXXXXX", num_x)) { + errno = EINVAL; + return NULL; + } + + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) + return NULL; + + tries = TMP_MAX; + retval = -1; + do { + if (read(fd, &v, sizeof(v)) != sizeof(v)) + break; + + cp = ep - num_x; + for (i = 0; i < num_x; i++) { + *cp++ = tempchars[v % num_chars]; + v /= num_chars; + } + + if (mkdir(path, S_IRWXU) == 0) { + retval = 0; + break; + } + else if (errno != EEXIST) + break; + } while (--tries); + + saved_errno = errno; + uv__close(fd); + if (tries == 0) { + errno = EEXIST; + return NULL; + } + + if (retval == -1) { + errno = saved_errno; + return NULL; + } + + return path; +} diff --git a/deps/uv/src/unix/os390-syscalls.h b/deps/uv/src/unix/os390-syscalls.h new file mode 100644 index 00000000000000..61a7cee8396587 --- /dev/null +++ b/deps/uv/src/unix/os390-syscalls.h @@ -0,0 +1,69 @@ +/* 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_OS390_SYSCALL_H_ +#define UV_OS390_SYSCALL_H_ + +#include "uv.h" +#include "internal.h" +#include +#include +#include + +#define EPOLL_CTL_ADD 1 +#define EPOLL_CTL_DEL 2 +#define EPOLL_CTL_MOD 3 +#define MAX_EPOLL_INSTANCES 256 +#define MAX_ITEMS_PER_EPOLL 1024 + +#define UV__O_CLOEXEC 0x80000 +#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC +#define UV__EPOLL_CTL_ADD EPOLL_CTL_ADD +#define UV__EPOLL_CTL_DEL EPOLL_CTL_DEL +#define UV__EPOLL_CTL_MOD EPOLL_CTL_MOD + +struct epoll_event { + int events; + int fd; +}; + +typedef struct { + QUEUE member; + struct pollfd* items; + unsigned long size; +} uv__os390_epoll; + +/* epoll api */ +uv__os390_epoll* epoll_create1(int flags); +int epoll_ctl(uv__os390_epoll* ep, int op, int fd, struct epoll_event *event); +int epoll_wait(uv__os390_epoll* ep, struct epoll_event *events, int maxevents, int timeout); +int epoll_file_close(int fd); + +/* utility functions */ +int nanosleep(const struct timespec* req, struct timespec* rem); +int scandir(const char* maindir, struct dirent*** namelist, + int (*filter)(const struct dirent *), + int (*compar)(const struct dirent **, + const struct dirent **)); +char *mkdtemp(char* path); + +#endif /* UV_OS390_SYSCALL_H_ */ diff --git a/deps/uv/src/unix/os390.c b/deps/uv/src/unix/os390.c index bcdbc4b6a80542..be325a923091f2 100644 --- a/deps/uv/src/unix/os390.c +++ b/deps/uv/src/unix/os390.c @@ -20,6 +20,628 @@ */ #include "internal.h" +#include +#include +#include +#include +#include +#if defined(__clang__) +#include "csrsic.h" +#else +#include "//'SYS1.SAMPLIB(CSRSIC)'" +#endif + +#define CVT_PTR 0x10 +#define CSD_OFFSET 0x294 + +/* + Long-term average CPU service used by this logical partition, + in millions of service units per hour. If this value is above + the partition's defined capacity, the partition will be capped. + It is calculated using the physical CPU adjustment factor + (RCTPCPUA) so it may not match other measures of service which + are based on the logical CPU adjustment factor. It is available + if the hardware supports LPAR cluster. +*/ +#define RCTLACS_OFFSET 0xC4 + +/* 32-bit count of alive CPUs. This includes both CPs and IFAs */ +#define CSD_NUMBER_ONLINE_CPUS 0xD4 + +/* Address of system resources manager (SRM) control table */ +#define CVTOPCTP_OFFSET 0x25C + +/* Address of the RCT table */ +#define RMCTRCT_OFFSET 0xE4 + +/* Address of the rsm control and enumeration area. */ +#define CVTRCEP_OFFSET 0x490 + +/* + Number of frames currently available to system. + Excluded are frames backing perm storage, frames offline, and bad frames. +*/ +#define RCEPOOL_OFFSET 0x004 + +/* Total number of frames currently on all available frame queues. */ +#define RCEAFC_OFFSET 0x088 + +/* CPC model length from the CSRSI Service. */ +#define CPCMODEL_LENGTH 16 + +/* Thread Entry constants */ +#define PGTH_CURRENT 1 +#define PGTH_LEN 26 +#define PGTHAPATH 0x20 +#pragma linkage(BPX4GTH, OS) +#pragma linkage(BPX1GTH, OS) + +typedef unsigned data_area_ptr_assign_type; + +typedef union { + struct { +#if defined(_LP64) + data_area_ptr_assign_type lower; +#endif + data_area_ptr_assign_type assign; + }; + char* deref; +} data_area_ptr; + + +void uv_loadavg(double avg[3]) { + /* TODO: implement the following */ + avg[0] = 0; + avg[1] = 0; + avg[2] = 0; +} + + +int uv__platform_loop_init(uv_loop_t* loop) { + uv__os390_epoll* ep; + + ep = epoll_create1(UV__EPOLL_CLOEXEC); + loop->ep = ep; + if (ep == NULL) + return -errno; + + return 0; +} + + +void uv__platform_loop_delete(uv_loop_t* loop) { + if (loop->ep != NULL) { + epoll_queue_close(loop->ep); + loop->ep = NULL; + } +} + + +uint64_t uv__hrtime(uv_clocktype_t type) { + struct timeval time; + gettimeofday(&time, NULL); + return (uint64_t) time.tv_sec * 1e9 + time.tv_usec * 1e3; +} + + +/* + Get the exe path using the thread entry information + in the address space. +*/ +static int getexe(const int pid, char* buf, size_t len) { + struct { + int pid; + int thid[2]; + char accesspid; + char accessthid; + char asid[2]; + char loginname[8]; + char flag; + char len; + } Input_data; + + union { + struct { + char gthb[4]; + int pid; + int thid[2]; + char accesspid; + char accessthid[3]; + int lenused; + int offsetProcess; + int offsetConTTY; + int offsetPath; + int offsetCommand; + int offsetFileData; + int offsetThread; + } Output_data; + char buf[2048]; + } Output_buf; + + struct Output_path_type { + char gthe[4]; + short int len; + char path[1024]; + }; + + int Input_length; + int Output_length; + void* Input_address; + void* Output_address; + struct Output_path_type* Output_path; + int rv; + int rc; + int rsn; + + Input_length = PGTH_LEN; + Output_length = sizeof(Output_buf); + Output_address = &Output_buf; + Input_address = &Input_data; + memset(&Input_data, 0, sizeof Input_data); + Input_data.flag |= PGTHAPATH; + Input_data.pid = pid; + Input_data.accesspid = PGTH_CURRENT; + +#ifdef _LP64 + BPX4GTH(&Input_length, + &Input_address, + &Output_length, + &Output_address, + &rv, + &rc, + &rsn); +#else + BPX1GTH(&Input_length, + &Input_address, + &Output_length, + &Output_address, + &rv, + &rc, + &rsn); +#endif + + if (rv == -1) { + errno = rc; + return -1; + } + + /* Check highest byte to ensure data availability */ + assert(((Output_buf.Output_data.offsetPath >>24) & 0xFF) == 'A'); + + /* Get the offset from the lowest 3 bytes */ + Output_path = (char*)(&Output_buf) + + (Output_buf.Output_data.offsetPath & 0x00FFFFFF); + + if (Output_path->len >= len) { + errno = ENOBUFS; + return -1; + } + + strncpy(buf, Output_path->path, len); + + return 0; +} + + +/* + * We could use a static buffer for the path manipulations that we need outside + * of the function, but this function could be called by multiple consumers and + * we don't want to potentially create a race condition in the use of snprintf. + * There is no direct way of getting the exe path in zOS - either through /procfs + * or through some libc APIs. The below approach is to parse the argv[0]'s pattern + * and use it in conjunction with PATH environment variable to craft one. + */ +int uv_exepath(char* buffer, size_t* size) { + int res; + char args[PATH_MAX]; + char abspath[PATH_MAX]; + size_t abspath_size; + int pid; + + if (buffer == NULL || size == NULL || *size == 0) + return -EINVAL; + + pid = getpid(); + res = getexe(pid, args, sizeof(args)); + if (res < 0) + return -EINVAL; + + /* + * Possibilities for args: + * i) an absolute path such as: /home/user/myprojects/nodejs/node + * ii) a relative path such as: ./node or ../myprojects/nodejs/node + * iii) a bare filename such as "node", after exporting PATH variable + * to its location. + */ + + /* Case i) and ii) absolute or relative paths */ + if (strchr(args, '/') != NULL) { + if (realpath(args, abspath) != abspath) + return -errno; + + abspath_size = strlen(abspath); + + *size -= 1; + if (*size > abspath_size) + *size = abspath_size; + + memcpy(buffer, abspath, *size); + buffer[*size] = '\0'; + + return 0; + } else { + /* Case iii). Search PATH environment variable */ + char trypath[PATH_MAX]; + char* clonedpath = NULL; + char* token = NULL; + char* path = getenv("PATH"); + + if (path == NULL) + return -EINVAL; + + clonedpath = uv__strdup(path); + if (clonedpath == NULL) + return -ENOMEM; + + token = strtok(clonedpath, ":"); + while (token != NULL) { + snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args); + if (realpath(trypath, abspath) == abspath) { + /* Check the match is executable */ + if (access(abspath, X_OK) == 0) { + abspath_size = strlen(abspath); + + *size -= 1; + if (*size > abspath_size) + *size = abspath_size; + + memcpy(buffer, abspath, *size); + buffer[*size] = '\0'; + + uv__free(clonedpath); + return 0; + } + } + token = strtok(NULL, ":"); + } + uv__free(clonedpath); + + /* Out of tokens (path entries), and no match found */ + return -EINVAL; + } +} + + +uint64_t uv_get_free_memory(void) { + uint64_t freeram; + + data_area_ptr cvt = {0}; + data_area_ptr rcep = {0}; + cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); + rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET); + freeram = *((uint64_t*)(rcep.deref + RCEAFC_OFFSET)) * 4; + return freeram; +} + + +uint64_t uv_get_total_memory(void) { + uint64_t totalram; + + data_area_ptr cvt = {0}; + data_area_ptr rcep = {0}; + cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); + rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET); + totalram = *((uint64_t*)(rcep.deref + RCEPOOL_OFFSET)) * 4; + return totalram; +} + + +int uv_resident_set_memory(size_t* rss) { + W_PSPROC buf; + + memset(&buf, 0, sizeof(buf)); + if (w_getpsent(0, &buf, sizeof(W_PSPROC)) == -1) + return -EINVAL; + + *rss = buf.ps_size; + return 0; +} + + +int uv_uptime(double* uptime) { + struct utmpx u ; + struct utmpx *v; + time64_t t; + + u.ut_type = BOOT_TIME; + v = getutxid(&u); + if (v == NULL) + return -1; + *uptime = difftime64(time64(&t), v->ut_tv.tv_sec); + return 0; +} + + +int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { + uv_cpu_info_t* cpu_info; + int result; + int idx; + siv1v2 info; + data_area_ptr cvt = {0}; + data_area_ptr csd = {0}; + data_area_ptr rmctrct = {0}; + data_area_ptr cvtopctp = {0}; + int cpu_usage_avg; + + cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); + + csd.assign = *((data_area_ptr_assign_type *) (cvt.deref + CSD_OFFSET)); + cvtopctp.assign = *((data_area_ptr_assign_type *) (cvt.deref + CVTOPCTP_OFFSET)); + rmctrct.assign = *((data_area_ptr_assign_type *) (cvtopctp.deref + RMCTRCT_OFFSET)); + + *count = *((int*) (csd.deref + CSD_NUMBER_ONLINE_CPUS)); + cpu_usage_avg = *((unsigned short int*) (rmctrct.deref + RCTLACS_OFFSET)); + + *cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t)); + if (!*cpu_infos) + return -ENOMEM; + + cpu_info = *cpu_infos; + idx = 0; + while (idx < *count) { + cpu_info->speed = *(int*)(info.siv1v2si22v1.si22v1cpucapability); + cpu_info->model = uv__malloc(CPCMODEL_LENGTH + 1); + memset(cpu_info->model, '\0', CPCMODEL_LENGTH + 1); + memcpy(cpu_info->model, info.siv1v2si11v1.si11v1cpcmodel, CPCMODEL_LENGTH); + cpu_info->cpu_times.user = cpu_usage_avg; + /* TODO: implement the following */ + cpu_info->cpu_times.sys = 0; + cpu_info->cpu_times.idle = 0; + cpu_info->cpu_times.irq = 0; + cpu_info->cpu_times.nice = 0; + ++cpu_info; + ++idx; + } + + return 0; +} + + +void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { + for (int i = 0; i < count; ++i) + uv__free(cpu_infos[i].model); + uv__free(cpu_infos); +} + + +static int uv__interface_addresses_v6(uv_interface_address_t** addresses, + int* count) { + uv_interface_address_t* address; + int sockfd; + int maxsize; + __net_ifconf6header_t ifc; + __net_ifconf6entry_t* ifr; + __net_ifconf6entry_t* p; + __net_ifconf6entry_t flg; + + *count = 0; + /* Assume maximum buffer size allowable */ + maxsize = 16384; + + if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) + return -errno; + + ifc.__nif6h_version = 1; + ifc.__nif6h_buflen = maxsize; + ifc.__nif6h_buffer = uv__calloc(1, maxsize);; + + if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) { + uv__close(sockfd); + return -errno; + } + + + *count = 0; + ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); + while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { + p = ifr; + ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); + + if (!(p->__nif6e_addr.sin6_family == AF_INET6 || + p->__nif6e_addr.sin6_family == AF_INET)) + continue; + + if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) + continue; + + ++(*count); + } + + /* Alloc the return interface structs */ + *addresses = uv__malloc(*count * sizeof(uv_interface_address_t)); + if (!(*addresses)) { + uv__close(sockfd); + return -ENOMEM; + } + address = *addresses; + + ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); + while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { + p = ifr; + ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); + + if (!(p->__nif6e_addr.sin6_family == AF_INET6 || + p->__nif6e_addr.sin6_family == AF_INET)) + continue; + + if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) + continue; + + /* All conditions above must match count loop */ + + address->name = uv__strdup(p->__nif6e_name); + + if (p->__nif6e_addr.sin6_family == AF_INET6) + address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr); + else + address->address.address4 = *((struct sockaddr_in*) &p->__nif6e_addr); + + /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */ + + address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0; + + address++; + } + + uv__close(sockfd); + return 0; +} + + +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + uv_interface_address_t* address; + int sockfd; + int maxsize; + struct ifconf ifc; + struct ifreq flg; + struct ifreq* ifr; + struct ifreq* p; + int count_v6; + + /* get the ipv6 addresses first */ + uv_interface_address_t* addresses_v6; + uv__interface_addresses_v6(&addresses_v6, &count_v6); + + /* now get the ipv4 addresses */ + *count = 0; + + /* Assume maximum buffer size allowable */ + maxsize = 16384; + + sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (0 > sockfd) + return -errno; + + ifc.ifc_req = uv__calloc(1, maxsize); + ifc.ifc_len = maxsize; + if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { + uv__close(sockfd); + return -errno; + } + +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) + + /* Count all up and running ipv4/ipv6 addresses */ + ifr = ifc.ifc_req; + while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { + p = ifr; + ifr = (struct ifreq*) + ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); + + if (!(p->ifr_addr.sa_family == AF_INET6 || + p->ifr_addr.sa_family == AF_INET)) + continue; + + memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { + uv__close(sockfd); + return -errno; + } + + if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) + continue; + + (*count)++; + } + + /* Alloc the return interface structs */ + *addresses = uv__malloc((*count + count_v6) * + sizeof(uv_interface_address_t)); + + if (!(*addresses)) { + uv__close(sockfd); + return -ENOMEM; + } + address = *addresses; + + /* copy over the ipv6 addresses */ + memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t)); + address += count_v6; + *count += count_v6; + uv__free(addresses_v6); + + ifr = ifc.ifc_req; + while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { + p = ifr; + ifr = (struct ifreq*) + ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); + + if (!(p->ifr_addr.sa_family == AF_INET6 || + p->ifr_addr.sa_family == AF_INET)) + continue; + + memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { + uv__close(sockfd); + return -ENOSYS; + } + + if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) + continue; + + /* All conditions above must match count loop */ + + address->name = uv__strdup(p->ifr_name); + + if (p->ifr_addr.sa_family == AF_INET6) { + address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); + } else { + address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); + } + + address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; + address++; + } + +#undef ADDR_SIZE +#undef MAX + + uv__close(sockfd); + return 0; +} + + +void uv_free_interface_addresses(uv_interface_address_t* addresses, + int count) { + int i; + for (i = 0; i < count; ++i) + uv__free(addresses[i].name); + uv__free(addresses); +} + + +void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { + struct epoll_event* events; + struct epoll_event dummy; + uintptr_t i; + uintptr_t nfds; + + assert(loop->watchers != NULL); + + events = (struct epoll_event*) loop->watchers[loop->nwatchers]; + nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; + if (events != NULL) + /* Invalidate events with same file descriptor */ + for (i = 0; i < nfds; i++) + if ((int) events[i].fd == fd) + events[i].fd = -1; + + /* Remove the file descriptor from the epoll. */ + if (loop->ep != NULL) + epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, &dummy); +} + int uv__io_check_fd(uv_loop_t* loop, int fd) { struct pollfd p[1]; @@ -40,3 +662,204 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) { return 0; } + + +void uv__fs_event_close(uv_fs_event_t* handle) { + UNREACHABLE(); +} + + +int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { + return -ENOSYS; +} + + +int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, + const char* filename, unsigned int flags) { + return -ENOSYS; +} + + +int uv_fs_event_stop(uv_fs_event_t* handle) { + return -ENOSYS; +} + + +void uv__io_poll(uv_loop_t* loop, int timeout) { + static const int max_safe_timeout = 1789569; + struct epoll_event events[1024]; + struct epoll_event* pe; + struct epoll_event e; + int real_timeout; + QUEUE* q; + uv__io_t* w; + uint64_t base; + int count; + int nfds; + int fd; + int op; + int i; + + if (loop->nfds == 0) { + assert(QUEUE_EMPTY(&loop->watcher_queue)); + return; + } + + while (!QUEUE_EMPTY(&loop->watcher_queue)) { + uv_stream_t* stream; + + q = QUEUE_HEAD(&loop->watcher_queue); + QUEUE_REMOVE(q); + QUEUE_INIT(q); + w = QUEUE_DATA(q, uv__io_t, watcher_queue); + + assert(w->pevents != 0); + assert(w->fd >= 0); + + stream= container_of(w, uv_stream_t, io_watcher); + + assert(w->fd < (int) loop->nwatchers); + + e.events = w->pevents; + e.fd = w->fd; + + if (w->events == 0) + op = UV__EPOLL_CTL_ADD; + else + op = UV__EPOLL_CTL_MOD; + + /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching + * events, skip the syscall and squelch the events after epoll_wait(). + */ + if (epoll_ctl(loop->ep, op, w->fd, &e)) { + if (errno != EEXIST) + abort(); + + assert(op == UV__EPOLL_CTL_ADD); + + /* We've reactivated a file descriptor that's been watched before. */ + if (epoll_ctl(loop->ep, UV__EPOLL_CTL_MOD, w->fd, &e)) + abort(); + } + + w->events = w->pevents; + } + + assert(timeout >= -1); + base = loop->time; + count = 48; /* Benchmarks suggest this gives the best throughput. */ + real_timeout = timeout; + int nevents = 0; + + nfds = 0; + for (;;) { + if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) + timeout = max_safe_timeout; + + nfds = epoll_wait(loop->ep, events, + ARRAY_SIZE(events), timeout); + + /* Update loop->time unconditionally. It's tempting to skip the update when + * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the + * operating system didn't reschedule our process while in the syscall. + */ + base = loop->time; + SAVE_ERRNO(uv__update_time(loop)); + if (nfds == 0) { + assert(timeout != -1); + timeout = real_timeout - timeout; + if (timeout > 0) + continue; + + return; + } + + if (nfds == -1) { + + if (errno != EINTR) + abort(); + + if (timeout == -1) + continue; + + if (timeout == 0) + return; + + /* Interrupted by a signal. Update timeout and poll again. */ + goto update_timeout; + } + + + assert(loop->watchers != NULL); + loop->watchers[loop->nwatchers] = (void*) events; + loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; + for (i = 0; i < nfds; i++) { + pe = events + i; + fd = pe->fd; + + /* Skip invalidated events, see uv__platform_invalidate_fd */ + if (fd == -1) + continue; + + assert(fd >= 0); + assert((unsigned) fd < loop->nwatchers); + + w = loop->watchers[fd]; + + if (w == NULL) { + /* File descriptor that we've stopped watching, disarm it. + * + * Ignore all errors because we may be racing with another thread + * when the file descriptor is closed. + */ + epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, pe); + continue; + } + + /* Give users only events they're interested in. Prevents spurious + * callbacks when previous callback invocation in this loop has stopped + * the current watcher. Also, filters out events that users has not + * requested us to watch. + */ + pe->events &= w->pevents | POLLERR | POLLHUP; + + if (pe->events == POLLERR || pe->events == POLLHUP) + pe->events |= w->pevents & (POLLIN | POLLOUT); + + if (pe->events != 0) { + w->cb(loop, w, pe->events); + nevents++; + } + } + loop->watchers[loop->nwatchers] = NULL; + loop->watchers[loop->nwatchers + 1] = NULL; + + if (nevents != 0) { + if (nfds == ARRAY_SIZE(events) && --count != 0) { + /* Poll for more events but don't block this time. */ + timeout = 0; + continue; + } + return; + } + + if (timeout == 0) + return; + + if (timeout == -1) + continue; + +update_timeout: + assert(timeout > 0); + + real_timeout -= (loop->time - base); + if (real_timeout <= 0) + return; + + timeout = real_timeout; + } +} + +void uv__set_process_title(const char* title) { + /* do nothing */ +} diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index 45f5b4526b9774..f2fe30521c1d9b 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -323,7 +323,7 @@ static void uv__process_child_init(const uv_process_options_t* options, } if (fd == use_fd) - uv__cloexec(use_fd, 0); + uv__cloexec_fcntl(use_fd, 0); else fd = dup2(use_fd, fd); @@ -333,7 +333,7 @@ static void uv__process_child_init(const uv_process_options_t* options, } if (fd <= 2) - uv__nonblock(fd, 0); + uv__nonblock_fcntl(fd, 0); if (close_fd >= stdio_count) uv__close(close_fd); diff --git a/deps/uv/src/unix/proctitle.c b/deps/uv/src/unix/proctitle.c index 08d875f7af4112..9160f7eafb3729 100644 --- a/deps/uv/src/unix/proctitle.c +++ b/deps/uv/src/unix/proctitle.c @@ -48,9 +48,15 @@ char** uv_setup_args(int argc, char** argv) { for (i = 0; i < argc; i++) size += strlen(argv[i]) + 1; +#if defined(__MVS__) + /* argv is not adjacent. So just use argv[0] */ + process_title.str = argv[0]; + process_title.len = strlen(argv[0]); +#else process_title.str = argv[0]; process_title.len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0]; assert(process_title.len + 1 == size); /* argv memory should be adjacent. */ +#endif /* Add space for the argv pointers. */ size += (argc + 1) * sizeof(char*); diff --git a/deps/uv/src/unix/pthread-barrier.c b/deps/uv/src/unix/pthread-barrier.c index f57bf25080c4e1..b6e604d46d825c 100644 --- a/deps/uv/src/unix/pthread-barrier.c +++ b/deps/uv/src/unix/pthread-barrier.c @@ -73,7 +73,8 @@ int pthread_barrier_wait(pthread_barrier_t* barrier) { if (++b->in == b->threshold) { b->in = 0; b->out = b->threshold - 1; - assert(pthread_cond_signal(&b->cond) == 0); + rc = pthread_cond_signal(&b->cond); + assert(rc == 0); pthread_mutex_unlock(&b->mutex); return PTHREAD_BARRIER_SERIAL_THREAD; diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 86f4eb7a5c6b3e..7059df16a69a03 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -390,7 +390,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { int uv__stream_open(uv_stream_t* stream, int fd, int flags) { -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__MVS__) int enable; #endif @@ -409,7 +409,7 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) { return -errno; } -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__MVS__) enable = 1; if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) && errno != ENOTSOCK && @@ -1194,6 +1194,30 @@ static void uv__read(uv_stream_t* stream) { return; } } + +#if defined(__MVS__) + if (is_ipc && msg.msg_controllen > 0) { + uv_buf_t blankbuf; + int nread; + struct iovec *old; + + blankbuf.base = 0; + blankbuf.len = 0; + old = msg.msg_iov; + msg.msg_iov = (struct iovec*) &blankbuf; + nread = 0; + do { + nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0); + err = uv__stream_recv_cmsg(stream, &msg); + if (err != 0) { + stream->read_cb(stream, err, &buf); + msg.msg_iov = old; + return; + } + } while (nread == 0 && msg.msg_controllen > 0); + msg.msg_iov = old; + } +#endif stream->read_cb(stream, nread, &buf); /* Return if we didn't fill the buffer, there is no more data to read. */ diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index 3e7a7592d911e5..a43f7f1b1c021c 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -695,6 +695,11 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } +#ifdef SUNOS_NO_IFADDRS +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + return -ENOSYS; +} +#else /* SUNOS_NO_IFADDRS */ /* * Inspired By: * https://blogs.oracle.com/paulie/entry/retrieving_mac_address_in_solaris @@ -742,9 +747,6 @@ static int uv__set_phys_addr(uv_interface_address_t* address, } int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { -#ifdef SUNOS_NO_IFADDRS - return -ENOSYS; -#else uv_interface_address_t* address; struct ifaddrs* addrs; struct ifaddrs* ent; @@ -805,9 +807,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { freeifaddrs(addrs); return 0; -#endif /* SUNOS_NO_IFADDRS */ } - +#endif /* SUNOS_NO_IFADDRS */ void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) { diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 46d954673a1c94..bc7d1379d131f2 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -512,8 +512,18 @@ void uv__fs_scandir_cleanup(uv_fs_t* req) { int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { uv__dirent_t** dents; uv__dirent_t* dent; + unsigned int* nbufs; - unsigned int* nbufs = uv__get_nbufs(req); + /* Check to see if req passed */ + if (req->result < 0) + return req->result; + + /* Ptr will be null if req was canceled or no files found */ + if (!req->ptr) + return UV_EOF; + + nbufs = uv__get_nbufs(req); + assert(nbufs); dents = req->ptr; diff --git a/deps/uv/src/win/signal.c b/deps/uv/src/win/signal.c index 2c64a55dc393a2..af7974c364465f 100644 --- a/deps/uv/src/win/signal.c +++ b/deps/uv/src/win/signal.c @@ -30,12 +30,14 @@ RB_HEAD(uv_signal_tree_s, uv_signal_s); static struct uv_signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree); -static ssize_t volatile uv__signal_control_handler_refs = 0; static CRITICAL_SECTION uv__signal_lock; +static BOOL WINAPI uv__signal_control_handler(DWORD type); void uv_signals_init() { InitializeCriticalSection(&uv__signal_lock); + if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE)) + abort(); } @@ -125,102 +127,6 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) { } -static int uv__signal_register_control_handler() { - /* When this function is called, the uv__signal_lock must be held. */ - - /* If the console control handler has already been hooked, just add a */ - /* reference. */ - if (uv__signal_control_handler_refs > 0) { - uv__signal_control_handler_refs++; - return 0; - } - - if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE)) - return GetLastError(); - - uv__signal_control_handler_refs++; - - return 0; -} - - -static void uv__signal_unregister_control_handler() { - /* When this function is called, the uv__signal_lock must be held. */ - BOOL r; - - /* Don't unregister if the number of console control handlers exceeds one. */ - /* Just remove a reference in that case. */ - if (uv__signal_control_handler_refs > 1) { - uv__signal_control_handler_refs--; - return; - } - - assert(uv__signal_control_handler_refs == 1); - - r = SetConsoleCtrlHandler(uv__signal_control_handler, FALSE); - /* This should never fail; if it does it is probably a bug in libuv. */ - assert(r); - - uv__signal_control_handler_refs--; -} - - -static int uv__signal_register(int signum) { - switch (signum) { - case SIGINT: - case SIGBREAK: - case SIGHUP: - return uv__signal_register_control_handler(); - - case SIGWINCH: - /* SIGWINCH is generated in tty.c. No need to register anything. */ - return 0; - - case SIGILL: - case SIGABRT_COMPAT: - case SIGFPE: - case SIGSEGV: - case SIGTERM: - case SIGABRT: - /* Signal is never raised. */ - return 0; - - default: - /* Invalid signal. */ - return ERROR_INVALID_PARAMETER; - } -} - - -static void uv__signal_unregister(int signum) { - switch (signum) { - case SIGINT: - case SIGBREAK: - case SIGHUP: - uv__signal_unregister_control_handler(); - return; - - case SIGWINCH: - /* SIGWINCH is generated in tty.c. No need to unregister anything. */ - return; - - case SIGILL: - case SIGABRT_COMPAT: - case SIGFPE: - case SIGSEGV: - case SIGTERM: - case SIGABRT: - /* Nothing is registered for this signal. */ - return; - - default: - /* Libuv bug. */ - assert(0 && "Invalid signum"); - return; - } -} - - int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) { uv_req_t* req; @@ -247,8 +153,6 @@ int uv_signal_stop(uv_signal_t* handle) { EnterCriticalSection(&uv__signal_lock); - uv__signal_unregister(handle->signum); - removed_handle = RB_REMOVE(uv_signal_tree_s, &uv__signal_tree, handle); assert(removed_handle == handle); @@ -262,14 +166,9 @@ int uv_signal_stop(uv_signal_t* handle) { int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { - int err; - - /* If the user supplies signum == 0, then return an error already. If the */ - /* signum is otherwise invalid then uv__signal_register will find out */ - /* eventually. */ - if (signum == 0) { + /* Test for invalid signal values. */ + if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG)) return UV_EINVAL; - } /* Short circuit: if the signal watcher is already watching {signum} don't */ /* go through the process of deregistering and registering the handler. */ @@ -289,13 +188,6 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { EnterCriticalSection(&uv__signal_lock); - err = uv__signal_register(signum); - if (err) { - /* Uh-oh, didn't work. */ - LeaveCriticalSection(&uv__signal_lock); - return uv_translate_sys_error(err); - } - handle->signum = signum; RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle); diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index 341fcd0842f76e..9401676fbdc3ad 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4606,6 +4606,10 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile) #endif /* from winerror.h */ +#ifndef ERROR_ELEVATION_REQUIRED +# define ERROR_ELEVATION_REQUIRED 740 +#endif + #ifndef ERROR_SYMLINK_NOT_SUPPORTED # define ERROR_SYMLINK_NOT_SUPPORTED 1464 #endif diff --git a/deps/uv/test/test-error.c b/deps/uv/test/test-error.c index ff53eb1d777903..a2d559a4ee1564 100644 --- a/deps/uv/test/test-error.c +++ b/deps/uv/test/test-error.c @@ -21,6 +21,9 @@ #include "uv.h" #include "task.h" +#if defined(_WIN32) +# include "../src/win/winapi.h" +#endif #include #include diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 70a23999624741..030245eadc5389 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -510,6 +510,18 @@ static void empty_scandir_cb(uv_fs_t* req) { scandir_cb_count++; } +static void non_existent_scandir_cb(uv_fs_t* req) { + uv_dirent_t dent; + + ASSERT(req == &scandir_req); + ASSERT(req->fs_type == UV_FS_SCANDIR); + ASSERT(req->result == UV_ENOENT); + ASSERT(req->ptr == NULL); + ASSERT(UV_ENOENT == uv_fs_scandir_next(req, &dent)); + uv_fs_req_cleanup(req); + scandir_cb_count++; +} + static void file_scandir_cb(uv_fs_t* req) { ASSERT(req == &scandir_req); @@ -2175,6 +2187,39 @@ TEST_IMPL(fs_scandir_empty_dir) { } +TEST_IMPL(fs_scandir_non_existent_dir) { + const char* path; + uv_fs_t req; + uv_dirent_t dent; + int r; + + path = "./non_existent_dir/"; + loop = uv_default_loop(); + + uv_fs_rmdir(NULL, &req, path, NULL); + uv_fs_req_cleanup(&req); + + /* Fill the req to ensure that required fields are cleaned up */ + memset(&req, 0xdb, sizeof(req)); + + r = uv_fs_scandir(NULL, &req, path, 0, NULL); + ASSERT(r == UV_ENOENT); + ASSERT(req.result == UV_ENOENT); + ASSERT(req.ptr == NULL); + ASSERT(UV_ENOENT == uv_fs_scandir_next(&req, &dent)); + uv_fs_req_cleanup(&req); + + r = uv_fs_scandir(loop, &scandir_req, path, 0, non_existent_scandir_cb); + ASSERT(r == 0); + + ASSERT(scandir_cb_count == 0); + uv_run(loop, UV_RUN_DEFAULT); + ASSERT(scandir_cb_count == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + TEST_IMPL(fs_scandir_file) { const char* path; int r; diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index be3f9069cc7779..3a1e82a919186b 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -295,6 +295,7 @@ TEST_DECLARE (fs_event_start_and_close) TEST_DECLARE (fs_event_error_reporting) TEST_DECLARE (fs_event_getpath) TEST_DECLARE (fs_scandir_empty_dir) +TEST_DECLARE (fs_scandir_non_existent_dir) TEST_DECLARE (fs_scandir_file) TEST_DECLARE (fs_open_dir) TEST_DECLARE (fs_rename_to_existing_file) @@ -345,6 +346,7 @@ TEST_DECLARE (listen_no_simultaneous_accepts) TEST_DECLARE (fs_stat_root) TEST_DECLARE (spawn_with_an_odd_path) TEST_DECLARE (ipc_listen_after_bind_twice) +TEST_DECLARE (win32_signum_number) #else TEST_DECLARE (emfile) TEST_DECLARE (close_fd) @@ -694,6 +696,7 @@ TASK_LIST_START TEST_ENTRY (fs_stat_root) TEST_ENTRY (spawn_with_an_odd_path) TEST_ENTRY (ipc_listen_after_bind_twice) + TEST_ENTRY (win32_signum_number) #else TEST_ENTRY (emfile) TEST_ENTRY (close_fd) @@ -751,6 +754,7 @@ TASK_LIST_START TEST_ENTRY (fs_event_error_reporting) TEST_ENTRY (fs_event_getpath) TEST_ENTRY (fs_scandir_empty_dir) + TEST_ENTRY (fs_scandir_non_existent_dir) TEST_ENTRY (fs_scandir_file) TEST_ENTRY (fs_open_dir) TEST_ENTRY (fs_rename_to_existing_file) diff --git a/deps/uv/test/test-process-title.c b/deps/uv/test/test-process-title.c index 21ab0ed4fde8c8..5d5ede9d60291c 100644 --- a/deps/uv/test/test-process-title.c +++ b/deps/uv/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) || defined(__MVS__) +#if defined(__sun) RETURN_SKIP("uv_(get|set)_process_title is not implemented."); #else /* Check for format string vulnerabilities. */ diff --git a/deps/uv/test/test-signal.c b/deps/uv/test/test-signal.c index fcdd8e4d2dde27..c0424c60a0995e 100644 --- a/deps/uv/test/test-signal.c +++ b/deps/uv/test/test-signal.c @@ -19,13 +19,40 @@ * IN THE SOFTWARE. */ - -/* This test does not pretend to be cross-platform. */ -#ifndef _WIN32 - #include "uv.h" #include "task.h" +/* For Windows we test only signum handling */ +#ifdef _WIN32 +static void signum_test_cb(uv_signal_t* handle, int signum) { + FATAL("signum_test_cb should not be called"); +} + +TEST_IMPL(win32_signum_number) { + uv_signal_t signal; + uv_loop_t* loop; + + loop = uv_default_loop(); + uv_signal_init(loop, &signal); + + ASSERT(uv_signal_start(&signal, signum_test_cb, 0) == UV_EINVAL); + ASSERT(uv_signal_start(&signal, signum_test_cb, SIGINT) == 0); + ASSERT(uv_signal_start(&signal, signum_test_cb, SIGBREAK) == 0); + ASSERT(uv_signal_start(&signal, signum_test_cb, SIGHUP) == 0); + ASSERT(uv_signal_start(&signal, signum_test_cb, SIGWINCH) == 0); + ASSERT(uv_signal_start(&signal, signum_test_cb, SIGILL) == 0); + ASSERT(uv_signal_start(&signal, signum_test_cb, SIGABRT_COMPAT) == 0); + ASSERT(uv_signal_start(&signal, signum_test_cb, SIGFPE) == 0); + ASSERT(uv_signal_start(&signal, signum_test_cb, SIGSEGV) == 0); + ASSERT(uv_signal_start(&signal, signum_test_cb, SIGTERM) == 0); + ASSERT(uv_signal_start(&signal, signum_test_cb, SIGABRT) == 0); + ASSERT(uv_signal_start(&signal, signum_test_cb, -1) == UV_EINVAL); + ASSERT(uv_signal_start(&signal, signum_test_cb, NSIG) == UV_EINVAL); + ASSERT(uv_signal_start(&signal, signum_test_cb, 1024) == UV_EINVAL); + MAKE_VALGRIND_HAPPY(); + return 0; +} +#else #include #include #include diff --git a/deps/uv/test/test-tty.c b/deps/uv/test/test-tty.c index d1f7deb2319e44..6fc2c95c98590c 100644 --- a/deps/uv/test/test-tty.c +++ b/deps/uv/test/test-tty.c @@ -287,6 +287,9 @@ TEST_IMPL(tty_large_write) { r = uv_tty_init(uv_default_loop(), &tty_out, ttyout_fd, 0); /* Writable. */ ASSERT(r == 0); + memset(dummy, '.', sizeof(dummy) - 1); + dummy[sizeof(dummy) - 1] = '\n'; + bufs[0] = uv_buf_init(dummy, sizeof(dummy)); r = uv_try_write((uv_stream_t*) &tty_out, bufs, 1); diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index b969a8cd5dad20..49d5d22f96784b 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -10,13 +10,14 @@ ['OS=="solaris"', { 'cflags': [ '-pthreads' ], }], - ['OS not in "solaris android zos"', { + ['OS not in "solaris android os390"', { 'cflags': [ '-pthread' ], }], - ['OS in "zos"', { + ['OS in "os390"', { 'defines': [ '_UNIX03_THREADS', '_UNIX03_SOURCE', + '_UNIX03_WITHDRAWN', '_OPEN_SYS_IF_EXT', '_OPEN_SYS_SOCK_IPV6', '_OPEN_MSGQ_EXT', @@ -28,6 +29,7 @@ 'PATH_MAX=255' ], 'cflags': [ '-qxplink' ], + 'ldflags': [ '-qxplink' ], }] ], }], @@ -170,10 +172,10 @@ ['OS=="solaris"', { 'ldflags': [ '-pthreads' ], }], - [ 'OS=="zos" and uv_library=="shared_library"', { + [ 'OS=="os390" and uv_library=="shared_library"', { 'ldflags': [ '-Wl,DLL' ], }], - ['OS != "solaris" and OS != "android" and OS != "zos"', { + ['OS != "solaris" and OS != "android" and OS != "os390"', { 'ldflags': [ '-pthread' ], }], ], @@ -181,14 +183,14 @@ 'conditions': [ ['uv_library=="shared_library"', { 'conditions': [ - ['OS=="zos"', { + ['OS=="os390"', { 'cflags': [ '-qexportall' ], }, { 'cflags': [ '-fPIC' ], }], ], }], - ['uv_library=="shared_library" and OS!="mac" and OS!="zos"', { + ['uv_library=="shared_library" and OS!="mac" and OS!="os390"', { # This will cause gyp to set soname # Must correspond with UV_VERSION_MAJOR # in include/uv-version.h @@ -196,10 +198,10 @@ }], ], }], - [ 'OS in "linux mac ios android"', { + [ 'OS in "linux mac ios android os390"', { 'sources': [ 'src/unix/proctitle.c' ], }], - [ 'OS != "zos"', { + [ 'OS != "os390"', { 'cflags': [ '-fvisibility=hidden', '-g', @@ -222,7 +224,7 @@ '_DARWIN_UNLIMITED_SELECT=1', ] }], - [ 'OS!="mac" and OS!="zos"', { + [ 'OS!="mac" and OS!="os390"', { # Enable on all platforms except OS X. The antique gcc/clang that # ships with Xcode emits waaaay too many false positives. 'cflags': [ '-Wstrict-aliasing' ], @@ -275,6 +277,7 @@ '_XOPEN_SOURCE=500', '_LINUX_SOURCE_COMPAT', '_THREAD_SAFE', + 'HAVE_SYS_AHAFS_EVPRODS_H', ], 'link_settings': { 'libraries': [ @@ -302,11 +305,12 @@ ['uv_library=="shared_library"', { 'defines': [ 'BUILDING_UV_SHARED=1' ] }], - ['OS=="zos"', { + ['OS=="os390"', { 'sources': [ 'src/unix/pthread-fixes.c', - 'src/unix/pthread-barrier.c' - 'src/unix/os390.c' + 'src/unix/pthread-barrier.c', + 'src/unix/os390.c', + 'src/unix/os390-syscalls.c' ] }], ] @@ -467,7 +471,7 @@ 'test/runner-unix.h', ], 'conditions': [ - [ 'OS != "zos"', { + [ 'OS != "os390"', { 'defines': [ '_GNU_SOURCE' ], 'cflags': [ '-Wno-long-long' ], 'xcode_settings': { @@ -496,7 +500,7 @@ ['uv_library=="shared_library"', { 'defines': [ 'USING_UV_SHARED=1' ], 'conditions': [ - [ 'OS == "zos"', { + [ 'OS == "os390"', { 'cflags': [ '-Wc,DLL' ], }], ], @@ -557,7 +561,7 @@ ['uv_library=="shared_library"', { 'defines': [ 'USING_UV_SHARED=1' ], 'conditions': [ - [ 'OS == "zos"', { + [ 'OS == "os390"', { 'cflags': [ '-Wc,DLL' ], }], ],