Browse Source

deps: upgrade libuv to 1.8.0

Fixes: https://github.com/nodejs/node/issues/3718
PR-URL: https://github.com/nodejs/node/pull/4276
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
v4.x
Saúl Ibarra Corretgé 9 years ago
committed by Myles Borins
parent
commit
1ebb0c0fdf
  1. 15
      deps/uv/AUTHORS
  2. 99
      deps/uv/ChangeLog
  3. 1
      deps/uv/Makefile.am
  4. 2
      deps/uv/README.md
  5. 2
      deps/uv/appveyor.yml
  6. 1
      deps/uv/common.gypi
  7. 2
      deps/uv/configure.ac
  8. 10
      deps/uv/docs/src/fs.rst
  9. 38
      deps/uv/docs/src/misc.rst
  10. 2
      deps/uv/docs/src/tcp.rst
  11. 3
      deps/uv/gyp_uv.py
  12. 4
      deps/uv/include/uv-version.h
  13. 14
      deps/uv/include/uv.h
  14. 4
      deps/uv/src/inet.c
  15. 14
      deps/uv/src/queue.h
  16. 7
      deps/uv/src/threadpool.c
  17. 2
      deps/uv/src/unix/android-ifaddrs.c
  18. 8
      deps/uv/src/unix/async.c
  19. 5
      deps/uv/src/unix/atomic-ops.h
  20. 39
      deps/uv/src/unix/core.c
  21. 4
      deps/uv/src/unix/darwin.c
  22. 9
      deps/uv/src/unix/dl.c
  23. 6
      deps/uv/src/unix/freebsd.c
  24. 83
      deps/uv/src/unix/fs.c
  25. 43
      deps/uv/src/unix/fsevents.c
  26. 4
      deps/uv/src/unix/linux-core.c
  27. 42
      deps/uv/src/unix/linux-inotify.c
  28. 8
      deps/uv/src/unix/linux-syscalls.c
  29. 4
      deps/uv/src/unix/linux-syscalls.h
  30. 7
      deps/uv/src/unix/loop-watcher.c
  31. 4
      deps/uv/src/unix/netbsd.c
  32. 6
      deps/uv/src/unix/openbsd.c
  33. 11
      deps/uv/src/unix/process.c
  34. 2
      deps/uv/src/unix/signal.c
  35. 4
      deps/uv/src/unix/stream.c
  36. 4
      deps/uv/src/unix/sunos.c
  37. 9
      deps/uv/src/unix/tty.c
  38. 4
      deps/uv/src/unix/udp.c
  39. 27
      deps/uv/src/uv-common.c
  40. 4
      deps/uv/src/uv-common.h
  41. 1
      deps/uv/src/win/error.c
  42. 23
      deps/uv/src/win/fs-event.c
  43. 215
      deps/uv/src/win/fs.c
  44. 13
      deps/uv/src/win/getaddrinfo.c
  45. 1
      deps/uv/src/win/internal.h
  46. 8
      deps/uv/src/win/pipe.c
  47. 42
      deps/uv/src/win/snprintf.c
  48. 2
      deps/uv/src/win/tty.c
  49. 12
      deps/uv/src/win/util.c
  50. 4
      deps/uv/src/win/winapi.c
  51. 7
      deps/uv/src/win/winapi.h
  52. 10
      deps/uv/test/runner-win.h
  53. 2
      deps/uv/test/runner.c
  54. 38
      deps/uv/test/task.h
  55. 15
      deps/uv/test/test-emfile.c
  56. 28
      deps/uv/test/test-fs-event.c
  57. 142
      deps/uv/test/test-fs.c
  58. 3
      deps/uv/test/test-get-loadavg.c
  59. 6
      deps/uv/test/test-getaddrinfo.c
  60. 4
      deps/uv/test/test-getnameinfo.c
  61. 291
      deps/uv/test/test-ipc-send-recv.c
  62. 10
      deps/uv/test/test-list.h
  63. 104
      deps/uv/test/test-mutexes.c
  64. 2
      deps/uv/test/test-process-title.c
  65. 200
      deps/uv/test/test-queue-foreach-delete.c
  66. 10
      deps/uv/test/test-spawn.c
  67. 5
      deps/uv/test/test-tcp-try-write.c
  68. 2
      deps/uv/test/test-tcp-write-fail.c
  69. 3
      deps/uv/test/test-threadpool-cancel.c
  70. 3
      deps/uv/test/test-tty.c
  71. 21
      deps/uv/test/test-udp-ipv6.c
  72. 2
      deps/uv/test/test-udp-multicast-join6.c
  73. 8
      deps/uv/uv.gyp

15
deps/uv/AUTHORS

@ -225,3 +225,18 @@ Colin Snover <github.com@zetafleet.com>
Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Eli Skeggs <skeggse@gmail.com> Eli Skeggs <skeggse@gmail.com>
nmushell <nmushell@bloomberg.net> nmushell <nmushell@bloomberg.net>
Gireesh Punathil <gpunathi@in.ibm.com>
Ryan Johnston <ryan@mediapixel.co.nz>
Adam Stylinski <stylinae@mail.uc.edu>
Nathan Corvino <nathan@corvino.com>
Wink Saville <wink@saville.com>
Angel Leon <gubatron@gmail.com>
Louis DeJardin <lodejard@microsoft.com>
Imran Iqbal <imrani@ca.ibm.com>
Petka Antonov <petka_antonov@hotmail.com>
Ian Kronquist <iankronquist@teleport.com>
kkdaemon <kkdaemon@gmail.com>
Yuval Brik <yuval@brik.org.il>
Joran Dirk Greef <joran@ronomon.com>
Andrey Mazo <andrey.mazo@fidelissecurity.com>
sztomi <hello.sztomi@gmail.com>

99
deps/uv/ChangeLog

@ -1,3 +1,102 @@
2015.12.15, Version 1.8.0 (Stable), 5467299450ecf61635657557b6e01aaaf6c3fdf4
Changes since version 1.7.5:
* unix: fix memory leak in uv_interface_addresses (Jianghua Yang)
* unix: make uv_guess_handle work properly for AIX (Gireesh Punathil)
* fs: undo uv__req_init when uv__malloc failed (Jianghua Yang)
* build: remove unused 'component' GYP option (Saúl Ibarra Corretgé)
* include: remove duplicate extern declaration (Jianghua Yang)
* win: use the MSVC provided snprintf where possible (Jason Williams)
* win, test: fix compilation warning (Saúl Ibarra Corretgé)
* win: fix compilation with VS < 2012 (Ryan Johnston)
* stream: support empty uv_try_write on unix (Fedor Indutny)
* unix: fix request handle leak in uv__udp_send (Jianghua Yang)
* src: replace QUEUE_SPLIT with QUEUE_MOVE (Ben Noordhuis)
* unix: use QUEUE_MOVE when iterating over lists (Ben Noordhuis)
* unix: squelch harmless valgrind warning (Ben Noordhuis)
* test: don't abort on setrlimit() failure (Ben Noordhuis)
* unix: only undo fs req registration in async mode (Ben Noordhuis)
* unix: fix uv__getiovmax return value (HungMingWu)
* unix: make work with Solaris Studio. (Adam Stylinski)
* test: fix fs_event_watch_file_currentdir flakiness (Santiago Gimeno)
* unix: skip prohibited syscalls on tvOS and watchOS (Nathan Corvino)
* test: use FQDN in getaddrinfo_fail test (Wink Saville)
* docs: clarify documentation of uv_tcp_init_ex (Andrius Bentkus)
* win: fix comment (Miodrag Milanovic)
* doc: fix typo in README (Angel Leon)
* darwin: abort() if (un)locking fs mutex fails (Ben Noordhuis)
* pipe: enable inprocess uv_write2 on Windows (Louis DeJardin)
* win: properly return UV_EBADF when _close() fails (Nicholas Vavilov)
* test: skip process_title for AIX (Imran Iqbal)
* misc: expose handle print APIs (Petka Antonov)
* include: add stdio.h to uv.h (Saúl Ibarra Corretgé)
* misc: remove unnecessary null pointer checks (Ian Kronquist)
* test,freebsd: skip udp_dual_stack if not supported (Santiago Gimeno)
* linux: don't retry dup2/dup3 on EINTR (Ben Noordhuis)
* unix: don't retry dup2/dup3 on EINTR (Ben Noordhuis)
* test: fix -Wtautological-pointer-compare warnings (Saúl Ibarra Corretgé)
* win: map ERROR_BAD_PATHNAME to UV_ENOENT (Tony Kelman)
* test: fix test/test-tty.c for AIX (Imran Iqbal)
* android: support api level less than 21 (kkdaemon)
* fsevents: fix race on simultaneous init+close (Fedor Indutny)
* linux,fs: fix p{read,write}v with a 64bit offset (Saúl Ibarra Corretgé)
* fs: add uv_fs_realpath() (Yuval Brik)
* win: fix path for removed and renamed fs events (Joran Dirk Greef)
* win: do not read more from stream than available (Jeremy Whitlock)
* test: test that uv_close() doesn't corrupt QUEUE (Andrey Mazo)
* unix: fix uv_fs_event_stop() from fs_event_cb (Andrey Mazo)
* test: fix self-deadlocks in thread_rwlock_trylock (Ben Noordhuis)
* src: remove non ascii character (sztomi)
* test: fix test udp_multicast_join6 for AIX (Imran Iqbal)
2015.09.23, Version 1.7.5 (Stable), a8c1136de2cabf25b143021488cbaab05834daa8 2015.09.23, Version 1.7.5 (Stable), a8c1136de2cabf25b143021488cbaab05834daa8
Changes since version 1.7.4: Changes since version 1.7.4:

1
deps/uv/Makefile.am

@ -200,6 +200,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-poll-closesocket.c \ test/test-poll-closesocket.c \
test/test-poll.c \ test/test-poll.c \
test/test-process-title.c \ test/test-process-title.c \
test/test-queue-foreach-delete.c \
test/test-ref.c \ test/test-ref.c \
test/test-run-nowait.c \ test/test-run-nowait.c \
test/test-run-once.c \ test/test-run-once.c \

2
deps/uv/README.md

@ -119,7 +119,7 @@ Git tags are signed with the developer's key, they can be verified as follows:
$ git verify-tag v1.6.1 $ git verify-tag v1.6.1
Starting with libuv 1.7.0, the tarballs stored in the Starting with libuv 1.7.0, the tarballs stored in the
[downloads site](http://dist.libuv.org/dist/) are signed and an accomanying [downloads site](http://dist.libuv.org/dist/) are signed and an accompanying
signature file sit alongside each. Once both the release tarball and the signature file sit alongside each. Once both the release tarball and the
signature file are downloaded, the file can be verified as follows: signature file are downloaded, the file can be verified as follows:

2
deps/uv/appveyor.yml

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

1
deps/uv/common.gypi

@ -4,7 +4,6 @@
'target_arch%': 'ia32', # set v8's target architecture 'target_arch%': 'ia32', # set v8's target architecture
'host_arch%': 'ia32', # set v8's host architecture 'host_arch%': 'ia32', # set v8's host architecture
'uv_library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds 'uv_library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds
'component%': 'static_library', # NB. these names match with what V8 expects
'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way 'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way
}, },

2
deps/uv/configure.ac

@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57) AC_PREREQ(2.57)
AC_INIT([libuv], [1.7.5], [https://github.com/libuv/libuv/issues]) AC_INIT([libuv], [1.8.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4]) m4_include([m4/as_case.m4])

10
deps/uv/docs/src/fs.rst

@ -279,6 +279,16 @@ API
Equivalent to :man:`readlink(2)`. Equivalent to :man:`readlink(2)`.
.. c:function:: int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
Equivalent to :man:`realpath(3)` on Unix. Windows uses ``GetFinalPathNameByHandle()``.
.. note::
This function is not implemented on Windows XP and Windows Server 2003.
On these systems, UV_ENOSYS is returned.
.. versionadded:: 1.8.0
.. c:function:: int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) .. c:function:: int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
.. c:function:: int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb) .. c:function:: int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)

38
deps/uv/docs/src/misc.rst

@ -288,3 +288,41 @@ API
.. note:: .. note::
Not every platform can support nanosecond resolution; however, this value will always Not every platform can support nanosecond resolution; however, this value will always
be in nanoseconds. be in nanoseconds.
.. c:function:: void uv_print_all_handles(uv_loop_t* loop, FILE* stream)
Prints all handles associated with the given `loop` to the given `stream`.
Example:
::
uv_print_all_handles(uv_default_loop(), stderr);
/*
[--I] signal 0x1a25ea8
[-AI] async 0x1a25cf0
[R--] idle 0x1a7a8c8
*/
The format is `[flags] handle-type handle-address`. For `flags`:
- `R` is printed for a handle that is referenced
- `A` is printed for a handle that is active
- `I` is printed for a handle that is internal
.. warning::
This function is meant for ad hoc debugging, there is no API/ABI
stability guarantees.
.. versionadded:: 1.8.0
.. c:function:: void uv_print_active_handles(uv_loop_t* loop, FILE* stream)
This is the same as :c:func:`uv_print_all_handles` except only active handles
are printed.
.. warning::
This function is meant for ad hoc debugging, there is no API/ABI
stability guarantees.
.. versionadded:: 1.8.0

2
deps/uv/docs/src/tcp.rst

@ -34,7 +34,7 @@ API
.. c:function:: int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) .. c:function:: int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags)
Initialize the handle with the specified flags. At the moment the lower 8 bits Initialize the handle with the specified flags. At the moment only the lower 8 bits
of the `flags` parameter are used as the socket domain. A socket will be created of the `flags` parameter are used as the socket domain. A socket will be created
for the given domain. If the specified domain is ``AF_UNSPEC`` no socket is created, for the given domain. If the specified domain is ``AF_UNSPEC`` no socket is created,
just like :c:func:`uv_tcp_init`. just like :c:func:`uv_tcp_init`.

3
deps/uv/gyp_uv.py

@ -83,9 +83,6 @@ if __name__ == '__main__':
if not any(a.startswith('-Duv_library=') for a in args): if not any(a.startswith('-Duv_library=') for a in args):
args.append('-Duv_library=static_library') args.append('-Duv_library=static_library')
if not any(a.startswith('-Dcomponent=') for a in args):
args.append('-Dcomponent=static_library')
# Some platforms (OpenBSD for example) don't have multiprocessing.synchronize # Some platforms (OpenBSD for example) don't have multiprocessing.synchronize
# so gyp must be run with --no-parallel # so gyp must be run with --no-parallel
if not gyp_parallel_support: if not gyp_parallel_support:

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

@ -31,8 +31,8 @@
*/ */
#define UV_VERSION_MAJOR 1 #define UV_VERSION_MAJOR 1
#define UV_VERSION_MINOR 7 #define UV_VERSION_MINOR 8
#define UV_VERSION_PATCH 5 #define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX "" #define UV_VERSION_SUFFIX ""

14
deps/uv/include/uv.h

@ -48,6 +48,7 @@ extern "C" {
#include "uv-errno.h" #include "uv-errno.h"
#include "uv-version.h" #include "uv-version.h"
#include <stddef.h> #include <stddef.h>
#include <stdio.h>
#if defined(_MSC_VER) && _MSC_VER < 1600 #if defined(_MSC_VER) && _MSC_VER < 1600
# include "stdint-msvc2008.h" # include "stdint-msvc2008.h"
@ -424,6 +425,10 @@ UV_EXTERN int uv_is_active(const uv_handle_t* handle);
UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg); UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg);
/* Helpers for ad hoc debugging, no API/ABI stability guaranteed. */
UV_EXTERN void uv_print_all_handles(uv_loop_t* loop, FILE* stream);
UV_EXTERN void uv_print_active_handles(uv_loop_t* loop, FILE* stream);
UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb); UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
UV_EXTERN int uv_send_buffer_size(uv_handle_t* handle, int* value); UV_EXTERN int uv_send_buffer_size(uv_handle_t* handle, int* value);
@ -1083,7 +1088,8 @@ typedef enum {
UV_FS_SYMLINK, UV_FS_SYMLINK,
UV_FS_READLINK, UV_FS_READLINK,
UV_FS_CHOWN, UV_FS_CHOWN,
UV_FS_FCHOWN UV_FS_FCHOWN,
UV_FS_REALPATH
} uv_fs_type; } uv_fs_type;
/* uv_fs_t is a subclass of uv_req_t. */ /* uv_fs_t is a subclass of uv_req_t. */
@ -1235,6 +1241,10 @@ UV_EXTERN int uv_fs_readlink(uv_loop_t* loop,
uv_fs_t* req, uv_fs_t* req,
const char* path, const char* path,
uv_fs_cb cb); uv_fs_cb cb);
UV_EXTERN int uv_fs_realpath(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
uv_fs_cb cb);
UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop, UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop,
uv_fs_t* req, uv_fs_t* req,
uv_file file, uv_file file,
@ -1363,7 +1373,7 @@ UV_EXTERN int uv_chdir(const char* dir);
UV_EXTERN uint64_t uv_get_free_memory(void); UV_EXTERN uint64_t uv_get_free_memory(void);
UV_EXTERN uint64_t uv_get_total_memory(void); UV_EXTERN uint64_t uv_get_total_memory(void);
UV_EXTERN extern uint64_t uv_hrtime(void); UV_EXTERN uint64_t uv_hrtime(void);
UV_EXTERN void uv_disable_stdio_inheritance(void); UV_EXTERN void uv_disable_stdio_inheritance(void);

4
deps/uv/src/inet.c

@ -55,11 +55,7 @@ static int inet_ntop4(const unsigned char *src, char *dst, size_t size) {
char tmp[UV__INET_ADDRSTRLEN]; char tmp[UV__INET_ADDRSTRLEN];
int l; int l;
#ifndef _WIN32
l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]); l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
#else
l = _snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
#endif
if (l <= 0 || (size_t) l >= size) { if (l <= 0 || (size_t) l >= size) {
return UV_ENOSPC; return UV_ENOSPC;
} }

14
deps/uv/src/queue.h

@ -30,6 +30,9 @@ typedef void *QUEUE[2];
#define QUEUE_DATA(ptr, type, field) \ #define QUEUE_DATA(ptr, type, field) \
((type *) ((char *) (ptr) - offsetof(type, field))) ((type *) ((char *) (ptr) - offsetof(type, field)))
/* Important note: mutating the list while QUEUE_FOREACH is
* iterating over its elements results in undefined behavior.
*/
#define QUEUE_FOREACH(q, h) \ #define QUEUE_FOREACH(q, h) \
for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q)) for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q))
@ -66,6 +69,17 @@ typedef void *QUEUE[2];
} \ } \
while (0) while (0)
#define QUEUE_MOVE(h, n) \
do { \
if (QUEUE_EMPTY(h)) \
QUEUE_INIT(n); \
else { \
QUEUE* q = QUEUE_HEAD(h); \
QUEUE_SPLIT(h, q, n); \
} \
} \
while (0)
#define QUEUE_INSERT_HEAD(h, q) \ #define QUEUE_INSERT_HEAD(h, q) \
do { \ do { \
QUEUE_NEXT(q) = QUEUE_NEXT(h); \ QUEUE_NEXT(q) = QUEUE_NEXT(h); \

7
deps/uv/src/threadpool.c

@ -223,13 +223,8 @@ void uv__work_done(uv_async_t* handle) {
int err; int err;
loop = container_of(handle, uv_loop_t, wq_async); loop = container_of(handle, uv_loop_t, wq_async);
QUEUE_INIT(&wq);
uv_mutex_lock(&loop->wq_mutex); uv_mutex_lock(&loop->wq_mutex);
if (!QUEUE_EMPTY(&loop->wq)) { QUEUE_MOVE(&loop->wq, &wq);
q = QUEUE_HEAD(&loop->wq);
QUEUE_SPLIT(&loop->wq, q, &wq);
}
uv_mutex_unlock(&loop->wq_mutex); uv_mutex_unlock(&loop->wq_mutex);
while (!QUEUE_EMPTY(&wq)) { while (!QUEUE_EMPTY(&wq)) {

2
deps/uv/src/unix/android-ifaddrs.c

@ -1,6 +1,6 @@
/* /*
Copyright (c) 2013, Kenneth MacKay Copyright (c) 2013, Kenneth MacKay
Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement n° 289016) Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement #289016)
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,

8
deps/uv/src/unix/async.c

@ -78,12 +78,18 @@ void uv__async_close(uv_async_t* handle) {
static void uv__async_event(uv_loop_t* loop, static void uv__async_event(uv_loop_t* loop,
struct uv__async* w, struct uv__async* w,
unsigned int nevents) { unsigned int nevents) {
QUEUE queue;
QUEUE* q; QUEUE* q;
uv_async_t* h; uv_async_t* h;
QUEUE_FOREACH(q, &loop->async_handles) { QUEUE_MOVE(&loop->async_handles, &queue);
while (!QUEUE_EMPTY(&queue)) {
q = QUEUE_HEAD(&queue);
h = QUEUE_DATA(q, uv_async_t, queue); h = QUEUE_DATA(q, uv_async_t, queue);
QUEUE_REMOVE(q);
QUEUE_INSERT_TAIL(&loop->async_handles, q);
if (cmpxchgi(&h->pending, 1, 0) == 0) if (cmpxchgi(&h->pending, 1, 0) == 0)
continue; continue;

5
deps/uv/src/unix/atomic-ops.h

@ -18,6 +18,11 @@
#include "internal.h" /* UV_UNUSED */ #include "internal.h" /* UV_UNUSED */
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
#include <atomic.h>
#define __sync_val_compare_and_swap(p, o, n) atomic_cas_ptr(p, o, n)
#endif
UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)); UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval));
UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)); UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval));
UV_UNUSED(static void cpu_relax(void)); UV_UNUSED(static void cpu_relax(void));

39
deps/uv/src/unix/core.c

@ -75,6 +75,10 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#endif #endif
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
# include <dlfcn.h> /* for dlsym */
#endif
static int uv__run_pending(uv_loop_t* loop); static int uv__run_pending(uv_loop_t* loop);
/* Verify that uv_buf_t is ABI-compatible with struct iovec. */ /* Verify that uv_buf_t is ABI-compatible with struct iovec. */
@ -204,8 +208,14 @@ int uv__getiovmax(void) {
return IOV_MAX; return IOV_MAX;
#elif defined(_SC_IOV_MAX) #elif defined(_SC_IOV_MAX)
static int iovmax = -1; static int iovmax = -1;
if (iovmax == -1) if (iovmax == -1) {
iovmax = sysconf(_SC_IOV_MAX); iovmax = sysconf(_SC_IOV_MAX);
/* On some embedded devices (arm-linux-uclibc based ip camera),
* sysconf(_SC_IOV_MAX) can not get the correct value. The return
* value is -1 and the errno is EINPROGRESS. Degrade the value to 1.
*/
if (iovmax == -1) iovmax = 1;
}
return iovmax; return iovmax;
#else #else
return 1024; return 1024;
@ -721,9 +731,7 @@ static int uv__run_pending(uv_loop_t* loop) {
if (QUEUE_EMPTY(&loop->pending_queue)) if (QUEUE_EMPTY(&loop->pending_queue))
return 0; return 0;
QUEUE_INIT(&pq); QUEUE_MOVE(&loop->pending_queue, &pq);
q = QUEUE_HEAD(&loop->pending_queue);
QUEUE_SPLIT(&loop->pending_queue, q, &pq);
while (!QUEUE_EMPTY(&pq)) { while (!QUEUE_EMPTY(&pq)) {
q = QUEUE_HEAD(&pq); q = QUEUE_HEAD(&pq);
@ -956,16 +964,12 @@ int uv__open_cloexec(const char* path, int flags) {
int uv__dup2_cloexec(int oldfd, int newfd) { int uv__dup2_cloexec(int oldfd, int newfd) {
int r; int r;
#if defined(__FreeBSD__) && __FreeBSD__ >= 10 #if defined(__FreeBSD__) && __FreeBSD__ >= 10
do r = dup3(oldfd, newfd, O_CLOEXEC);
r = dup3(oldfd, newfd, O_CLOEXEC);
while (r == -1 && errno == EINTR);
if (r == -1) if (r == -1)
return -errno; return -errno;
return r; return r;
#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC) #elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC)
do r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
while (r == -1 && errno == EINTR);
if (r != -1) if (r != -1)
return r; return r;
if (errno != EINVAL) if (errno != EINVAL)
@ -976,7 +980,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
if (!no_dup3) { if (!no_dup3) {
do do
r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC); r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC);
while (r == -1 && (errno == EINTR || errno == EBUSY)); while (r == -1 && errno == EBUSY);
if (r != -1) if (r != -1)
return r; return r;
if (errno != ENOSYS) if (errno != ENOSYS)
@ -990,9 +994,9 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
do do
r = dup2(oldfd, newfd); r = dup2(oldfd, newfd);
#if defined(__linux__) #if defined(__linux__)
while (r == -1 && (errno == EINTR || errno == EBUSY)); while (r == -1 && errno == EBUSY);
#else #else
while (r == -1 && errno == EINTR); while (0); /* Never retry. */
#endif #endif
if (r == -1) if (r == -1)
@ -1018,6 +1022,9 @@ int uv_os_homedir(char* buffer, size_t* size) {
size_t len; size_t len;
long initsize; long initsize;
int r; int r;
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**);
#endif
if (buffer == NULL || size == NULL || *size == 0) if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL; return -EINVAL;
@ -1039,6 +1046,12 @@ int uv_os_homedir(char* buffer, size_t* size) {
return 0; return 0;
} }
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r");
if (getpwuid_r == NULL)
return -ENOSYS;
#endif
/* HOME is not set, so call getpwuid() */ /* HOME is not set, so call getpwuid() */
initsize = sysconf(_SC_GETPW_R_SIZE_MAX); initsize = sysconf(_SC_GETPW_R_SIZE_MAX);

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

@ -258,8 +258,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
} }
*addresses = uv__malloc(*count * sizeof(**addresses)); *addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) if (!(*addresses)) {
freeifaddrs(addrs);
return -ENOMEM; return -ENOMEM;
}
address = *addresses; address = *addresses;

9
deps/uv/src/unix/dl.c

@ -39,10 +39,8 @@ int uv_dlopen(const char* filename, uv_lib_t* lib) {
void uv_dlclose(uv_lib_t* lib) { void uv_dlclose(uv_lib_t* lib) {
if (lib->errmsg) { uv__free(lib->errmsg);
uv__free(lib->errmsg); lib->errmsg = NULL;
lib->errmsg = NULL;
}
if (lib->handle) { if (lib->handle) {
/* Ignore errors. No good way to signal them without leaking memory. */ /* Ignore errors. No good way to signal them without leaking memory. */
@ -67,8 +65,7 @@ const char* uv_dlerror(const uv_lib_t* lib) {
static int uv__dlerror(uv_lib_t* lib) { static int uv__dlerror(uv_lib_t* lib) {
const char* errmsg; const char* errmsg;
if (lib->errmsg) uv__free(lib->errmsg);
uv__free(lib->errmsg);
errmsg = dlerror(); errmsg = dlerror();

6
deps/uv/src/unix/freebsd.c

@ -176,7 +176,7 @@ char** uv_setup_args(int argc, char** argv) {
int uv_set_process_title(const char* title) { int uv_set_process_title(const char* title) {
int oid[4]; int oid[4];
if (process_title) uv__free(process_title); uv__free(process_title);
process_title = uv__strdup(title); process_title = uv__strdup(title);
oid[0] = CTL_KERN; oid[0] = CTL_KERN;
@ -373,8 +373,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
} }
*addresses = uv__malloc(*count * sizeof(**addresses)); *addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) if (!(*addresses)) {
freeifaddrs(addrs);
return -ENOMEM; return -ENOMEM;
}
address = *addresses; address = *addresses;

83
deps/uv/src/unix/fs.c

@ -80,8 +80,10 @@
req->path = path; \ req->path = path; \
} else { \ } else { \
req->path = uv__strdup(path); \ req->path = uv__strdup(path); \
if (req->path == NULL) \ if (req->path == NULL) { \
uv__req_unregister(loop, req); \
return -ENOMEM; \ return -ENOMEM; \
} \
} \ } \
} \ } \
while (0) while (0)
@ -97,8 +99,10 @@
path_len = strlen(path) + 1; \ path_len = strlen(path) + 1; \
new_path_len = strlen(new_path) + 1; \ new_path_len = strlen(new_path) + 1; \
req->path = uv__malloc(path_len + new_path_len); \ req->path = uv__malloc(path_len + new_path_len); \
if (req->path == NULL) \ if (req->path == NULL) { \
uv__req_unregister(loop, req); \
return -ENOMEM; \ return -ENOMEM; \
} \
req->new_path = req->path + path_len; \ req->new_path = req->path + path_len; \
memcpy((void*) req->path, path, path_len); \ memcpy((void*) req->path, path, path_len); \
memcpy((void*) req->new_path, new_path, new_path_len); \ memcpy((void*) req->new_path, new_path, new_path_len); \
@ -370,20 +374,27 @@ out:
} }
static ssize_t uv__fs_readlink(uv_fs_t* req) { static ssize_t uv__fs_pathmax_size(const char* path) {
ssize_t len; ssize_t pathmax;
char* buf;
len = pathconf(req->path, _PC_PATH_MAX); pathmax = pathconf(path, _PC_PATH_MAX);
if (len == -1) { if (pathmax == -1) {
#if defined(PATH_MAX) #if defined(PATH_MAX)
len = PATH_MAX; return PATH_MAX;
#else #else
len = 4096; return 4096;
#endif #endif
} }
return pathmax;
}
static ssize_t uv__fs_readlink(uv_fs_t* req) {
ssize_t len;
char* buf;
len = uv__fs_pathmax_size(req->path);
buf = uv__malloc(len + 1); buf = uv__malloc(len + 1);
if (buf == NULL) { if (buf == NULL) {
@ -404,6 +415,27 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
return 0; return 0;
} }
static ssize_t uv__fs_realpath(uv_fs_t* req) {
ssize_t len;
char* buf;
len = uv__fs_pathmax_size(req->path);
buf = uv__malloc(len + 1);
if (buf == NULL) {
errno = ENOMEM;
return -1;
}
if (realpath(req->path, buf) == NULL) {
uv__free(buf);
return -1;
}
req->ptr = buf;
return 0;
}
static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) { static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
struct pollfd pfd; struct pollfd pfd;
@ -626,7 +658,9 @@ static ssize_t uv__fs_write(uv_fs_t* req) {
*/ */
#if defined(__APPLE__) #if defined(__APPLE__)
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&lock);
if (pthread_mutex_lock(&lock))
abort();
#endif #endif
if (req->off < 0) { if (req->off < 0) {
@ -683,7 +717,8 @@ static ssize_t uv__fs_write(uv_fs_t* req) {
done: done:
#if defined(__APPLE__) #if defined(__APPLE__)
pthread_mutex_unlock(&lock); if (pthread_mutex_unlock(&lock))
abort();
#endif #endif
return r; return r;
@ -867,6 +902,7 @@ static void uv__fs_work(struct uv__work* w) {
X(READ, uv__fs_buf_iter(req, uv__fs_read)); X(READ, uv__fs_buf_iter(req, uv__fs_read));
X(SCANDIR, uv__fs_scandir(req)); X(SCANDIR, uv__fs_scandir(req));
X(READLINK, uv__fs_readlink(req)); X(READLINK, uv__fs_readlink(req));
X(REALPATH, uv__fs_realpath(req));
X(RENAME, rename(req->path, req->new_path)); X(RENAME, rename(req->path, req->new_path));
X(RMDIR, rmdir(req->path)); X(RMDIR, rmdir(req->path));
X(SENDFILE, uv__fs_sendfile(req)); X(SENDFILE, uv__fs_sendfile(req));
@ -1062,8 +1098,11 @@ int uv_fs_mkdtemp(uv_loop_t* loop,
uv_fs_cb cb) { uv_fs_cb cb) {
INIT(MKDTEMP); INIT(MKDTEMP);
req->path = uv__strdup(tpl); req->path = uv__strdup(tpl);
if (req->path == NULL) if (req->path == NULL) {
if (cb != NULL)
uv__req_unregister(loop, req);
return -ENOMEM; return -ENOMEM;
}
POST; POST;
} }
@ -1099,8 +1138,11 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
if (nbufs > ARRAY_SIZE(req->bufsml)) if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(*bufs)); req->bufs = uv__malloc(nbufs * sizeof(*bufs));
if (req->bufs == NULL) if (req->bufs == NULL) {
if (cb != NULL)
uv__req_unregister(loop, req);
return -ENOMEM; return -ENOMEM;
}
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
@ -1131,6 +1173,16 @@ int uv_fs_readlink(uv_loop_t* loop,
} }
int uv_fs_realpath(uv_loop_t* loop,
uv_fs_t* req,
const char * path,
uv_fs_cb cb) {
INIT(REALPATH);
PATH;
POST;
}
int uv_fs_rename(uv_loop_t* loop, int uv_fs_rename(uv_loop_t* loop,
uv_fs_t* req, uv_fs_t* req,
const char* path, const char* path,
@ -1224,8 +1276,11 @@ int uv_fs_write(uv_loop_t* loop,
if (nbufs > ARRAY_SIZE(req->bufsml)) if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(*bufs)); req->bufs = uv__malloc(nbufs * sizeof(*bufs));
if (req->bufs == NULL) if (req->bufs == NULL) {
if (cb != NULL)
uv__req_unregister(loop, req);
return -ENOMEM; return -ENOMEM;
}
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs)); memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));

43
deps/uv/src/unix/fsevents.c

@ -73,9 +73,16 @@ typedef struct uv__fsevents_event_s uv__fsevents_event_t;
typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t; typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t;
typedef struct uv__cf_loop_state_s uv__cf_loop_state_t; typedef struct uv__cf_loop_state_s uv__cf_loop_state_t;
enum uv__cf_loop_signal_type_e {
kUVCFLoopSignalRegular,
kUVCFLoopSignalClosing
};
typedef enum uv__cf_loop_signal_type_e uv__cf_loop_signal_type_t;
struct uv__cf_loop_signal_s { struct uv__cf_loop_signal_s {
QUEUE member; QUEUE member;
uv_fs_event_t* handle; uv_fs_event_t* handle;
uv__cf_loop_signal_type_t type;
}; };
struct uv__fsevents_event_s { struct uv__fsevents_event_s {
@ -98,7 +105,9 @@ struct uv__cf_loop_state_s {
/* Forward declarations */ /* Forward declarations */
static void uv__cf_loop_cb(void* arg); static void uv__cf_loop_cb(void* arg);
static void* uv__cf_loop_runner(void* arg); static void* uv__cf_loop_runner(void* arg);
static int uv__cf_loop_signal(uv_loop_t* loop, uv_fs_event_t* handle); static int uv__cf_loop_signal(uv_loop_t* loop,
uv_fs_event_t* handle,
uv__cf_loop_signal_type_t type);
/* Lazy-loaded by uv__fsevents_global_init(). */ /* Lazy-loaded by uv__fsevents_global_init(). */
static CFArrayRef (*pCFArrayCreate)(CFAllocatorRef, static CFArrayRef (*pCFArrayCreate)(CFAllocatorRef,
@ -149,11 +158,7 @@ static void (*pFSEventStreamStop)(FSEventStreamRef);
int err; \ int err; \
uv_mutex_lock(&(handle)->cf_mutex); \ uv_mutex_lock(&(handle)->cf_mutex); \
/* Split-off all events and empty original queue */ \ /* Split-off all events and empty original queue */ \
QUEUE_INIT(&events); \ QUEUE_MOVE(&(handle)->cf_events, &events); \
if (!QUEUE_EMPTY(&(handle)->cf_events)) { \
q = QUEUE_HEAD(&(handle)->cf_events); \
QUEUE_SPLIT(&(handle)->cf_events, q, &events); \
} \
/* Get error (if any) and zero original one */ \ /* Get error (if any) and zero original one */ \
err = (handle)->cf_error; \ err = (handle)->cf_error; \
(handle)->cf_error = 0; \ (handle)->cf_error = 0; \
@ -387,7 +392,8 @@ static void uv__fsevents_destroy_stream(uv_loop_t* loop) {
/* Runs in CF thread, when there're new fsevent handles to add to stream */ /* Runs in CF thread, when there're new fsevent handles to add to stream */
static void uv__fsevents_reschedule(uv_fs_event_t* handle) { static void uv__fsevents_reschedule(uv_fs_event_t* handle,
uv__cf_loop_signal_type_t type) {
uv__cf_loop_state_t* state; uv__cf_loop_state_t* state;
QUEUE* q; QUEUE* q;
uv_fs_event_t* curr; uv_fs_event_t* curr;
@ -486,7 +492,7 @@ final:
* *
* NOTE: This is coupled with `uv_sem_wait()` in `uv__fsevents_close` * NOTE: This is coupled with `uv_sem_wait()` in `uv__fsevents_close`
*/ */
if (!uv__is_active(handle)) if (type == kUVCFLoopSignalClosing)
uv_sem_post(&state->fsevent_sem); uv_sem_post(&state->fsevent_sem);
} }
@ -676,7 +682,7 @@ void uv__fsevents_loop_delete(uv_loop_t* loop) {
if (loop->cf_state == NULL) if (loop->cf_state == NULL)
return; return;
if (uv__cf_loop_signal(loop, NULL) != 0) if (uv__cf_loop_signal(loop, NULL, kUVCFLoopSignalRegular) != 0)
abort(); abort();
uv_thread_join(&loop->cf_thread); uv_thread_join(&loop->cf_thread);
@ -735,17 +741,14 @@ static void uv__cf_loop_cb(void* arg) {
loop = arg; loop = arg;
state = loop->cf_state; state = loop->cf_state;
QUEUE_INIT(&split_head);
uv_mutex_lock(&loop->cf_mutex); uv_mutex_lock(&loop->cf_mutex);
if (!QUEUE_EMPTY(&loop->cf_signals)) { QUEUE_MOVE(&loop->cf_signals, &split_head);
QUEUE* split_pos = QUEUE_HEAD(&loop->cf_signals);
QUEUE_SPLIT(&loop->cf_signals, split_pos, &split_head);
}
uv_mutex_unlock(&loop->cf_mutex); uv_mutex_unlock(&loop->cf_mutex);
while (!QUEUE_EMPTY(&split_head)) { while (!QUEUE_EMPTY(&split_head)) {
item = QUEUE_HEAD(&split_head); item = QUEUE_HEAD(&split_head);
QUEUE_REMOVE(item);
s = QUEUE_DATA(item, uv__cf_loop_signal_t, member); s = QUEUE_DATA(item, uv__cf_loop_signal_t, member);
@ -753,16 +756,17 @@ static void uv__cf_loop_cb(void* arg) {
if (s->handle == NULL) if (s->handle == NULL)
pCFRunLoopStop(state->loop); pCFRunLoopStop(state->loop);
else else
uv__fsevents_reschedule(s->handle); uv__fsevents_reschedule(s->handle, s->type);
QUEUE_REMOVE(item);
uv__free(s); uv__free(s);
} }
} }
/* Runs in UV loop to notify CF thread */ /* Runs in UV loop to notify CF thread */
int uv__cf_loop_signal(uv_loop_t* loop, uv_fs_event_t* handle) { int uv__cf_loop_signal(uv_loop_t* loop,
uv_fs_event_t* handle,
uv__cf_loop_signal_type_t type) {
uv__cf_loop_signal_t* item; uv__cf_loop_signal_t* item;
uv__cf_loop_state_t* state; uv__cf_loop_state_t* state;
@ -771,6 +775,7 @@ int uv__cf_loop_signal(uv_loop_t* loop, uv_fs_event_t* handle) {
return -ENOMEM; return -ENOMEM;
item->handle = handle; item->handle = handle;
item->type = type;
uv_mutex_lock(&loop->cf_mutex); uv_mutex_lock(&loop->cf_mutex);
QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member); QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member);
@ -833,7 +838,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
/* Reschedule FSEventStream */ /* Reschedule FSEventStream */
assert(handle != NULL); assert(handle != NULL);
err = uv__cf_loop_signal(handle->loop, handle); err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalRegular);
if (err) if (err)
goto fail_loop_signal; goto fail_loop_signal;
@ -873,7 +878,7 @@ int uv__fsevents_close(uv_fs_event_t* handle) {
/* Reschedule FSEventStream */ /* Reschedule FSEventStream */
assert(handle != NULL); assert(handle != NULL);
err = uv__cf_loop_signal(handle->loop, handle); err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalClosing);
if (err) if (err)
return -err; return -err;

4
deps/uv/src/unix/linux-core.c

@ -814,8 +814,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
return 0; return 0;
*addresses = uv__malloc(*count * sizeof(**addresses)); *addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) if (!(*addresses)) {
freeifaddrs(addrs);
return -ENOMEM; return -ENOMEM;
}
address = *addresses; address = *addresses;

42
deps/uv/src/unix/linux-inotify.c

@ -35,6 +35,7 @@
struct watcher_list { struct watcher_list {
RB_ENTRY(watcher_list) entry; RB_ENTRY(watcher_list) entry;
QUEUE watchers; QUEUE watchers;
int iterating;
char* path; char* path;
int wd; int wd;
}; };
@ -113,6 +114,15 @@ static struct watcher_list* find_watcher(uv_loop_t* loop, int wd) {
return RB_FIND(watcher_root, CAST(&loop->inotify_watchers), &w); return RB_FIND(watcher_root, CAST(&loop->inotify_watchers), &w);
} }
static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) {
/* if the watcher_list->watchers is being iterated over, we can't free it. */
if ((!w->iterating) && QUEUE_EMPTY(&w->watchers)) {
/* No watchers left for this path. Clean up. */
RB_REMOVE(watcher_root, CAST(&loop->inotify_watchers), w);
uv__inotify_rm_watch(loop->inotify_fd, w->wd);
uv__free(w);
}
}
static void uv__inotify_read(uv_loop_t* loop, static void uv__inotify_read(uv_loop_t* loop,
uv__io_t* dummy, uv__io_t* dummy,
@ -120,6 +130,7 @@ static void uv__inotify_read(uv_loop_t* loop,
const struct uv__inotify_event* e; const struct uv__inotify_event* e;
struct watcher_list* w; struct watcher_list* w;
uv_fs_event_t* h; uv_fs_event_t* h;
QUEUE queue;
QUEUE* q; QUEUE* q;
const char* path; const char* path;
ssize_t size; ssize_t size;
@ -159,10 +170,31 @@ static void uv__inotify_read(uv_loop_t* loop,
*/ */
path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path); path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path);
QUEUE_FOREACH(q, &w->watchers) { /* We're about to iterate over the queue and call user's callbacks.
* What can go wrong?
* A callback could call uv_fs_event_stop()
* and the queue can change under our feet.
* So, we use QUEUE_MOVE() trick to safely iterate over the queue.
* And we don't free the watcher_list until we're done iterating.
*
* First,
* tell uv_fs_event_stop() (that could be called from a user's callback)
* not to free watcher_list.
*/
w->iterating = 1;
QUEUE_MOVE(&w->watchers, &queue);
while (!QUEUE_EMPTY(&queue)) {
q = QUEUE_HEAD(&queue);
h = QUEUE_DATA(q, uv_fs_event_t, watchers); h = QUEUE_DATA(q, uv_fs_event_t, watchers);
QUEUE_REMOVE(q);
QUEUE_INSERT_TAIL(&w->watchers, q);
h->cb(h, path, events, 0); h->cb(h, path, events, 0);
} }
/* done iterating, time to (maybe) free empty watcher_list */
w->iterating = 0;
maybe_free_watcher_list(w, loop);
} }
} }
} }
@ -214,6 +246,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
w->wd = wd; w->wd = wd;
w->path = strcpy((char*)(w + 1), path); w->path = strcpy((char*)(w + 1), path);
QUEUE_INIT(&w->watchers); QUEUE_INIT(&w->watchers);
w->iterating = 0;
RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w); RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w);
no_insert: no_insert:
@ -241,12 +274,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
uv__handle_stop(handle); uv__handle_stop(handle);
QUEUE_REMOVE(&handle->watchers); QUEUE_REMOVE(&handle->watchers);
if (QUEUE_EMPTY(&w->watchers)) { maybe_free_watcher_list(w, handle->loop);
/* No watchers left for this path. Clean up. */
RB_REMOVE(watcher_root, CAST(&handle->loop->inotify_watchers), w);
uv__inotify_rm_watch(handle->loop->inotify_fd, w->wd);
uv__free(w);
}
return 0; return 0;
} }

8
deps/uv/src/unix/linux-syscalls.c

@ -444,18 +444,18 @@ int uv__utimesat(int dirfd,
} }
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) { ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {
#if defined(__NR_preadv) #if defined(__NR_preadv)
return syscall(__NR_preadv, fd, iov, iovcnt, offset); return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
#else #else
return errno = ENOSYS, -1; return errno = ENOSYS, -1;
#endif #endif
} }
ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) { ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {
#if defined(__NR_pwritev) #if defined(__NR_pwritev)
return syscall(__NR_pwritev, fd, iov, iovcnt, offset); return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
#else #else
return errno = ENOSYS, -1; return errno = ENOSYS, -1;
#endif #endif

4
deps/uv/src/unix/linux-syscalls.h

@ -151,8 +151,8 @@ int uv__utimesat(int dirfd,
const char* path, const char* path,
const struct timespec times[2], const struct timespec times[2],
int flags); int flags);
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset); ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset); ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
int uv__dup3(int oldfd, int newfd, int flags); int uv__dup3(int oldfd, int newfd, int flags);
#endif /* UV_LINUX_SYSCALL_H_ */ #endif /* UV_LINUX_SYSCALL_H_ */

7
deps/uv/src/unix/loop-watcher.c

@ -47,9 +47,14 @@
\ \
void uv__run_##name(uv_loop_t* loop) { \ void uv__run_##name(uv_loop_t* loop) { \
uv_##name##_t* h; \ uv_##name##_t* h; \
QUEUE queue; \
QUEUE* q; \ QUEUE* q; \
QUEUE_FOREACH(q, &loop->name##_handles) { \ QUEUE_MOVE(&loop->name##_handles, &queue); \
while (!QUEUE_EMPTY(&queue)) { \
q = QUEUE_HEAD(&queue); \
h = QUEUE_DATA(q, uv_##name##_t, queue); \ h = QUEUE_DATA(q, uv_##name##_t, queue); \
QUEUE_REMOVE(q); \
QUEUE_INSERT_TAIL(&loop->name##_handles, q); \
h->name##_cb(h); \ h->name##_cb(h); \
} \ } \
} \ } \

4
deps/uv/src/unix/netbsd.c

@ -298,8 +298,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
*addresses = uv__malloc(*count * sizeof(**addresses)); *addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) if (!(*addresses)) {
freeifaddrs(addrs);
return -ENOMEM; return -ENOMEM;
}
address = *addresses; address = *addresses;

6
deps/uv/src/unix/openbsd.c

@ -161,7 +161,7 @@ char** uv_setup_args(int argc, char** argv) {
int uv_set_process_title(const char* title) { int uv_set_process_title(const char* title) {
if (process_title) uv__free(process_title); uv__free(process_title);
process_title = uv__strdup(title); process_title = uv__strdup(title);
setproctitle(title); setproctitle(title);
return 0; return 0;
@ -313,8 +313,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
*addresses = uv__malloc(*count * sizeof(**addresses)); *addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) if (!(*addresses)) {
freeifaddrs(addrs);
return -ENOMEM; return -ENOMEM;
}
address = *addresses; address = *addresses;

11
deps/uv/src/unix/process.c

@ -270,6 +270,11 @@ static void uv__write_int(int fd, int val) {
} }
#if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH))
/* execvp is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED, so must be
* avoided. Since this isn't called on those targets, the function
* doesn't even need to be defined for them.
*/
static void uv__process_child_init(const uv_process_options_t* options, static void uv__process_child_init(const uv_process_options_t* options,
int stdio_count, int stdio_count,
int (*pipes)[2], int (*pipes)[2],
@ -375,11 +380,16 @@ static void uv__process_child_init(const uv_process_options_t* options,
uv__write_int(error_fd, -errno); uv__write_int(error_fd, -errno);
_exit(127); _exit(127);
} }
#endif
int uv_spawn(uv_loop_t* loop, int uv_spawn(uv_loop_t* loop,
uv_process_t* process, uv_process_t* process,
const uv_process_options_t* options) { const uv_process_options_t* options) {
#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
/* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
return -ENOSYS;
#else
int signal_pipe[2] = { -1, -1 }; int signal_pipe[2] = { -1, -1 };
int (*pipes)[2]; int (*pipes)[2];
int stdio_count; int stdio_count;
@ -528,6 +538,7 @@ error:
} }
return err; return err;
#endif
} }

2
deps/uv/src/unix/signal.c

@ -234,6 +234,8 @@ void uv__signal_loop_cleanup(uv_loop_t* loop) {
/* Stop all the signal watchers that are still attached to this loop. This /* Stop all the signal watchers that are still attached to this loop. This
* ensures that the (shared) signal tree doesn't contain any invalid entries * ensures that the (shared) signal tree doesn't contain any invalid entries
* entries, and that signal handlers are removed when appropriate. * entries, and that signal handlers are removed when appropriate.
* It's safe to use QUEUE_FOREACH here because the handles and the handle
* queue are not modified by uv__signal_stop().
*/ */
QUEUE_FOREACH(q, &loop->handle_queue) { QUEUE_FOREACH(q, &loop->handle_queue) {
uv_handle_t* handle = QUEUE_DATA(q, uv_handle_t, handle_queue); uv_handle_t* handle = QUEUE_DATA(q, uv_handle_t, handle_queue);

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

@ -779,9 +779,9 @@ start:
if (req->send_handle) { if (req->send_handle) {
struct msghdr msg; struct msghdr msg;
char scratch[64];
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
int fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle); int fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);
char scratch[64] = {0};
assert(fd_to_send >= 0); assert(fd_to_send >= 0);
@ -1471,7 +1471,7 @@ int uv_try_write(uv_stream_t* stream,
uv__stream_osx_interrupt_select(stream); uv__stream_osx_interrupt_select(stream);
} }
if (written == 0) if (written == 0 && req_size != 0)
return -EAGAIN; return -EAGAIN;
else else
return written; return written;

4
deps/uv/src/unix/sunos.c

@ -693,8 +693,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
} }
*addresses = uv__malloc(*count * sizeof(**addresses)); *addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) if (!(*addresses)) {
freeifaddrs(addrs);
return -ENOMEM; return -ENOMEM;
}
address = *addresses; address = *addresses;

9
deps/uv/src/unix/tty.c

@ -236,6 +236,15 @@ uv_handle_type uv_guess_handle(uv_file file) {
return UV_UDP; return UV_UDP;
if (type == SOCK_STREAM) { if (type == SOCK_STREAM) {
#if defined(_AIX)
/* on AIX the getsockname call returns an empty sa structure
* for sockets of type AF_UNIX. For all other types it will
* return a properly filled in structure.
*/
if (len == 0)
return UV_NAMED_PIPE;
#endif /* defined(_AIX) */
if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6) if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6)
return UV_TCP; return UV_TCP;
if (sa.sa_family == AF_UNIX) if (sa.sa_family == AF_UNIX)

4
deps/uv/src/unix/udp.c

@ -410,8 +410,10 @@ int uv__udp_send(uv_udp_send_t* req,
if (nbufs > ARRAY_SIZE(req->bufsml)) if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(bufs[0])); req->bufs = uv__malloc(nbufs * sizeof(bufs[0]));
if (req->bufs == NULL) if (req->bufs == NULL) {
uv__req_unregister(handle->loop, req);
return -ENOMEM; return -ENOMEM;
}
memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0])); memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
handle->send_queue_size += uv__count_bufs(req->bufs, req->nbufs); handle->send_queue_size += uv__count_bufs(req->bufs, req->nbufs);

27
deps/uv/src/uv-common.c

@ -141,11 +141,7 @@ static const char* uv__unknown_err_code(int err) {
char buf[32]; char buf[32];
char* copy; char* copy;
#ifndef _WIN32
snprintf(buf, sizeof(buf), "Unknown system error %d", err); snprintf(buf, sizeof(buf), "Unknown system error %d", err);
#else
_snprintf(buf, sizeof(buf), "Unknown system error %d", err);
#endif
copy = uv__strdup(buf); copy = uv__strdup(buf);
return copy != NULL ? copy : "Unknown system error"; return copy != NULL ? copy : "Unknown system error";
@ -341,19 +337,25 @@ int uv_udp_recv_stop(uv_udp_t* handle) {
void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) { void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
QUEUE queue;
QUEUE* q; QUEUE* q;
uv_handle_t* h; uv_handle_t* h;
QUEUE_FOREACH(q, &loop->handle_queue) { QUEUE_MOVE(&loop->handle_queue, &queue);
while (!QUEUE_EMPTY(&queue)) {
q = QUEUE_HEAD(&queue);
h = QUEUE_DATA(q, uv_handle_t, handle_queue); h = QUEUE_DATA(q, uv_handle_t, handle_queue);
QUEUE_REMOVE(q);
QUEUE_INSERT_TAIL(&loop->handle_queue, q);
if (h->flags & UV__HANDLE_INTERNAL) continue; if (h->flags & UV__HANDLE_INTERNAL) continue;
walk_cb(h, arg); walk_cb(h, arg);
} }
} }
#ifndef NDEBUG static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
static void uv__print_handles(uv_loop_t* loop, int only_active) {
const char* type; const char* type;
QUEUE* q; QUEUE* q;
uv_handle_t* h; uv_handle_t* h;
@ -374,7 +376,7 @@ static void uv__print_handles(uv_loop_t* loop, int only_active) {
default: type = "<unknown>"; default: type = "<unknown>";
} }
fprintf(stderr, fprintf(stream,
"[%c%c%c] %-8s %p\n", "[%c%c%c] %-8s %p\n",
"R-"[!(h->flags & UV__HANDLE_REF)], "R-"[!(h->flags & UV__HANDLE_REF)],
"A-"[!(h->flags & UV__HANDLE_ACTIVE)], "A-"[!(h->flags & UV__HANDLE_ACTIVE)],
@ -385,15 +387,14 @@ static void uv__print_handles(uv_loop_t* loop, int only_active) {
} }
void uv_print_all_handles(uv_loop_t* loop) { void uv_print_all_handles(uv_loop_t* loop, FILE* stream) {
uv__print_handles(loop, 0); uv__print_handles(loop, 0, stream);
} }
void uv_print_active_handles(uv_loop_t* loop) { void uv_print_active_handles(uv_loop_t* loop, FILE* stream) {
uv__print_handles(loop, 1); uv__print_handles(loop, 1, stream);
} }
#endif
void uv_ref(uv_handle_t* handle) { void uv_ref(uv_handle_t* handle) {

4
deps/uv/src/uv-common.h

@ -41,6 +41,10 @@
#include "tree.h" #include "tree.h"
#include "queue.h" #include "queue.h"
#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
extern int snprintf(char*, size_t, const char*, ...);
#endif
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define container_of(ptr, type, member) \ #define container_of(ptr, type, member) \

1
deps/uv/src/win/error.c

@ -129,6 +129,7 @@ int uv_translate_sys_error(int sys_errno) {
case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH; case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH;
case WSAENETUNREACH: return UV_ENETUNREACH; case WSAENETUNREACH: return UV_ENETUNREACH;
case WSAENOBUFS: return UV_ENOBUFS; case WSAENOBUFS: return UV_ENOBUFS;
case ERROR_BAD_PATHNAME: return UV_ENOENT;
case ERROR_DIRECTORY: return UV_ENOENT; case ERROR_DIRECTORY: return UV_ENOENT;
case ERROR_FILE_NOT_FOUND: return UV_ENOENT; case ERROR_FILE_NOT_FOUND: return UV_ENOENT;
case ERROR_INVALID_NAME: return UV_ENOENT; case ERROR_INVALID_NAME: return UV_ENOENT;

23
deps/uv/src/win/fs-event.c

@ -381,9 +381,10 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
if (handle->dirw) { if (handle->dirw) {
/* /*
* We attempt to convert the file name to its long form for * We attempt to resolve the long form of the file name explicitly.
* events that still point to valid files on disk. * We only do this for file names that might still exist on disk.
* For removed and renamed events, we do not provide the file name. * If this fails, we use the name given by ReadDirectoryChangesW.
* This may be the long form or the 8.3 short name in some cases.
*/ */
if (file_info->Action != FILE_ACTION_REMOVED && if (file_info->Action != FILE_ACTION_REMOVED &&
file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) { file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) {
@ -438,16 +439,24 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
} }
/* /*
* If we couldn't get the long name - just use the name * We could not resolve the long form explicitly.
* provided by ReadDirectoryChangesW. * We therefore use the name given by ReadDirectoryChangesW.
* This may be the long form or the 8.3 short name in some cases.
*/ */
if (!long_filenamew) { if (!long_filenamew) {
filenamew = file_info->FileName; filenamew = file_info->FileName;
sizew = file_info->FileNameLength / sizeof(WCHAR); sizew = file_info->FileNameLength / sizeof(WCHAR);
} }
} else { } else {
/* Removed or renamed callbacks don't provide filename. */ /*
filenamew = NULL; * Removed or renamed events cannot be resolved to the long form.
* We therefore use the name given by ReadDirectoryChangesW.
* This may be the long form or the 8.3 short name in some cases.
*/
if (!long_filenamew) {
filenamew = file_info->FileName;
sizew = file_info->FileNameLength / sizeof(WCHAR);
}
} }
} else { } else {
/* We already have the long name of the file, so just use it. */ /* We already have the long name of the file, so just use it. */

215
deps/uv/src/win/fs.c

@ -110,6 +110,9 @@ const WCHAR JUNCTION_PREFIX_LEN = 4;
const WCHAR LONG_PATH_PREFIX[] = L"\\\\?\\"; const WCHAR LONG_PATH_PREFIX[] = L"\\\\?\\";
const WCHAR LONG_PATH_PREFIX_LEN = 4; const WCHAR LONG_PATH_PREFIX_LEN = 4;
const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\";
const WCHAR UNC_PATH_PREFIX_LEN = 8;
void uv_fs_init() { void uv_fs_init() {
_fmode = _O_BINARY; _fmode = _O_BINARY;
@ -233,14 +236,61 @@ INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
} }
static int fs__wide_to_utf8(WCHAR* w_source_ptr,
DWORD w_source_len,
char** target_ptr,
uint64_t* target_len_ptr) {
int r;
int target_len;
char* target;
target_len = WideCharToMultiByte(CP_UTF8,
0,
w_source_ptr,
w_source_len,
NULL,
0,
NULL,
NULL);
if (target_len == 0) {
return -1;
}
if (target_len_ptr != NULL) {
*target_len_ptr = target_len;
}
if (target_ptr == NULL) {
return 0;
}
target = uv__malloc(target_len + 1);
if (target == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return -1;
}
r = WideCharToMultiByte(CP_UTF8,
0,
w_source_ptr,
w_source_len,
target,
target_len,
NULL,
NULL);
assert(r == target_len);
target[target_len] = '\0';
*target_ptr = target;
return 0;
}
INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
uint64_t* target_len_ptr) { uint64_t* target_len_ptr) {
char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer; REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer;
WCHAR *w_target; WCHAR* w_target;
DWORD w_target_len; DWORD w_target_len;
char* target;
int target_len;
DWORD bytes; DWORD bytes;
if (!DeviceIoControl(handle, if (!DeviceIoControl(handle,
@ -333,50 +383,7 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
return -1; return -1;
} }
/* If needed, compute the length of the target. */ return fs__wide_to_utf8(w_target, w_target_len, target_ptr, target_len_ptr);
if (target_ptr != NULL || target_len_ptr != NULL) {
/* Compute the length of the target. */
target_len = WideCharToMultiByte(CP_UTF8,
0,
w_target,
w_target_len,
NULL,
0,
NULL,
NULL);
if (target_len == 0) {
return -1;
}
}
/* If requested, allocate memory and convert to UTF8. */
if (target_ptr != NULL) {
int r;
target = (char*) uv__malloc(target_len + 1);
if (target == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return -1;
}
r = WideCharToMultiByte(CP_UTF8,
0,
w_target,
w_target_len,
target,
target_len,
NULL,
NULL);
assert(r == target_len);
target[target_len] = '\0';
*target_ptr = target;
}
if (target_len_ptr != NULL) {
*target_len_ptr = target_len;
}
return 0;
} }
@ -533,7 +540,15 @@ void fs__close(uv_fs_t* req) {
else else
result = 0; result = 0;
SET_REQ_RESULT(req, result); /* _close doesn't set _doserrno on failure, but it does always set errno
* to EBADF on failure.
*/
if (result == -1) {
assert(errno == EBADF);
SET_REQ_UV_ERROR(req, UV_EBADF, ERROR_INVALID_HANDLE);
} else {
req->result = 0;
}
} }
@ -1699,6 +1714,84 @@ static void fs__readlink(uv_fs_t* req) {
} }
static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
int r;
DWORD w_realpath_len;
WCHAR* w_realpath_ptr;
WCHAR* w_finalpath_ptr = NULL;
w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
if (w_realpath_len == 0) {
return -1;
}
w_realpath_ptr = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR));
if (w_realpath_ptr == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return -1;
}
if (pGetFinalPathNameByHandleW(handle,
w_realpath_ptr,
w_realpath_len,
VOLUME_NAME_DOS) == 0) {
uv__free(w_realpath_ptr);
SetLastError(ERROR_INVALID_HANDLE);
return -1;
}
/* convert UNC path to long path */
if (wcsncmp(w_realpath_ptr,
UNC_PATH_PREFIX,
UNC_PATH_PREFIX_LEN) == 0) {
w_finalpath_ptr = w_realpath_ptr + 6;
*w_finalpath_ptr = L'\\';
} else if (wcsncmp(w_realpath_ptr,
LONG_PATH_PREFIX,
LONG_PATH_PREFIX_LEN) == 0) {
w_finalpath_ptr = w_realpath_ptr + 4;
} else {
uv__free(w_realpath_ptr);
SetLastError(ERROR_INVALID_HANDLE);
return -1;
}
r = fs__wide_to_utf8(w_finalpath_ptr, w_realpath_len, realpath_ptr, NULL);
uv__free(w_realpath_ptr);
return r;
}
static void fs__realpath(uv_fs_t* req) {
HANDLE handle;
if (!pGetFinalPathNameByHandleW) {
SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
return;
}
handle = CreateFileW(req->file.pathw,
0,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (handle == INVALID_HANDLE_VALUE) {
SET_REQ_WIN32_ERROR(req, GetLastError());
return;
}
if (fs__realpath_handle(handle, (char**) &req->ptr) == -1) {
CloseHandle(handle);
SET_REQ_WIN32_ERROR(req, GetLastError());
return;
}
CloseHandle(handle);
req->flags |= UV_FS_FREE_PTR;
SET_REQ_RESULT(req, 0);
}
static void fs__chown(uv_fs_t* req) { static void fs__chown(uv_fs_t* req) {
req->result = 0; req->result = 0;
@ -1743,6 +1836,7 @@ static void uv__fs_work(struct uv__work* w) {
XX(LINK, link) XX(LINK, link)
XX(SYMLINK, symlink) XX(SYMLINK, symlink)
XX(READLINK, readlink) XX(READLINK, readlink)
XX(REALPATH, realpath)
XX(CHOWN, chown) XX(CHOWN, chown)
XX(FCHOWN, fchown); XX(FCHOWN, fchown);
default: default:
@ -2067,6 +2161,31 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
} }
int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_cb cb) {
int err;
if (!req || !path) {
return UV_EINVAL;
}
uv_fs_req_init(loop, req, UV_FS_REALPATH, cb);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
if (cb) {
QUEUE_FS_TP_JOB(loop, req);
return 0;
} else {
fs__realpath(req);
return req->result;
}
}
int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
uv_gid_t gid, uv_fs_cb cb) { uv_gid_t gid, uv_fs_cb cb) {
int err; int err;

13
deps/uv/src/win/getaddrinfo.c

@ -109,10 +109,8 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
req = container_of(w, uv_getaddrinfo_t, work_req); req = container_of(w, uv_getaddrinfo_t, work_req);
/* release input parameter memory */ /* release input parameter memory */
if (req->alloc != NULL) { uv__free(req->alloc);
uv__free(req->alloc); req->alloc = NULL;
req->alloc = NULL;
}
if (status == UV_ECANCELED) { if (status == UV_ECANCELED) {
assert(req->retcode == 0); assert(req->retcode == 0);
@ -219,9 +217,7 @@ void uv_freeaddrinfo(struct addrinfo* ai) {
char* alloc_ptr = (char*)ai; char* alloc_ptr = (char*)ai;
/* release copied result memory */ /* release copied result memory */
if (alloc_ptr != NULL) { uv__free(alloc_ptr);
uv__free(alloc_ptr);
}
} }
@ -354,8 +350,9 @@ int uv_getaddrinfo(uv_loop_t* loop,
} }
error: error:
if (req != NULL && req->alloc != NULL) { if (req != NULL) {
uv__free(req->alloc); uv__free(req->alloc);
req->alloc = NULL;
} }
return uv_translate_sys_error(err); return uv_translate_sys_error(err);
} }

1
deps/uv/src/win/internal.h

@ -327,6 +327,7 @@ void uv__util_init();
uint64_t uv__hrtime(double scale); uint64_t uv__hrtime(double scale);
int uv_parent_pid(); int uv_parent_pid();
int uv_current_pid();
__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall); __declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);

8
deps/uv/src/win/pipe.c

@ -85,7 +85,7 @@ static void eof_timer_close_cb(uv_handle_t* handle);
static void uv_unique_pipe_name(char* ptr, char* name, size_t size) { static void uv_unique_pipe_name(char* ptr, char* name, size_t size) {
_snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%u", ptr, GetCurrentProcessId()); snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%u", ptr, GetCurrentProcessId());
} }
@ -1246,6 +1246,10 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
if (send_handle) { if (send_handle) {
tcp_send_handle = (uv_tcp_t*)send_handle; tcp_send_handle = (uv_tcp_t*)send_handle;
if (handle->pipe.conn.ipc_pid == 0) {
handle->pipe.conn.ipc_pid = uv_current_pid();
}
err = uv_tcp_duplicate_socket(tcp_send_handle, handle->pipe.conn.ipc_pid, err = uv_tcp_duplicate_socket(tcp_send_handle, handle->pipe.conn.ipc_pid,
&ipc_frame.socket_info_ex.socket_info); &ipc_frame.socket_info_ex.socket_info);
if (err) { if (err) {
@ -1629,7 +1633,7 @@ void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
if (ReadFile(handle->handle, if (ReadFile(handle->handle,
buf.base, buf.base,
buf.len, min(buf.len, avail),
&bytes, &bytes,
NULL)) { NULL)) {
/* Successful read */ /* Successful read */

42
deps/uv/src/win/snprintf.c

@ -0,0 +1,42 @@
/* Copyright the 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.
*/
#if defined(_MSC_VER) && _MSC_VER < 1900
#include <stdio.h>
#include <stdarg.h>
/* Emulate snprintf() on MSVC<2015, _snprintf() doesn't zero-terminate the buffer
* on overflow...
*/
int snprintf(char* buf, size_t len, const char* fmt, ...) {
int n;
va_list ap;
va_start(ap, fmt);
n = _vscprintf(fmt, ap);
vsnprintf_s(buf, len, _TRUNCATE, fmt, ap);
va_end(ap);
return n;
}
#endif

2
deps/uv/src/win/tty.c

@ -208,7 +208,7 @@ static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info) {
static int style_captured = 0; static int style_captured = 0;
/* Only do this once. /* Only do this once.
/* Assumption: Caller has acquired uv_tty_output_lock. */ Assumption: Caller has acquired uv_tty_output_lock. */
if (style_captured) if (style_captured)
return; return;

12
deps/uv/src/win/util.c

@ -59,6 +59,10 @@
static char *process_title; static char *process_title;
static CRITICAL_SECTION process_title_lock; static CRITICAL_SECTION process_title_lock;
/* Cached copy of the process id, written once. */
static DWORD current_pid = 0;
/* Interval (in seconds) of the high-resolution clock. */ /* Interval (in seconds) of the high-resolution clock. */
static double hrtime_interval_ = 0; static double hrtime_interval_ = 0;
@ -359,6 +363,14 @@ int uv_parent_pid() {
} }
int uv_current_pid() {
if (current_pid == 0) {
current_pid = GetCurrentProcessId();
}
return current_pid;
}
char** uv_setup_args(int argc, char** argv) { char** uv_setup_args(int argc, char** argv) {
return argv; return argv;
} }

4
deps/uv/src/win/winapi.c

@ -46,6 +46,7 @@ sSleepConditionVariableSRW pSleepConditionVariableSRW;
sWakeAllConditionVariable pWakeAllConditionVariable; sWakeAllConditionVariable pWakeAllConditionVariable;
sWakeConditionVariable pWakeConditionVariable; sWakeConditionVariable pWakeConditionVariable;
sCancelSynchronousIo pCancelSynchronousIo; sCancelSynchronousIo pCancelSynchronousIo;
sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
void uv_winapi_init() { void uv_winapi_init() {
@ -139,4 +140,7 @@ void uv_winapi_init() {
pCancelSynchronousIo = (sCancelSynchronousIo) pCancelSynchronousIo = (sCancelSynchronousIo)
GetProcAddress(kernel32_module, "CancelSynchronousIo"); GetProcAddress(kernel32_module, "CancelSynchronousIo");
pGetFinalPathNameByHandleW = (sGetFinalPathNameByHandleW)
GetProcAddress(kernel32_module, "GetFinalPathNameByHandleW");
} }

7
deps/uv/src/win/winapi.h

@ -4678,6 +4678,12 @@ typedef VOID (WINAPI* sWakeConditionVariable)
typedef BOOL (WINAPI* sCancelSynchronousIo) typedef BOOL (WINAPI* sCancelSynchronousIo)
(HANDLE hThread); (HANDLE hThread);
typedef DWORD (WINAPI* sGetFinalPathNameByHandleW)
(HANDLE hFile,
LPWSTR lpszFilePath,
DWORD cchFilePath,
DWORD dwFlags);
/* Ntdll function pointers */ /* Ntdll function pointers */
extern sRtlNtStatusToDosError pRtlNtStatusToDosError; extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
extern sNtDeviceIoControlFile pNtDeviceIoControlFile; extern sNtDeviceIoControlFile pNtDeviceIoControlFile;
@ -4699,5 +4705,6 @@ extern sSleepConditionVariableSRW pSleepConditionVariableSRW;
extern sWakeAllConditionVariable pWakeAllConditionVariable; extern sWakeAllConditionVariable pWakeAllConditionVariable;
extern sWakeConditionVariable pWakeConditionVariable; extern sWakeConditionVariable pWakeConditionVariable;
extern sCancelSynchronousIo pCancelSynchronousIo; extern sCancelSynchronousIo pCancelSynchronousIo;
extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
#endif /* UV_WIN_WINAPI_H_ */ #endif /* UV_WIN_WINAPI_H_ */

10
deps/uv/test/runner-win.h

@ -19,9 +19,6 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
/* Don't complain about _snprintf being insecure. */
#define _CRT_SECURE_NO_WARNINGS
/* Don't complain about write(), fileno() etc. being deprecated. */ /* Don't complain about write(), fileno() etc. being deprecated. */
#pragma warning(disable : 4996) #pragma warning(disable : 4996)
@ -30,10 +27,9 @@
#include <windows.h> #include <windows.h>
#include <stdio.h> #include <stdio.h>
#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
/* Windows has no snprintf, only _snprintf. */ extern int snprintf(char*, size_t, const char*, ...);
#define snprintf _snprintf #endif
typedef struct { typedef struct {
HANDLE process; HANDLE process;

2
deps/uv/test/runner.c

@ -210,6 +210,8 @@ int run_test(const char* test,
#ifndef _WIN32 #ifndef _WIN32
/* Clean up stale socket from previous run. */ /* Clean up stale socket from previous run. */
remove(TEST_PIPENAME); remove(TEST_PIPENAME);
remove(TEST_PIPENAME_2);
remove(TEST_PIPENAME_3);
#endif #endif
/* If it's a helper the user asks for, start it directly. */ /* If it's a helper the user asks for, start it directly. */

38
deps/uv/test/task.h

@ -50,9 +50,11 @@
#ifdef _WIN32 #ifdef _WIN32
# define TEST_PIPENAME "\\\\?\\pipe\\uv-test" # define TEST_PIPENAME "\\\\?\\pipe\\uv-test"
# define TEST_PIPENAME_2 "\\\\?\\pipe\\uv-test2" # define TEST_PIPENAME_2 "\\\\?\\pipe\\uv-test2"
# define TEST_PIPENAME_3 "\\\\?\\pipe\\uv-test3"
#else #else
# define TEST_PIPENAME "/tmp/uv-test-sock" # define TEST_PIPENAME "/tmp/uv-test-sock"
# define TEST_PIPENAME_2 "/tmp/uv-test-sock2" # define TEST_PIPENAME_2 "/tmp/uv-test-sock2"
# define TEST_PIPENAME_3 "/tmp/uv-test-sock3"
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
@ -174,40 +176,8 @@ enum test_status {
#endif #endif
#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
#if defined _WIN32 && ! defined __GNUC__ extern int snprintf(char*, size_t, const char*, ...);
#include <stdarg.h>
/* Define inline for MSVC<2015 */
# if defined(_MSC_VER) && _MSC_VER < 1900
# define inline __inline
# endif
# if defined(_MSC_VER) && _MSC_VER < 1900
/* Emulate snprintf() on MSVC<2015, _snprintf() doesn't zero-terminate the buffer
* on overflow...
*/
inline int snprintf(char* buf, size_t len, const char* fmt, ...) {
va_list ap;
int n;
va_start(ap, fmt);
n = _vsprintf_p(buf, len, fmt, ap);
va_end(ap);
/* It's a sad fact of life that no one ever checks the return value of
* snprintf(). Zero-terminating the buffer hopefully reduces the risk
* of gaping security holes.
*/
if (n < 0)
if (len > 0)
buf[0] = '\0';
return n;
}
# endif
#endif #endif
#if defined(__clang__) || \ #if defined(__clang__) || \

15
deps/uv/test/test-emfile.c

@ -25,7 +25,6 @@
#include "task.h" #include "task.h"
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <unistd.h> #include <unistd.h>
@ -45,6 +44,13 @@ TEST_IMPL(emfile) {
uv_loop_t* loop; uv_loop_t* loop;
int first_fd; int first_fd;
/* Lower the file descriptor limit and use up all fds save one. */
limits.rlim_cur = limits.rlim_max = maxfd + 1;
if (setrlimit(RLIMIT_NOFILE, &limits)) {
ASSERT(errno == EPERM); /* Valgrind blocks the setrlimit() call. */
RETURN_SKIP("setrlimit(RLIMIT_NOFILE) failed, running under valgrind?");
}
loop = uv_default_loop(); loop = uv_default_loop();
ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
ASSERT(0 == uv_tcp_init(loop, &server_handle)); ASSERT(0 == uv_tcp_init(loop, &server_handle));
@ -52,13 +58,6 @@ TEST_IMPL(emfile) {
ASSERT(0 == uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr, 0)); ASSERT(0 == uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr, 0));
ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 8, connection_cb)); ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 8, connection_cb));
/* Lower the file descriptor limit and use up all fds save one. */
limits.rlim_cur = limits.rlim_max = maxfd + 1;
if (setrlimit(RLIMIT_NOFILE, &limits)) {
perror("setrlimit(RLIMIT_NOFILE)");
ASSERT(0);
}
/* Remember the first one so we can clean up afterwards. */ /* Remember the first one so we can clean up afterwards. */
do do
first_fd = dup(0); first_fd = dup(0);

28
deps/uv/test/test-fs-event.c

@ -115,7 +115,11 @@ static void fs_event_cb_dir(uv_fs_event_t* handle, const char* filename,
ASSERT(handle == &fs_event); ASSERT(handle == &fs_event);
ASSERT(status == 0); ASSERT(status == 0);
ASSERT(events == UV_RENAME); ASSERT(events == UV_RENAME);
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
ASSERT(strcmp(filename, "file1") == 0);
#else
ASSERT(filename == NULL || strcmp(filename, "file1") == 0); ASSERT(filename == NULL || strcmp(filename, "file1") == 0);
#endif
ASSERT(0 == uv_fs_event_stop(handle)); ASSERT(0 == uv_fs_event_stop(handle));
uv_close((uv_handle_t*)handle, close_cb); uv_close((uv_handle_t*)handle, close_cb);
} }
@ -178,8 +182,12 @@ static void fs_event_cb_dir_multi_file(uv_fs_event_t* handle,
ASSERT(handle == &fs_event); ASSERT(handle == &fs_event);
ASSERT(status == 0); ASSERT(status == 0);
ASSERT(events == UV_CHANGE || UV_RENAME); ASSERT(events == UV_CHANGE || UV_RENAME);
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
ASSERT(strncmp(filename, file_prefix, sizeof(file_prefix) - 1) == 0);
#else
ASSERT(filename == NULL || ASSERT(filename == NULL ||
strncmp(filename, file_prefix, sizeof(file_prefix) - 1) == 0); strncmp(filename, file_prefix, sizeof(file_prefix) - 1) == 0);
#endif
if (fs_event_created + fs_event_removed == fs_event_file_count) { if (fs_event_created + fs_event_removed == fs_event_file_count) {
/* Once we've processed all create events, delete all files */ /* Once we've processed all create events, delete all files */
@ -250,8 +258,16 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle,
ASSERT(handle == &fs_event); ASSERT(handle == &fs_event);
ASSERT(status == 0); ASSERT(status == 0);
ASSERT(events == UV_CHANGE || UV_RENAME); ASSERT(events == UV_CHANGE || UV_RENAME);
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
ASSERT(strncmp(filename,
file_prefix_in_subdir,
sizeof(file_prefix_in_subdir) - 1) == 0);
#else
ASSERT(filename == NULL || ASSERT(filename == NULL ||
strncmp(filename, file_prefix_in_subdir, sizeof(file_prefix_in_subdir) - 1) == 0); strncmp(filename,
file_prefix_in_subdir,
sizeof(file_prefix_in_subdir) - 1) == 0);
#endif
if (fs_event_created + fs_event_removed == fs_event_file_count) { if (fs_event_created + fs_event_removed == fs_event_file_count) {
/* Once we've processed all create events, delete all files */ /* Once we've processed all create events, delete all files */
@ -270,7 +286,11 @@ static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename,
ASSERT(handle == &fs_event); ASSERT(handle == &fs_event);
ASSERT(status == 0); ASSERT(status == 0);
ASSERT(events == UV_CHANGE); ASSERT(events == UV_CHANGE);
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
ASSERT(strcmp(filename, "file2") == 0);
#else
ASSERT(filename == NULL || strcmp(filename, "file2") == 0); ASSERT(filename == NULL || strcmp(filename, "file2") == 0);
#endif
ASSERT(0 == uv_fs_event_stop(handle)); ASSERT(0 == uv_fs_event_stop(handle));
uv_close((uv_handle_t*)handle, close_cb); uv_close((uv_handle_t*)handle, close_cb);
} }
@ -293,7 +313,11 @@ static void fs_event_cb_file_current_dir(uv_fs_event_t* handle,
ASSERT(handle == &fs_event); ASSERT(handle == &fs_event);
ASSERT(status == 0); ASSERT(status == 0);
ASSERT(events == UV_CHANGE); ASSERT(events == UV_CHANGE);
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
ASSERT(strcmp(filename, "watch_file") == 0);
#else
ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0); ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0);
#endif
/* Regression test for SunOS: touch should generate just one event. */ /* Regression test for SunOS: touch should generate just one event. */
{ {
@ -487,7 +511,7 @@ TEST_IMPL(fs_event_watch_file_current_dir) {
r = uv_timer_init(loop, &timer); r = uv_timer_init(loop, &timer);
ASSERT(r == 0); ASSERT(r == 0);
r = uv_timer_start(&timer, timer_cb_touch, 1, 0); r = uv_timer_start(&timer, timer_cb_touch, 10, 0);
ASSERT(r == 0); ASSERT(r == 0);
ASSERT(timer_cb_touch_called == 0); ASSERT(timer_cb_touch_called == 0);

142
deps/uv/test/test-fs.c

@ -83,6 +83,7 @@ static int fchown_cb_count;
static int link_cb_count; static int link_cb_count;
static int symlink_cb_count; static int symlink_cb_count;
static int readlink_cb_count; static int readlink_cb_count;
static int realpath_cb_count;
static int utime_cb_count; static int utime_cb_count;
static int futime_cb_count; static int futime_cb_count;
@ -168,6 +169,35 @@ static void readlink_cb(uv_fs_t* req) {
} }
static void realpath_cb(uv_fs_t* req) {
char test_file_abs_buf[PATHMAX];
size_t test_file_abs_size = sizeof(test_file_abs_buf);
ASSERT(req->fs_type == UV_FS_REALPATH);
#ifdef _WIN32
/*
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
*/
if (req->result == UV_ENOSYS) {
realpath_cb_count++;
uv_fs_req_cleanup(req);
return;
}
#endif
ASSERT(req->result == 0);
uv_cwd(test_file_abs_buf, &test_file_abs_size);
#ifdef _WIN32
strcat(test_file_abs_buf, "\\test_file");
ASSERT(stricmp(req->ptr, test_file_abs_buf) == 0);
#else
strcat(test_file_abs_buf, "/test_file");
ASSERT(strcmp(req->ptr, test_file_abs_buf) == 0);
#endif
realpath_cb_count++;
uv_fs_req_cleanup(req);
}
static void access_cb(uv_fs_t* req) { static void access_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_ACCESS); ASSERT(req->fs_type == UV_FS_ACCESS);
access_cb_count++; access_cb_count++;
@ -1565,11 +1595,43 @@ TEST_IMPL(fs_readlink) {
} }
TEST_IMPL(fs_realpath) {
uv_fs_t req;
loop = uv_default_loop();
ASSERT(0 == uv_fs_realpath(loop, &req, "no_such_file", dummy_cb));
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
ASSERT(dummy_cb_count == 1);
ASSERT(req.ptr == NULL);
#ifdef _WIN32
/*
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
*/
if (req.result == UV_ENOSYS) {
uv_fs_req_cleanup(&req);
RETURN_SKIP("realpath is not supported on Windows XP");
}
#endif
ASSERT(req.result == UV_ENOENT);
uv_fs_req_cleanup(&req);
ASSERT(UV_ENOENT == uv_fs_realpath(NULL, &req, "no_such_file", NULL));
ASSERT(req.ptr == NULL);
ASSERT(req.result == UV_ENOENT);
uv_fs_req_cleanup(&req);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(fs_symlink) { TEST_IMPL(fs_symlink) {
int r; int r;
uv_fs_t req; uv_fs_t req;
uv_file file; uv_file file;
uv_file link; uv_file link;
char test_file_abs_buf[PATHMAX];
size_t test_file_abs_size;
/* Setup. */ /* Setup. */
unlink("test_file"); unlink("test_file");
@ -1577,6 +1639,14 @@ TEST_IMPL(fs_symlink) {
unlink("test_file_symlink2"); unlink("test_file_symlink2");
unlink("test_file_symlink_symlink"); unlink("test_file_symlink_symlink");
unlink("test_file_symlink2_symlink"); unlink("test_file_symlink2_symlink");
test_file_abs_size = sizeof(test_file_abs_buf);
#ifdef _WIN32
uv_cwd(test_file_abs_buf, &test_file_abs_size);
strcat(test_file_abs_buf, "\\test_file");
#else
uv_cwd(test_file_abs_buf, &test_file_abs_size);
strcat(test_file_abs_buf, "/test_file");
#endif
loop = uv_default_loop(); loop = uv_default_loop();
@ -1647,6 +1717,24 @@ TEST_IMPL(fs_symlink) {
ASSERT(strcmp(req.ptr, "test_file_symlink") == 0); ASSERT(strcmp(req.ptr, "test_file_symlink") == 0);
uv_fs_req_cleanup(&req); uv_fs_req_cleanup(&req);
r = uv_fs_realpath(NULL, &req, "test_file_symlink_symlink", NULL);
#ifdef _WIN32
/*
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
*/
if (r == UV_ENOSYS) {
uv_fs_req_cleanup(&req);
RETURN_SKIP("realpath is not supported on Windows XP");
}
#endif
ASSERT(r == 0);
#ifdef _WIN32
ASSERT(stricmp(req.ptr, test_file_abs_buf) == 0);
#else
ASSERT(strcmp(req.ptr, test_file_abs_buf) == 0);
#endif
uv_fs_req_cleanup(&req);
/* async link */ /* async link */
r = uv_fs_symlink(loop, r = uv_fs_symlink(loop,
&req, &req,
@ -1687,6 +1775,20 @@ TEST_IMPL(fs_symlink) {
uv_run(loop, UV_RUN_DEFAULT); uv_run(loop, UV_RUN_DEFAULT);
ASSERT(readlink_cb_count == 1); ASSERT(readlink_cb_count == 1);
r = uv_fs_realpath(loop, &req, "test_file", realpath_cb);
#ifdef _WIN32
/*
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
*/
if (r == UV_ENOSYS) {
uv_fs_req_cleanup(&req);
RETURN_SKIP("realpath is not supported on Windows XP");
}
#endif
ASSERT(r == 0);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(realpath_cb_count == 1);
/* /*
* Run the loop just to check we don't have make any extraneous uv_ref() * Run the loop just to check we don't have make any extraneous uv_ref()
* calls. This should drop out immediately. * calls. This should drop out immediately.
@ -1710,12 +1812,15 @@ TEST_IMPL(fs_symlink_dir) {
int r; int r;
char* test_dir; char* test_dir;
uv_dirent_t dent; uv_dirent_t dent;
static char test_dir_abs_buf[PATHMAX];
size_t test_dir_abs_size;
/* set-up */ /* set-up */
unlink("test_dir/file1"); unlink("test_dir/file1");
unlink("test_dir/file2"); unlink("test_dir/file2");
rmdir("test_dir"); rmdir("test_dir");
rmdir("test_dir_symlink"); rmdir("test_dir_symlink");
test_dir_abs_size = sizeof(test_dir_abs_buf);
loop = uv_default_loop(); loop = uv_default_loop();
@ -1723,16 +1828,16 @@ TEST_IMPL(fs_symlink_dir) {
uv_fs_req_cleanup(&req); uv_fs_req_cleanup(&req);
#ifdef _WIN32 #ifdef _WIN32
{ strcpy(test_dir_abs_buf, "\\\\?\\");
static char src_path_buf[PATHMAX]; uv_cwd(test_dir_abs_buf + 4, &test_dir_abs_size);
size_t size; test_dir_abs_size += 4;
size = sizeof(src_path_buf); strcat(test_dir_abs_buf, "\\test_dir\\");
strcpy(src_path_buf, "\\\\?\\"); test_dir_abs_size += strlen("\\test_dir\\");
uv_cwd(src_path_buf + 4, &size); test_dir = test_dir_abs_buf;
strcat(src_path_buf, "\\test_dir\\");
test_dir = src_path_buf;
}
#else #else
uv_cwd(test_dir_abs_buf, &test_dir_abs_size);
strcat(test_dir_abs_buf, "/test_dir");
test_dir_abs_size += strlen("/test_dir");
test_dir = "test_dir"; test_dir = "test_dir";
#endif #endif
@ -1767,6 +1872,25 @@ TEST_IMPL(fs_symlink_dir) {
#endif #endif
uv_fs_req_cleanup(&req); uv_fs_req_cleanup(&req);
r = uv_fs_realpath(NULL, &req, "test_dir_symlink", NULL);
#ifdef _WIN32
/*
* Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
*/
if (r == UV_ENOSYS) {
uv_fs_req_cleanup(&req);
RETURN_SKIP("realpath is not supported on Windows XP");
}
#endif
ASSERT(r == 0);
#ifdef _WIN32
ASSERT(strlen(req.ptr) == test_dir_abs_size - 5);
ASSERT(strnicmp(req.ptr, test_dir + 4, test_dir_abs_size - 5) == 0);
#else
ASSERT(strcmp(req.ptr, test_dir_abs_buf) == 0);
#endif
uv_fs_req_cleanup(&req);
r = uv_fs_open(NULL, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT, r = uv_fs_open(NULL, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT,
S_IWUSR | S_IRUSR, NULL); S_IWUSR | S_IRUSR, NULL);
ASSERT(r >= 0); ASSERT(r >= 0);

3
deps/uv/test/test-get-loadavg.c

@ -24,10 +24,9 @@
TEST_IMPL(get_loadavg) { TEST_IMPL(get_loadavg) {
double avg[3]; double avg[3] = {-1, -1, -1};
uv_loadavg(avg); uv_loadavg(avg);
ASSERT(avg != NULL);
ASSERT(avg[0] >= 0); ASSERT(avg[0] >= 0);
ASSERT(avg[1] >= 0); ASSERT(avg[1] >= 0);
ASSERT(avg[2] >= 0); ASSERT(avg[2] >= 0);

6
deps/uv/test/test-getaddrinfo.c

@ -83,10 +83,11 @@ static void getaddrinfo_cuncurrent_cb(uv_getaddrinfo_t* handle,
TEST_IMPL(getaddrinfo_fail) { TEST_IMPL(getaddrinfo_fail) {
uv_getaddrinfo_t req; uv_getaddrinfo_t req;
/* Use a FQDN by ending in a period */
ASSERT(0 == uv_getaddrinfo(uv_default_loop(), ASSERT(0 == uv_getaddrinfo(uv_default_loop(),
&req, &req,
getaddrinfo_fail_cb, getaddrinfo_fail_cb,
"xyzzy.xyzzy.xyzzy", "xyzzy.xyzzy.xyzzy.",
NULL, NULL,
NULL)); NULL));
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
@ -100,10 +101,11 @@ TEST_IMPL(getaddrinfo_fail) {
TEST_IMPL(getaddrinfo_fail_sync) { TEST_IMPL(getaddrinfo_fail_sync) {
uv_getaddrinfo_t req; uv_getaddrinfo_t req;
/* Use a FQDN by ending in a period */
ASSERT(0 > uv_getaddrinfo(uv_default_loop(), ASSERT(0 > uv_getaddrinfo(uv_default_loop(),
&req, &req,
NULL, NULL,
"xyzzy.xyzzy.xyzzy", "xyzzy.xyzzy.xyzzy.",
NULL, NULL,
NULL)); NULL));
uv_freeaddrinfo(req.addrinfo); uv_freeaddrinfo(req.addrinfo);

4
deps/uv/test/test-getnameinfo.c

@ -73,8 +73,8 @@ TEST_IMPL(getnameinfo_basic_ip4_sync) {
NULL, NULL,
(const struct sockaddr*)&addr4, (const struct sockaddr*)&addr4,
0)); 0));
ASSERT(req.host != NULL); ASSERT(req.host[0] != '\0');
ASSERT(req.service != NULL); ASSERT(req.service[0] != '\0');
MAKE_VALGRIND_HAPPY(); MAKE_VALGRIND_HAPPY();
return 0; return 0;

291
deps/uv/test/test-ipc-send-recv.c

@ -30,6 +30,8 @@ void spawn_helper(uv_pipe_t* channel,
uv_process_t* process, uv_process_t* process,
const char* helper); const char* helper);
void ipc_send_recv_helper_threadproc(void* arg);
union handles { union handles {
uv_handle_t handle; uv_handle_t handle;
uv_stream_t stream; uv_stream_t stream;
@ -38,16 +40,37 @@ union handles {
uv_tty_t tty; uv_tty_t tty;
}; };
struct echo_ctx { struct test_ctx {
uv_pipe_t channel; uv_pipe_t channel;
uv_connect_t connect_req;
uv_write_t write_req; uv_write_t write_req;
uv_write_t write_req2;
uv_handle_type expected_type; uv_handle_type expected_type;
union handles send; union handles send;
union handles send2;
union handles recv;
union handles recv2;
};
struct echo_ctx {
uv_pipe_t listen;
uv_pipe_t channel;
uv_write_t write_req;
uv_write_t write_req2;
uv_handle_type expected_type;
union handles recv; union handles recv;
union handles recv2;
}; };
static struct echo_ctx ctx; static struct test_ctx ctx;
static int num_recv_handles; static struct echo_ctx ctx2;
/* Used in write2_cb to decide if we need to cleanup or not */
static int is_child_process;
static int is_in_process;
static int read_cb_called;
static int recv_cb_called;
static int write2_cb_called;
static void alloc_cb(uv_handle_t* handle, static void alloc_cb(uv_handle_t* handle,
@ -66,39 +89,55 @@ static void recv_cb(uv_stream_t* handle,
uv_handle_type pending; uv_handle_type pending;
uv_pipe_t* pipe; uv_pipe_t* pipe;
int r; int r;
union handles* recv;
if (++recv_cb_called == 1) {
recv = &ctx.recv;
} else {
recv = &ctx.recv2;
}
pipe = (uv_pipe_t*) handle; pipe = (uv_pipe_t*) handle;
ASSERT(pipe == &ctx.channel); ASSERT(pipe == &ctx.channel);
ASSERT(nread >= 0);
ASSERT(1 == uv_pipe_pending_count(pipe));
pending = uv_pipe_pending_type(pipe);
ASSERT(pending == ctx.expected_type);
if (pending == UV_NAMED_PIPE)
r = uv_pipe_init(ctx.channel.loop, &ctx.recv.pipe, 0);
else if (pending == UV_TCP)
r = uv_tcp_init(ctx.channel.loop, &ctx.recv.tcp);
else
abort();
ASSERT(r == 0);
r = uv_accept(handle, &ctx.recv.stream); /* Depending on the OS, the final recv_cb can be called after the child
ASSERT(r == 0); * process has terminated which can result in nread being UV_EOF instead of
* the number of bytes read. Since the other end of the pipe has closed this
uv_close((uv_handle_t*)&ctx.channel, NULL); * UV_EOF is an acceptable value. */
uv_close(&ctx.send.handle, NULL); if (nread == UV_EOF) {
uv_close(&ctx.recv.handle, NULL); /* UV_EOF is only acceptable for the final recv_cb call */
num_recv_handles++; ASSERT(recv_cb_called == 2);
} else {
ASSERT(nread >= 0);
ASSERT(1 == uv_pipe_pending_count(pipe));
pending = uv_pipe_pending_type(pipe);
ASSERT(pending == ctx.expected_type);
if (pending == UV_NAMED_PIPE)
r = uv_pipe_init(ctx.channel.loop, &recv->pipe, 0);
else if (pending == UV_TCP)
r = uv_tcp_init(ctx.channel.loop, &recv->tcp);
else
abort();
ASSERT(r == 0);
r = uv_accept(handle, &recv->stream);
ASSERT(r == 0);
}
/* Close after two writes received */
if (recv_cb_called == 2) {
uv_close((uv_handle_t*)&ctx.channel, NULL);
}
} }
static void connect_cb(uv_connect_t* req, int status) {
static int run_test(void) {
uv_process_t process;
uv_buf_t buf;
int r; int r;
uv_buf_t buf;
spawn_helper(&ctx.channel, &process, "ipc_send_recv_helper"); ASSERT(req == &ctx.connect_req);
ASSERT(status == 0);
buf = uv_buf_init(".", 1); buf = uv_buf_init(".", 1);
r = uv_write2(&ctx.write_req, r = uv_write2(&ctx.write_req,
@ -108,19 +147,56 @@ static int run_test(void) {
NULL); NULL);
ASSERT(r == 0); ASSERT(r == 0);
/* Perform two writes to the same pipe to make sure that on Windows we are
* not running into issue 505:
* https://github.com/libuv/libuv/issues/505 */
buf = uv_buf_init(".", 1);
r = uv_write2(&ctx.write_req2,
(uv_stream_t*)&ctx.channel,
&buf, 1,
&ctx.send2.stream,
NULL);
ASSERT(r == 0);
r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, recv_cb); r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, recv_cb);
ASSERT(r == 0); ASSERT(r == 0);
}
static int run_test(int inprocess) {
uv_process_t process;
uv_thread_t tid;
int r;
if (inprocess) {
r = uv_thread_create(&tid, ipc_send_recv_helper_threadproc, (void *) 42);
ASSERT(r == 0);
uv_sleep(1000);
r = uv_pipe_init(uv_default_loop(), &ctx.channel, 1);
ASSERT(r == 0);
uv_pipe_connect(&ctx.connect_req, &ctx.channel, TEST_PIPENAME_3, connect_cb);
} else {
spawn_helper(&ctx.channel, &process, "ipc_send_recv_helper");
connect_cb(&ctx.connect_req, 0);
}
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(r == 0); ASSERT(r == 0);
ASSERT(num_recv_handles == 1); ASSERT(recv_cb_called == 2);
if (inprocess) {
r = uv_thread_join(&tid);
ASSERT(r == 0);
}
return 0; return 0;
} }
static int run_ipc_send_recv_pipe(int inprocess) {
TEST_IMPL(ipc_send_recv_pipe) {
int r; int r;
ctx.expected_type = UV_NAMED_PIPE; ctx.expected_type = UV_NAMED_PIPE;
@ -131,15 +207,28 @@ TEST_IMPL(ipc_send_recv_pipe) {
r = uv_pipe_bind(&ctx.send.pipe, TEST_PIPENAME); r = uv_pipe_bind(&ctx.send.pipe, TEST_PIPENAME);
ASSERT(r == 0); ASSERT(r == 0);
r = run_test(); r = uv_pipe_init(uv_default_loop(), &ctx.send2.pipe, 1);
ASSERT(r == 0);
r = uv_pipe_bind(&ctx.send2.pipe, TEST_PIPENAME_2);
ASSERT(r == 0);
r = run_test(inprocess);
ASSERT(r == 0); ASSERT(r == 0);
MAKE_VALGRIND_HAPPY(); MAKE_VALGRIND_HAPPY();
return 0; return 0;
} }
TEST_IMPL(ipc_send_recv_pipe) {
return run_ipc_send_recv_pipe(0);
}
TEST_IMPL(ipc_send_recv_tcp) { TEST_IMPL(ipc_send_recv_pipe_inprocess) {
return run_ipc_send_recv_pipe(1);
}
static int run_ipc_send_recv_tcp(int inprocess) {
struct sockaddr_in addr; struct sockaddr_in addr;
int r; int r;
@ -150,25 +239,45 @@ TEST_IMPL(ipc_send_recv_tcp) {
r = uv_tcp_init(uv_default_loop(), &ctx.send.tcp); r = uv_tcp_init(uv_default_loop(), &ctx.send.tcp);
ASSERT(r == 0); ASSERT(r == 0);
r = uv_tcp_init(uv_default_loop(), &ctx.send2.tcp);
ASSERT(r == 0);
r = uv_tcp_bind(&ctx.send.tcp, (const struct sockaddr*) &addr, 0); r = uv_tcp_bind(&ctx.send.tcp, (const struct sockaddr*) &addr, 0);
ASSERT(r == 0); ASSERT(r == 0);
r = run_test(); r = uv_tcp_bind(&ctx.send2.tcp, (const struct sockaddr*) &addr, 0);
ASSERT(r == 0);
r = run_test(inprocess);
ASSERT(r == 0); ASSERT(r == 0);
MAKE_VALGRIND_HAPPY(); MAKE_VALGRIND_HAPPY();
return 0; return 0;
} }
TEST_IMPL(ipc_send_recv_tcp) {
return run_ipc_send_recv_tcp(0);
}
TEST_IMPL(ipc_send_recv_tcp_inprocess) {
return run_ipc_send_recv_tcp(1);
}
/* Everything here runs in a child process. */ /* Everything here runs in a child process or second thread. */
static void write2_cb(uv_write_t* req, int status) { static void write2_cb(uv_write_t* req, int status) {
ASSERT(status == 0); ASSERT(status == 0);
uv_close(&ctx.recv.handle, NULL);
uv_close((uv_handle_t*)&ctx.channel, NULL);
}
/* After two successful writes in the child process, allow the child
* process to be closed. */
if (++write2_cb_called == 2 && (is_child_process || is_in_process)) {
uv_close(&ctx2.recv.handle, NULL);
uv_close(&ctx2.recv2.handle, NULL);
uv_close((uv_handle_t*)&ctx2.channel, NULL);
uv_close((uv_handle_t*)&ctx2.listen, NULL);
}
}
static void read_cb(uv_stream_t* handle, static void read_cb(uv_stream_t* handle,
ssize_t nread, ssize_t nread,
@ -177,37 +286,102 @@ static void read_cb(uv_stream_t* handle,
uv_pipe_t* pipe; uv_pipe_t* pipe;
uv_handle_type pending; uv_handle_type pending;
int r; int r;
union handles* recv;
uv_write_t* write_req;
if (nread == UV__EOF || nread == UV__ECONNABORTED) {
return;
}
if (++read_cb_called == 2) {
recv = &ctx2.recv;
write_req = &ctx2.write_req;
} else {
recv = &ctx2.recv2;
write_req = &ctx2.write_req2;
}
pipe = (uv_pipe_t*) handle; pipe = (uv_pipe_t*) handle;
ASSERT(pipe == &ctx.channel); ASSERT(pipe == &ctx2.channel);
ASSERT(nread >= 0); ASSERT(nread >= 0);
ASSERT(1 == uv_pipe_pending_count(pipe)); ASSERT(1 == uv_pipe_pending_count(pipe));
pending = uv_pipe_pending_type(pipe); pending = uv_pipe_pending_type(pipe);
ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP); ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP);
wrbuf = uv_buf_init(".", 1);
if (pending == UV_NAMED_PIPE) if (pending == UV_NAMED_PIPE)
r = uv_pipe_init(ctx.channel.loop, &ctx.recv.pipe, 0); r = uv_pipe_init(ctx2.channel.loop, &recv->pipe, 0);
else if (pending == UV_TCP) else if (pending == UV_TCP)
r = uv_tcp_init(ctx.channel.loop, &ctx.recv.tcp); r = uv_tcp_init(ctx2.channel.loop, &recv->tcp);
else else
abort(); abort();
ASSERT(r == 0); ASSERT(r == 0);
r = uv_accept(handle, &ctx.recv.stream); r = uv_accept(handle, &recv->stream);
ASSERT(r == 0); ASSERT(r == 0);
r = uv_write2(&ctx.write_req, wrbuf = uv_buf_init(".", 1);
(uv_stream_t*)&ctx.channel, r = uv_write2(write_req,
(uv_stream_t*)&ctx2.channel,
&wrbuf, &wrbuf,
1, 1,
&ctx.recv.stream, &recv->stream,
write2_cb); write2_cb);
ASSERT(r == 0); ASSERT(r == 0);
} }
static void send_recv_start() {
int r;
ASSERT(1 == uv_is_readable((uv_stream_t*)&ctx2.channel));
ASSERT(1 == uv_is_writable((uv_stream_t*)&ctx2.channel));
ASSERT(0 == uv_is_closing((uv_handle_t*)&ctx2.channel));
r = uv_read_start((uv_stream_t*)&ctx2.channel, alloc_cb, read_cb);
ASSERT(r == 0);
}
static void listen_cb(uv_stream_t* handle, int status) {
int r;
ASSERT(handle == (uv_stream_t*)&ctx2.listen);
ASSERT(status == 0);
r = uv_accept((uv_stream_t*)&ctx2.listen, (uv_stream_t*)&ctx2.channel);
ASSERT(r == 0);
send_recv_start();
}
int run_ipc_send_recv_helper(uv_loop_t* loop, int inprocess) {
int r;
is_in_process = inprocess;
memset(&ctx2, 0, sizeof(ctx2));
r = uv_pipe_init(loop, &ctx2.listen, 0);
ASSERT(r == 0);
r = uv_pipe_init(loop, &ctx2.channel, 1);
ASSERT(r == 0);
if (inprocess) {
r = uv_pipe_bind(&ctx2.listen, TEST_PIPENAME_3);
ASSERT(r == 0);
r = uv_listen((uv_stream_t*)&ctx2.listen, SOMAXCONN, listen_cb);
ASSERT(r == 0);
} else {
r = uv_pipe_open(&ctx2.channel, 0);
ASSERT(r == 0);
send_recv_start();
}
r = uv_run(loop, UV_RUN_DEFAULT);
ASSERT(r == 0);
return 0;
}
/* stdin is a duplex channel over which a handle is sent. /* stdin is a duplex channel over which a handle is sent.
* We receive it and send it back where it came from. * We receive it and send it back where it came from.
@ -215,22 +389,23 @@ static void read_cb(uv_stream_t* handle,
int ipc_send_recv_helper(void) { int ipc_send_recv_helper(void) {
int r; int r;
memset(&ctx, 0, sizeof(ctx)); r = run_ipc_send_recv_helper(uv_default_loop(), 0);
r = uv_pipe_init(uv_default_loop(), &ctx.channel, 1);
ASSERT(r == 0); ASSERT(r == 0);
uv_pipe_open(&ctx.channel, 0); MAKE_VALGRIND_HAPPY();
ASSERT(1 == uv_is_readable((uv_stream_t*)&ctx.channel)); return 0;
ASSERT(1 == uv_is_writable((uv_stream_t*)&ctx.channel)); }
ASSERT(0 == uv_is_closing((uv_handle_t*)&ctx.channel));
r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, read_cb); void ipc_send_recv_helper_threadproc(void* arg) {
int r;
uv_loop_t loop;
r = uv_loop_init(&loop);
ASSERT(r == 0); ASSERT(r == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); r = run_ipc_send_recv_helper(&loop, 1);
ASSERT(r == 0); ASSERT(r == 0);
MAKE_VALGRIND_HAPPY(); r = uv_loop_close(&loop);
return 0; ASSERT(r == 0);
} }

10
deps/uv/test/test-list.h

@ -50,8 +50,10 @@ TEST_DECLARE (ipc_listen_before_write)
TEST_DECLARE (ipc_listen_after_write) TEST_DECLARE (ipc_listen_after_write)
#ifndef _WIN32 #ifndef _WIN32
TEST_DECLARE (ipc_send_recv_pipe) TEST_DECLARE (ipc_send_recv_pipe)
TEST_DECLARE (ipc_send_recv_pipe_inprocess)
#endif #endif
TEST_DECLARE (ipc_send_recv_tcp) TEST_DECLARE (ipc_send_recv_tcp)
TEST_DECLARE (ipc_send_recv_tcp_inprocess)
TEST_DECLARE (ipc_tcp_connection) TEST_DECLARE (ipc_tcp_connection)
TEST_DECLARE (tcp_ping_pong) TEST_DECLARE (tcp_ping_pong)
TEST_DECLARE (tcp_ping_pong_v6) TEST_DECLARE (tcp_ping_pong_v6)
@ -252,6 +254,7 @@ TEST_DECLARE (fs_unlink_readonly)
TEST_DECLARE (fs_chown) TEST_DECLARE (fs_chown)
TEST_DECLARE (fs_link) TEST_DECLARE (fs_link)
TEST_DECLARE (fs_readlink) TEST_DECLARE (fs_readlink)
TEST_DECLARE (fs_realpath)
TEST_DECLARE (fs_symlink) TEST_DECLARE (fs_symlink)
TEST_DECLARE (fs_symlink_dir) TEST_DECLARE (fs_symlink_dir)
TEST_DECLARE (fs_utime) TEST_DECLARE (fs_utime)
@ -334,6 +337,7 @@ HELPER_DECLARE (tcp6_echo_server)
HELPER_DECLARE (udp4_echo_server) HELPER_DECLARE (udp4_echo_server)
HELPER_DECLARE (pipe_echo_server) HELPER_DECLARE (pipe_echo_server)
TEST_DECLARE (queue_foreach_delete)
TASK_LIST_START TASK_LIST_START
TEST_ENTRY_CUSTOM (platform_output, 0, 1, 5000) TEST_ENTRY_CUSTOM (platform_output, 0, 1, 5000)
@ -380,8 +384,10 @@ TASK_LIST_START
TEST_ENTRY (ipc_listen_after_write) TEST_ENTRY (ipc_listen_after_write)
#ifndef _WIN32 #ifndef _WIN32
TEST_ENTRY (ipc_send_recv_pipe) TEST_ENTRY (ipc_send_recv_pipe)
TEST_ENTRY (ipc_send_recv_pipe_inprocess)
#endif #endif
TEST_ENTRY (ipc_send_recv_tcp) TEST_ENTRY (ipc_send_recv_tcp)
TEST_ENTRY (ipc_send_recv_tcp_inprocess)
TEST_ENTRY (ipc_tcp_connection) TEST_ENTRY (ipc_tcp_connection)
TEST_ENTRY (tcp_ping_pong) TEST_ENTRY (tcp_ping_pong)
@ -671,6 +677,7 @@ TASK_LIST_START
TEST_ENTRY (fs_utime) TEST_ENTRY (fs_utime)
TEST_ENTRY (fs_futime) TEST_ENTRY (fs_futime)
TEST_ENTRY (fs_readlink) TEST_ENTRY (fs_readlink)
TEST_ENTRY (fs_realpath)
TEST_ENTRY (fs_symlink) TEST_ENTRY (fs_symlink)
TEST_ENTRY (fs_symlink_dir) TEST_ENTRY (fs_symlink_dir)
TEST_ENTRY (fs_stat_missing_path) TEST_ENTRY (fs_stat_missing_path)
@ -714,6 +721,9 @@ TASK_LIST_START
TEST_ENTRY (dlerror) TEST_ENTRY (dlerror)
TEST_ENTRY (ip4_addr) TEST_ENTRY (ip4_addr)
TEST_ENTRY (ip6_addr_link_local) TEST_ENTRY (ip6_addr_link_local)
TEST_ENTRY (queue_foreach_delete)
#if 0 #if 0
/* These are for testing the test runner. */ /* These are for testing the test runner. */
TEST_ENTRY (fail_always) TEST_ENTRY (fail_always)

104
deps/uv/test/test-mutexes.c

@ -25,6 +25,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
static uv_cond_t condvar;
static uv_mutex_t mutex;
static uv_rwlock_t rwlock;
static int step;
/* The mutex and rwlock tests are really poor. /* The mutex and rwlock tests are really poor.
* They're very basic sanity checks and nothing more. * They're very basic sanity checks and nothing more.
@ -63,60 +67,96 @@ TEST_IMPL(thread_rwlock) {
} }
TEST_IMPL(thread_rwlock_trylock) { /* Call when holding |mutex|. */
uv_rwlock_t rwlock; static void synchronize_nowait(void) {
int r; step += 1;
uv_cond_signal(&condvar);
r = uv_rwlock_init(&rwlock); }
ASSERT(r == 0);
/* No locks held. */
r = uv_rwlock_trywrlock(&rwlock);
ASSERT(r == 0);
/* Write lock held. */ /* Call when holding |mutex|. */
static void synchronize(void) {
int current;
r = uv_rwlock_tryrdlock(&rwlock); synchronize_nowait();
ASSERT(r == UV_EBUSY); /* Wait for the other thread. Guard against spurious wakeups. */
r = uv_rwlock_trywrlock(&rwlock); for (current = step; current == step; uv_cond_wait(&condvar, &mutex));
ASSERT(r == UV_EBUSY); ASSERT(step == current + 1);
}
uv_rwlock_wrunlock(&rwlock);
/* No locks held. */ static void thread_rwlock_trylock_peer(void* unused) {
(void) &unused;
r = uv_rwlock_tryrdlock(&rwlock); uv_mutex_lock(&mutex);
ASSERT(r == 0);
/* One read lock held. */ /* Write lock held by other thread. */
ASSERT(UV_EBUSY == uv_rwlock_tryrdlock(&rwlock));
ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock));
synchronize();
r = uv_rwlock_tryrdlock(&rwlock); /* Read lock held by other thread. */
ASSERT(r == 0); ASSERT(0 == uv_rwlock_tryrdlock(&rwlock));
uv_rwlock_rdunlock(&rwlock);
ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock));
synchronize();
/* Two read locks held. */ /* Acquire write lock. */
ASSERT(0 == uv_rwlock_trywrlock(&rwlock));
synchronize();
r = uv_rwlock_trywrlock(&rwlock); /* Release write lock and acquire read lock. */
ASSERT(r == UV_EBUSY); uv_rwlock_wrunlock(&rwlock);
ASSERT(0 == uv_rwlock_tryrdlock(&rwlock));
synchronize();
uv_rwlock_rdunlock(&rwlock); uv_rwlock_rdunlock(&rwlock);
synchronize_nowait(); /* Signal main thread we're going away. */
uv_mutex_unlock(&mutex);
}
/* One read lock held. */
uv_rwlock_rdunlock(&rwlock); TEST_IMPL(thread_rwlock_trylock) {
uv_thread_t thread;
/* No read locks held. */ ASSERT(0 == uv_cond_init(&condvar));
ASSERT(0 == uv_mutex_init(&mutex));
ASSERT(0 == uv_rwlock_init(&rwlock));
r = uv_rwlock_trywrlock(&rwlock); uv_mutex_lock(&mutex);
ASSERT(r == 0); ASSERT(0 == uv_thread_create(&thread, thread_rwlock_trylock_peer, NULL));
/* Write lock held. */ /* Hold write lock. */
ASSERT(0 == uv_rwlock_trywrlock(&rwlock));
synchronize(); /* Releases the mutex to the other thread. */
/* Release write lock and acquire read lock. Pthreads doesn't support
* the notion of upgrading or downgrading rwlocks, so neither do we.
*/
uv_rwlock_wrunlock(&rwlock); uv_rwlock_wrunlock(&rwlock);
ASSERT(0 == uv_rwlock_tryrdlock(&rwlock));
synchronize();
/* Release read lock. */
uv_rwlock_rdunlock(&rwlock);
synchronize();
/* No locks held. */ /* Write lock held by other thread. */
ASSERT(UV_EBUSY == uv_rwlock_tryrdlock(&rwlock));
ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock));
synchronize();
/* Read lock held by other thread. */
ASSERT(0 == uv_rwlock_tryrdlock(&rwlock));
uv_rwlock_rdunlock(&rwlock);
ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock));
synchronize();
ASSERT(0 == uv_thread_join(&thread));
uv_rwlock_destroy(&rwlock); uv_rwlock_destroy(&rwlock);
uv_mutex_unlock(&mutex);
uv_mutex_destroy(&mutex);
uv_cond_destroy(&condvar);
return 0; return 0;
} }

2
deps/uv/test/test-process-title.c

@ -42,7 +42,7 @@ static void set_title(const char* title) {
TEST_IMPL(process_title) { TEST_IMPL(process_title) {
#if defined(__sun) #if defined(__sun) || defined(_AIX)
RETURN_SKIP("uv_(get|set)_process_title is not implemented."); RETURN_SKIP("uv_(get|set)_process_title is not implemented.");
#else #else
/* Check for format string vulnerabilities. */ /* Check for format string vulnerabilities. */

200
deps/uv/test/test-queue-foreach-delete.c

@ -0,0 +1,200 @@
/* Copyright The libuv project and contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
#include <string.h>
/*
* The idea behind the test is as follows.
* Certain handle types are stored in a queue internally.
* Extra care should be taken for removal of a handle from the queue while iterating over the queue.
* (i.e., QUEUE_REMOVE() called within QUEUE_FOREACH())
* This usually happens when someone closes or stops a handle from within its callback.
* So we need to check that we haven't screwed the queue on close/stop.
* To do so we do the following (for each handle type):
* 1. Create and start 3 handles (#0, #1, and #2).
*
* The queue after the start() calls:
* ..=> [queue head] <=> [handle] <=> [handle #1] <=> [handle] <=..
*
* 2. Trigger handles to fire (for uv_idle_t, uv_prepare_t, and uv_check_t there is nothing to do).
*
* 3. In the callback for the first-executed handle (#0 or #2 depending on handle type)
* stop the handle and the next one (#1).
* (for uv_idle_t, uv_prepare_t, and uv_check_t callbacks are executed in the reverse order as they are start()'ed,
* so callback for handle #2 will be called first)
*
* The queue after the stop() calls:
* correct foreach "next" |
* \/
* ..=> [queue head] <==============================> [handle] <=..
* [ ] <- [handle] <=> [handle #1] -> [ ]
* /\
* wrong foreach "next" |
*
* 4. The callback for handle #1 shouldn't be called because the handle #1 is stopped in the previous step.
* However, if QUEUE_REMOVE() is not handled properly within QUEUE_FOREACH(), the callback _will_ be called.
*/
static const unsigned first_handle_number_idle = 2;
static const unsigned first_handle_number_prepare = 2;
static const unsigned first_handle_number_check = 2;
#ifdef __linux__
static const unsigned first_handle_number_fs_event = 0;
#endif
#define DEFINE_GLOBALS_AND_CBS(name) \
static uv_##name##_t (name)[3]; \
static unsigned name##_cb_calls[3]; \
\
static void name##2_cb(uv_##name##_t* handle) { \
ASSERT(handle == &(name)[2]); \
if (first_handle_number_##name == 2) { \
uv_close((uv_handle_t*)&(name)[2], NULL); \
uv_close((uv_handle_t*)&(name)[1], NULL); \
} \
name##_cb_calls[2]++; \
} \
\
static void name##1_cb(uv_##name##_t* handle) { \
ASSERT(handle == &(name)[1]); \
ASSERT(0 && "Shouldn't be called" && (&name[0])); \
} \
\
static void name##0_cb(uv_##name##_t* handle) { \
ASSERT(handle == &(name)[0]); \
if (first_handle_number_##name == 0) { \
uv_close((uv_handle_t*)&(name)[0], NULL); \
uv_close((uv_handle_t*)&(name)[1], NULL); \
} \
name##_cb_calls[0]++; \
} \
\
static const uv_##name##_cb name##_cbs[] = { \
(uv_##name##_cb)name##0_cb, \
(uv_##name##_cb)name##1_cb, \
(uv_##name##_cb)name##2_cb, \
};
#define INIT_AND_START(name, loop) \
do { \
size_t i; \
for (i = 0; i < ARRAY_SIZE(name); i++) { \
int r; \
r = uv_##name##_init((loop), &(name)[i]); \
ASSERT(r == 0); \
\
r = uv_##name##_start(&(name)[i], name##_cbs[i]); \
ASSERT(r == 0); \
} \
} while (0)
#define END_ASSERTS(name) \
do { \
ASSERT(name##_cb_calls[0] == 1); \
ASSERT(name##_cb_calls[1] == 0); \
ASSERT(name##_cb_calls[2] == 1); \
} while (0)
DEFINE_GLOBALS_AND_CBS(idle)
DEFINE_GLOBALS_AND_CBS(prepare)
DEFINE_GLOBALS_AND_CBS(check)
#ifdef __linux__
DEFINE_GLOBALS_AND_CBS(fs_event)
static const char watched_dir[] = ".";
static uv_timer_t timer;
static unsigned helper_timer_cb_calls;
static void init_and_start_fs_events(uv_loop_t* loop) {
size_t i;
for (i = 0; i < ARRAY_SIZE(fs_event); i++) {
int r;
r = uv_fs_event_init(loop, &fs_event[i]);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event[i],
(uv_fs_event_cb)fs_event_cbs[i],
watched_dir,
0);
ASSERT(r == 0);
}
}
static void helper_timer_cb(uv_timer_t* thandle) {
int r;
uv_fs_t fs_req;
/* fire all fs_events */
r = uv_fs_utime(thandle->loop, &fs_req, watched_dir, 0, 0, NULL);
ASSERT(r == 0);
ASSERT(fs_req.result == 0);
ASSERT(fs_req.fs_type == UV_FS_UTIME);
ASSERT(strcmp(fs_req.path, watched_dir) == 0);
uv_fs_req_cleanup(&fs_req);
helper_timer_cb_calls++;
}
#endif
TEST_IMPL(queue_foreach_delete) {
uv_loop_t* loop;
int r;
loop = uv_default_loop();
INIT_AND_START(idle, loop);
INIT_AND_START(prepare, loop);
INIT_AND_START(check, loop);
#ifdef __linux__
init_and_start_fs_events(loop);
/* helper timer to trigger async and fs_event callbacks */
r = uv_timer_init(loop, &timer);
ASSERT(r == 0);
r = uv_timer_start(&timer, helper_timer_cb, 0, 0);
ASSERT(r == 0);
#endif
r = uv_run(loop, UV_RUN_NOWAIT);
ASSERT(r == 1);
END_ASSERTS(idle);
END_ASSERTS(prepare);
END_ASSERTS(check);
#ifdef __linux__
ASSERT(helper_timer_cb_calls == 1);
#endif
MAKE_VALGRIND_HAPPY();
return 0;
}

10
deps/uv/test/test-spawn.c

@ -960,11 +960,11 @@ TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) {
options.stdio_count = 2; options.stdio_count = 2;
/* Create a pipe that'll cause a collision. */ /* Create a pipe that'll cause a collision. */
_snprintf(name, snprintf(name,
sizeof(name), sizeof(name),
"\\\\.\\pipe\\uv\\%p-%d", "\\\\.\\pipe\\uv\\%p-%d",
&out, &out,
GetCurrentProcessId()); GetCurrentProcessId());
pipe_handle = CreateNamedPipeA(name, pipe_handle = CreateNamedPipeA(name,
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,

5
deps/uv/test/test-tcp-try-write.c

@ -58,6 +58,11 @@ static void connect_cb(uv_connect_t* req, int status) {
break; break;
} }
} while (1); } while (1);
do {
buf = uv_buf_init("", 0);
r = uv_try_write((uv_stream_t*) &client, &buf, 1);
} while (r != 0);
uv_close((uv_handle_t*) &client, close_cb); uv_close((uv_handle_t*) &client, close_cb);
} }

2
deps/uv/test/test-tcp-write-fail.c

@ -43,7 +43,7 @@ static void close_socket(uv_tcp_t* sock) {
r = uv_fileno((uv_handle_t*)sock, &fd); r = uv_fileno((uv_handle_t*)sock, &fd);
ASSERT(r == 0); ASSERT(r == 0);
#ifdef _WIN32 #ifdef _WIN32
r = closesocket(fd); r = closesocket((uv_os_sock_t)fd);
#else #else
r = close(fd); r = close(fd);
#endif #endif

3
deps/uv/test/test-threadpool-cancel.c

@ -276,7 +276,7 @@ TEST_IMPL(threadpool_cancel_work) {
TEST_IMPL(threadpool_cancel_fs) { TEST_IMPL(threadpool_cancel_fs) {
struct cancel_info ci; struct cancel_info ci;
uv_fs_t reqs[25]; uv_fs_t reqs[26];
uv_loop_t* loop; uv_loop_t* loop;
unsigned n; unsigned n;
uv_buf_t iov; uv_buf_t iov;
@ -305,6 +305,7 @@ TEST_IMPL(threadpool_cancel_fs) {
ASSERT(0 == uv_fs_read(loop, reqs + n++, 0, &iov, 1, 0, fs_cb)); ASSERT(0 == uv_fs_read(loop, reqs + n++, 0, &iov, 1, 0, fs_cb));
ASSERT(0 == uv_fs_scandir(loop, reqs + n++, "/", 0, fs_cb)); ASSERT(0 == uv_fs_scandir(loop, reqs + n++, "/", 0, fs_cb));
ASSERT(0 == uv_fs_readlink(loop, reqs + n++, "/", fs_cb)); ASSERT(0 == uv_fs_readlink(loop, reqs + n++, "/", fs_cb));
ASSERT(0 == uv_fs_realpath(loop, reqs + n++, "/", fs_cb));
ASSERT(0 == uv_fs_rename(loop, reqs + n++, "/", "/", fs_cb)); ASSERT(0 == uv_fs_rename(loop, reqs + n++, "/", "/", fs_cb));
ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb)); ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb));
ASSERT(0 == uv_fs_sendfile(loop, reqs + n++, 0, 0, 0, 0, fs_cb)); ASSERT(0 == uv_fs_sendfile(loop, reqs + n++, 0, 0, 0, 0, fs_cb));

3
deps/uv/test/test-tty.c

@ -153,11 +153,14 @@ TEST_IMPL(tty_file) {
ASSERT(0 == close(fd)); ASSERT(0 == close(fd));
} }
/* Bug on AIX where '/dev/random' returns 1 from isatty() */
#ifndef _AIX
fd = open("/dev/random", O_RDONLY); fd = open("/dev/random", O_RDONLY);
if (fd != -1) { if (fd != -1) {
ASSERT(UV_EINVAL == uv_tty_init(&loop, &tty, fd, 1)); ASSERT(UV_EINVAL == uv_tty_init(&loop, &tty, fd, 1));
ASSERT(0 == close(fd)); ASSERT(0 == close(fd));
} }
#endif /* _AIX */
fd = open("/dev/zero", O_RDONLY); fd = open("/dev/zero", O_RDONLY);
if (fd != -1) { if (fd != -1) {

21
deps/uv/test/test-udp-ipv6.c

@ -26,6 +26,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef __FreeBSD__
#include <sys/sysctl.h>
#endif
#define CHECK_HANDLE(handle) \ #define CHECK_HANDLE(handle) \
ASSERT((uv_udp_t*)(handle) == &server \ ASSERT((uv_udp_t*)(handle) == &server \
|| (uv_udp_t*)(handle) == &client \ || (uv_udp_t*)(handle) == &client \
@ -43,6 +47,18 @@ static int send_cb_called;
static int recv_cb_called; static int recv_cb_called;
static int close_cb_called; static int close_cb_called;
#ifdef __FreeBSD__
static int can_ipv6_ipv4_dual() {
int v6only;
size_t size = sizeof(int);
if (sysctlbyname("net.inet6.ip6.v6only", &v6only, &size, NULL, 0))
return 0;
return v6only != 1;
}
#endif
static void alloc_cb(uv_handle_t* handle, static void alloc_cb(uv_handle_t* handle,
size_t suggested_size, size_t suggested_size,
@ -150,6 +166,11 @@ TEST_IMPL(udp_dual_stack) {
if (!can_ipv6()) if (!can_ipv6())
RETURN_SKIP("IPv6 not supported"); RETURN_SKIP("IPv6 not supported");
#ifdef __FreeBSD__
if (!can_ipv6_ipv4_dual())
RETURN_SKIP("IPv6-IPv4 dual stack not supported");
#endif
do_test(ipv6_recv_ok, 0); do_test(ipv6_recv_ok, 0);
ASSERT(recv_cb_called == 1); ASSERT(recv_cb_called == 1);

2
deps/uv/test/test-udp-multicast-join6.c

@ -119,7 +119,7 @@ TEST_IMPL(udp_multicast_join6) {
ASSERT(r == 0); ASSERT(r == 0);
/* join the multicast channel */ /* join the multicast channel */
#if defined(__APPLE__) #if defined(__APPLE__) || defined(_AIX)
r = uv_udp_set_membership(&client, "ff02::1", "::1%lo0", UV_JOIN_GROUP); r = uv_udp_set_membership(&client, "ff02::1", "::1%lo0", UV_JOIN_GROUP);
#else #else
r = uv_udp_set_membership(&client, "ff02::1", NULL, UV_JOIN_GROUP); r = uv_udp_set_membership(&client, "ff02::1", NULL, UV_JOIN_GROUP);

8
deps/uv/uv.gyp

@ -104,6 +104,13 @@
'src/win/winsock.c', 'src/win/winsock.c',
'src/win/winsock.h', 'src/win/winsock.h',
], ],
'conditions': [
['MSVS_VERSION < "2015"', {
'sources': [
'src/win/snprintf.c'
]
}]
],
'link_settings': { 'link_settings': {
'libraries': [ 'libraries': [
'-ladvapi32', '-ladvapi32',
@ -340,6 +347,7 @@
'test/test-poll-close-doesnt-corrupt-stack.c', 'test/test-poll-close-doesnt-corrupt-stack.c',
'test/test-poll-closesocket.c', 'test/test-poll-closesocket.c',
'test/test-process-title.c', 'test/test-process-title.c',
'test/test-queue-foreach-delete.c',
'test/test-ref.c', 'test/test-ref.c',
'test/test-run-nowait.c', 'test/test-run-nowait.c',
'test/test-run-once.c', 'test/test-run-once.c',

Loading…
Cancel
Save