Browse Source

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 <jasnell@gmail.com>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
v6
cjihrig 8 years ago
parent
commit
8514269876
  1. 1
      deps/uv/.mailmap
  2. 5
      deps/uv/AUTHORS
  3. 39
      deps/uv/ChangeLog
  4. 12
      deps/uv/Makefile.am
  5. 2
      deps/uv/appveyor.yml
  6. 4
      deps/uv/common.gypi
  7. 2
      deps/uv/configure.ac
  8. 6
      deps/uv/docs/src/conf.py
  9. 6
      deps/uv/docs/src/misc.rst
  10. 2
      deps/uv/include/pthread-barrier.h
  11. 3
      deps/uv/include/uv-os390.h
  12. 4
      deps/uv/include/uv-unix.h
  13. 4
      deps/uv/include/uv-version.h
  14. 1
      deps/uv/include/uv-win.h
  15. 86
      deps/uv/src/unix/aix.c
  16. 27
      deps/uv/src/unix/atomic-ops.h
  17. 3
      deps/uv/src/unix/core.c
  18. 10
      deps/uv/src/unix/darwin.c
  19. 28
      deps/uv/src/unix/fs.c
  20. 4
      deps/uv/src/unix/internal.h
  21. 334
      deps/uv/src/unix/os390-syscalls.c
  22. 69
      deps/uv/src/unix/os390-syscalls.h
  23. 823
      deps/uv/src/unix/os390.c
  24. 4
      deps/uv/src/unix/process.c
  25. 6
      deps/uv/src/unix/proctitle.c
  26. 3
      deps/uv/src/unix/pthread-barrier.c
  27. 28
      deps/uv/src/unix/stream.c
  28. 11
      deps/uv/src/unix/sunos.c
  29. 12
      deps/uv/src/uv-common.c
  30. 118
      deps/uv/src/win/signal.c
  31. 4
      deps/uv/src/win/winapi.h
  32. 3
      deps/uv/test/test-error.c
  33. 45
      deps/uv/test/test-fs.c
  34. 4
      deps/uv/test/test-list.h
  35. 2
      deps/uv/test/test-process-title.c
  36. 35
      deps/uv/test/test-signal.c
  37. 3
      deps/uv/test/test-tty.c
  38. 34
      deps/uv/uv.gyp

1
deps/uv/.mailmap

@ -1,6 +1,7 @@
Aaron Bieber <qbit@deftly.net> <deftly@gmail.com>
Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com>
Bert Belder <bertbelder@gmail.com> <i@bertbelder.com>
Bert Belder <bertbelder@gmail.com> <info@2bs.nl>
Bert Belder <bertbelder@gmail.com> <user@ChrUbuntu.(none)>
Brandon Philips <brandon.philips@rackspace.com> <brandon@ifup.org>

5
deps/uv/AUTHORS

@ -279,3 +279,8 @@ Philippe Laferriere <laferriere.phil@gmail.com>
Will Speak <lithiumflame@gmail.com>
Hitesh Kanwathirtha <digitalinfinity@gmail.com>
Eric Sciple <ersciple@microsoft.com>
jBarz <jBarz@users.noreply.github.com>
muflub <admin@lodle.net>
Daniel Bevenius <daniel.bevenius@gmail.com>
Howard Hellyer <hhellyer@uk.ibm.com>
Chris Araman <chris.araman@fuze.com>

39
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:

12
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

2
deps/uv/appveyor.yml

@ -1,4 +1,4 @@
version: v1.10.2.build{build}
version: v1.11.0.build{build}
install:
- cinst -y nsis

4
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' ],
}],

2
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])

6
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))

6
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)

2
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 <errno.h>
#include <pthread.h>
#if !defined(__MVS__)
#include <semaphore.h> /* sem_t */
#endif
#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345

3
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 */

4
deps/uv/include/uv-unix.h

@ -36,7 +36,9 @@
#include <termios.h>
#include <pwd.h>
#if !defined(__MVS__)
#include <semaphore.h>
#endif
#include <pthread.h>
#include <signal.h>
@ -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)

4
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 ""

1
deps/uv/include/uv-win.h

@ -49,6 +49,7 @@ typedef struct pollfd {
#include <process.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/stat.h>
#if defined(_MSC_VER) && _MSC_VER < 1600

86
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;

27
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

3
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);
}

10
deps/uv/src/unix/darwin.c

@ -34,12 +34,8 @@
#include <mach-o/dyld.h> /* _NSGetExecutablePath */
#include <sys/resource.h>
#include <sys/sysctl.h>
#include <time.h>
#include <unistd.h> /* 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
}

28
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;
}

4
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 <sys/port.h>
# include <port.h>

334
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 <errno.h>
#include <stdlib.h>
#include <assert.h>
#include <search.h>
#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;
}

69
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 <dirent.h>
#include <poll.h>
#include <pthread.h>
#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_ */

823
deps/uv/src/unix/os390.c

@ -20,6 +20,628 @@
*/
#include "internal.h"
#include <sys/ioctl.h>
#include <net/if.h>
#include <utmpx.h>
#include <unistd.h>
#include <sys/ps.h>
#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 */
}

4
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);

6
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*);

3
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;

28
deps/uv/src/unix/stream.c

@ -390,7 +390,7 @@ failed_malloc:
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. */

11
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) {

12
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;

118
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);

4
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

3
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 <stdio.h>
#include <stdlib.h>

45
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;

4
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)

2
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. */

35
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 <errno.h>
#include <signal.h>
#include <stdarg.h>

3
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);

34
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' ],
}],
],

Loading…
Cancel
Save