diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk index 64501832f4..cdcf5eaf99 100644 --- a/deps/uv/config-unix.mk +++ b/deps/uv/config-unix.mk @@ -27,18 +27,24 @@ LINKFLAGS=-lm CPPFLAGS += -D_LARGEFILE_SOURCE CPPFLAGS += -D_FILE_OFFSET_BITS=64 +OBJS += src/unix/async.o +OBJS += src/unix/cares.o +OBJS += src/unix/check.o OBJS += src/unix/core.o OBJS += src/unix/dl.o -OBJS += src/unix/fs.o -OBJS += src/unix/cares.o -OBJS += src/unix/udp.o OBJS += src/unix/error.o -OBJS += src/unix/thread.o +OBJS += src/unix/fs.o +OBJS += src/unix/idle.o +OBJS += src/unix/loop.o +OBJS += src/unix/pipe.o +OBJS += src/unix/prepare.o OBJS += src/unix/process.o +OBJS += src/unix/stream.o OBJS += src/unix/tcp.o -OBJS += src/unix/pipe.o +OBJS += src/unix/thread.o +OBJS += src/unix/timer.o OBJS += src/unix/tty.o -OBJS += src/unix/stream.o +OBJS += src/unix/udp.o ifeq (SunOS,$(uname_S)) EV_CONFIG=config_sunos.h @@ -51,7 +57,7 @@ endif ifeq (Darwin,$(uname_S)) EV_CONFIG=config_darwin.h EIO_CONFIG=config_darwin.h -CPPFLAGS += -Isrc/ares/config_darwin +CPPFLAGS += -D_DARWIN_USE_64_BIT_INODE=1 -Isrc/ares/config_darwin LINKFLAGS+=-framework CoreServices OBJS += src/unix/darwin.o OBJS += src/unix/kqueue.o @@ -63,7 +69,7 @@ EIO_CONFIG=config_linux.h CSTDFLAG += -D_GNU_SOURCE CPPFLAGS += -Isrc/ares/config_linux LINKFLAGS+=-ldl -lrt -OBJS += src/unix/linux/core.o src/unix/linux/inotify.o +OBJS += src/unix/linux/core.o src/unix/linux/inotify.o src/unix/linux/syscalls.o endif ifeq (FreeBSD,$(uname_S)) @@ -97,7 +103,7 @@ ifeq (OpenBSD,$(uname_S)) EV_CONFIG=config_openbsd.h EIO_CONFIG=config_openbsd.h CPPFLAGS += -Isrc/ares/config_openbsd -LINKFLAGS+= +LINKFLAGS+=-lkvm OBJS += src/unix/openbsd.o OBJS += src/unix/kqueue.o endif diff --git a/deps/uv/gyp_uv b/deps/uv/gyp_uv index 225c9768db..14a3cae764 100755 --- a/deps/uv/gyp_uv +++ b/deps/uv/gyp_uv @@ -8,7 +8,11 @@ script_dir = os.path.dirname(__file__) uv_root = os.path.normpath(script_dir) sys.path.insert(0, os.path.join(uv_root, 'build', 'gyp', 'pylib')) -import gyp +try: + import gyp +except ImportError: + print('You need to install gyp in build/gyp first. See the README.') + sys.exit(42) # Directory within which we want all generated files (including Makefiles) # to be written. diff --git a/deps/uv/include/uv-private/tree.h b/deps/uv/include/uv-private/tree.h index eb05cdcd14..f936416e3d 100644 --- a/deps/uv/include/uv-private/tree.h +++ b/deps/uv/include/uv-private/tree.h @@ -26,10 +26,12 @@ #ifndef UV_TREE_H_ #define UV_TREE_H_ -#if __GNUC__ -# define __unused __attribute__((unused)) -#else -# define __unused +#ifndef UV__UNUSED +# if __GNUC__ +# define UV__UNUSED __attribute__((unused)) +# else +# define UV__UNUSED +# endif #endif /* @@ -381,7 +383,7 @@ struct { \ #define RB_PROTOTYPE(name, type, field, cmp) \ RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) #define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ - RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static) + RB_PROTOTYPE_INTERNAL(name, type, field, cmp, UV__UNUSED static) #define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ @@ -400,7 +402,7 @@ attr struct type *name##_RB_MINMAX(struct name *, int); \ #define RB_GENERATE(name, type, field, cmp) \ RB_GENERATE_INTERNAL(name, type, field, cmp,) #define RB_GENERATE_STATIC(name, type, field, cmp) \ - RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static) + RB_GENERATE_INTERNAL(name, type, field, cmp, UV__UNUSED static) #define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ attr void \ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ diff --git a/deps/uv/include/uv-private/uv-unix.h b/deps/uv/include/uv-private/uv-unix.h index bb8e5d6b9b..e190b85345 100644 --- a/deps/uv/include/uv-private/uv-unix.h +++ b/deps/uv/include/uv-private/uv-unix.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -51,10 +52,17 @@ typedef pthread_t uv_thread_t; typedef pthread_mutex_t uv_mutex_t; typedef pthread_rwlock_t uv_rwlock_t; +/* Platform-specific definitions for uv_spawn support. */ +typedef gid_t uv_gid_t; +typedef uid_t uv_uid_t; + /* Platform-specific definitions for uv_dlopen support. */ typedef void* uv_lib_t; #define UV_DYNAMIC /* empty */ +#define UV_HANDLE_TYPE_PRIVATE /* empty */ +#define UV_REQ_TYPE_PRIVATE /* empty */ + #if __linux__ # define UV_LOOP_PRIVATE_PLATFORM_FIELDS \ /* RB_HEAD(uv__inotify_watchers, uv_fs_event_s) */ \ @@ -74,7 +82,7 @@ typedef void* uv_lib_t; * sure that we're always calling ares_process. See the warning above the \ * definition of ares_timeout(). \ */ \ - ev_timer timer; \ + uv_timer_t timer; \ /* Poll result queue */ \ eio_channel uv_eio_channel; \ struct ev_loop* ev; \ @@ -82,6 +90,7 @@ typedef void* uv_lib_t; uv_async_t uv_eio_want_poll_notifier; \ uv_async_t uv_eio_done_poll_notifier; \ uv_idle_t uv_eio_poller; \ + uv_handle_t* endgame_handles; \ UV_LOOP_PRIVATE_PLATFORM_FIELDS #define UV_REQ_BUFSML_SIZE (4) @@ -118,7 +127,7 @@ typedef void* uv_lib_t; #define UV_HANDLE_PRIVATE_FIELDS \ int fd; \ int flags; \ - ev_idle next_watcher; + uv_handle_t* endgame_next; /* that's what uv-win calls it */ \ #define UV_STREAM_PRIVATE_FIELDS \ @@ -182,11 +191,6 @@ typedef void* uv_lib_t; ev_timer timer_watcher; \ uv_timer_cb timer_cb; -#define UV_ARES_TASK_PRIVATE_FIELDS \ - int sock; \ - ev_io read_watcher; \ - ev_io write_watcher; - #define UV_GETADDRINFO_PRIVATE_FIELDS \ uv_getaddrinfo_cb cb; \ struct addrinfo* hints; \ diff --git a/deps/uv/include/uv-private/uv-win.h b/deps/uv/include/uv-private/uv-win.h index 812b274173..c55802c66f 100644 --- a/deps/uv/include/uv-private/uv-win.h +++ b/deps/uv/include/uv-private/uv-win.h @@ -115,8 +115,7 @@ typedef int (WSAAPI* LPFN_WSARECV) LPDWORD bytes, LPDWORD flags, LPWSAOVERLAPPED overlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE - completion_routine); + LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); typedef int (WSAAPI* LPFN_WSARECVFROM) (SOCKET socket, @@ -166,6 +165,10 @@ typedef struct uv_once_s { HANDLE padding; } uv_once_t; +/* Platform-specific definitions for uv_spawn support. */ +typedef unsigned char uv_uid_t; +typedef unsigned char uv_gid_t; + /* Platform-specific definitions for uv_dlopen support. */ typedef HMODULE uv_lib_t; #define UV_DYNAMIC FAR WINAPI @@ -206,15 +209,21 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); /* Counter to keep track of active udp streams */ \ unsigned int active_udp_streams; +#define UV_HANDLE_TYPE_PRIVATE \ + UV_ARES_EVENT, + #define UV_REQ_TYPE_PRIVATE \ /* TODO: remove the req suffix */ \ + UV_ACCEPT, \ UV_ARES_EVENT_REQ, \ UV_ARES_CLEANUP_REQ, \ + UV_FS_EVENT_REQ, \ UV_GETADDRINFO_REQ, \ UV_PROCESS_EXIT, \ UV_PROCESS_CLOSE, \ + UV_READ, \ UV_UDP_RECV, \ - UV_FS_EVENT_REQ + UV_WAKEUP, #define UV_REQ_PRIVATE_FIELDS \ union { \ @@ -390,13 +399,6 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); uv_handle_t* endgame_next; \ unsigned int flags; -#define UV_ARES_TASK_PRIVATE_FIELDS \ - struct uv_req_s ares_req; \ - SOCKET sock; \ - HANDLE h_wait; \ - WSAEVENT h_event; \ - HANDLE h_close_event; - #define UV_GETADDRINFO_PRIVATE_FIELDS \ struct uv_req_s getadddrinfo_req; \ uv_getaddrinfo_cb getaddrinfo_cb; \ @@ -422,20 +424,26 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); HANDLE close_handle; #define UV_FS_PRIVATE_FIELDS \ - wchar_t* pathw; \ int flags; \ DWORD sys_errno_; \ - struct _stati64 stat; \ - void* arg0; \ + union { \ + wchar_t* pathw; \ + int file; \ + }; \ union { \ struct { \ - void* arg1; \ - void* arg2; \ - void* arg3; \ + int mode; \ + wchar_t* new_pathw; \ + int file_flags; \ + int file_out; \ + void* buf; \ + size_t length; \ + int64_t offset; \ }; \ + struct _stati64 stat; \ struct { \ - ssize_t arg4; \ - ssize_t arg5; \ + double atime; \ + double mtime; \ }; \ }; diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 16098845c2..97d419d23b 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -57,8 +57,10 @@ extern "C" { #include "ares.h" -#ifndef _SSIZE_T_ -typedef intptr_t ssize_t; +#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) + typedef intptr_t ssize_t; +# define _SSIZE_T_ +# define _SSIZE_T_DEFINED #endif #if defined(__unix__) || defined(__POSIX__) || defined(__APPLE__) @@ -122,7 +124,9 @@ typedef intptr_t ssize_t; XX( 51, ELOOP, "too many symbolic links encountered") \ XX( 52, EXDEV, "cross-device link not permitted") \ XX( 53, ENOTEMPTY, "directory not empty") \ - XX( 54, ENOSPC, "no space left on device") + XX( 54, ENOSPC, "no space left on device") \ + XX( 55, EIO, "i/o error") \ + XX( 56, EROFS, "read-only file system" ) #define UV_ERRNO_GEN(val, name, s) UV_##name = val, @@ -132,37 +136,46 @@ typedef enum { } uv_err_code; #undef UV_ERRNO_GEN +#define UV_HANDLE_TYPE_MAP(XX) \ + XX(ARES_TASK, ares_task) \ + XX(ASYNC, async) \ + XX(CHECK, check) \ + XX(FS_EVENT, fs_event) \ + XX(IDLE, idle) \ + XX(NAMED_PIPE, pipe) \ + XX(PREPARE, prepare) \ + XX(PROCESS, process) \ + XX(TCP, tcp) \ + XX(TIMER, timer) \ + XX(TTY, tty) \ + XX(UDP, udp) \ + +#define UV_REQ_TYPE_MAP(XX) \ + XX(CONNECT, connect) \ + XX(WRITE, write) \ + XX(SHUTDOWN, shutdown) \ + XX(UDP_SEND, udp_send) \ + XX(FS, fs) \ + XX(WORK, work) \ + XX(GETADDRINFO, getaddrinfo) \ + typedef enum { UV_UNKNOWN_HANDLE = 0, - UV_TCP, - UV_UDP, - UV_NAMED_PIPE, - UV_TTY, +#define XX(uc, lc) UV_##uc, + UV_HANDLE_TYPE_MAP(XX) +#undef XX UV_FILE, - UV_TIMER, - UV_PREPARE, - UV_CHECK, - UV_IDLE, - UV_ASYNC, - UV_ARES_TASK, - UV_ARES_EVENT, - UV_PROCESS, - UV_FS_EVENT + UV_HANDLE_TYPE_PRIVATE + UV_HANDLE_TYPE_MAX } uv_handle_type; typedef enum { UV_UNKNOWN_REQ = 0, - UV_CONNECT, - UV_ACCEPT, - UV_READ, - UV_WRITE, - UV_SHUTDOWN, - UV_WAKEUP, - UV_UDP_SEND, - UV_FS, - UV_WORK, - UV_GETADDRINFO, +#define XX(uc, lc) UV_##uc, + UV_REQ_TYPE_MAP(XX) +#undef XX UV_REQ_TYPE_PRIVATE + UV_REQ_TYPE_MAX } uv_req_type; @@ -373,11 +386,23 @@ struct uv_handle_s { UV_HANDLE_FIELDS }; +/* + * Returns size of various handle types, useful for FFI + * bindings to allocate correct memory without copying struct + * definitions + */ +UV_EXTERN size_t uv_handle_size(uv_handle_type type); + +/* + * Returns size of request types, useful for dynamic lookup with FFI + */ +UV_EXTERN size_t uv_req_size(uv_req_type type); + /* * Returns 1 if the prepare/check/idle/timer handle has been started, 0 * otherwise. For other handle types this always returns 1. */ -UV_EXTERN int uv_is_active(uv_handle_t* handle); +UV_EXTERN int uv_is_active(const uv_handle_t* handle); /* * Request handle to be closed. close_cb will be called asynchronously after @@ -518,8 +543,18 @@ struct uv_write_s { /* * Used to determine whether a stream is readable or writable. */ -UV_EXTERN int uv_is_readable(uv_stream_t* handle); -UV_EXTERN int uv_is_writable(uv_stream_t* handle); +UV_EXTERN int uv_is_readable(const uv_stream_t* handle); +UV_EXTERN int uv_is_writable(const uv_stream_t* handle); + + +/* + * Used to determine whether a stream is closing or closed. + * + * N.B. is only valid between the initialization of the handle + * and the arrival of the close callback, and cannot be used + * to validate the handle. + */ +UV_EXTERN int uv_is_closing(const uv_handle_t* handle); /* @@ -1026,7 +1061,7 @@ UV_EXTERN void uv_ares_destroy(uv_loop_t*, ares_channel channel); struct uv_getaddrinfo_s { UV_REQ_FIELDS /* read-only */ - uv_loop_t* loop; \ + uv_loop_t* loop; UV_GETADDRINFO_PRIVATE_FIELDS }; @@ -1070,12 +1105,18 @@ typedef struct uv_process_options_s { * in. Stands for current working directory. */ char* cwd; - /* - * TODO describe how this works. + * Various flags that control how uv_spawn() behaves. See the definition of + * `enum uv_process_flags` below. */ - int windows_verbatim_arguments; - + unsigned int flags; + /* + * Libuv can change the child process' user/group id. This happens only when + * the appropriate bits are set in the flags fields. This is not supported on + * windows; uv_spawn() will fail and set the error to UV_ENOTSUP. + */ + uv_uid_t uid; + uv_gid_t gid; /* * The user should supply pointers to initialized uv_pipe_t structs for * stdio. This is used to to send or receive input from the subprocess. @@ -1086,6 +1127,30 @@ typedef struct uv_process_options_s { uv_pipe_t* stderr_stream; } uv_process_options_t; +/* + * These are the flags that can be used for the uv_process_options.flags field. + */ +enum uv_process_flags { + /* + * Set the child process' user id. The user id is supplied in the `uid` field + * of the options struct. This does not work on windows; setting this flag + * will cause uv_spawn() to fail. + */ + UV_PROCESS_SETUID = (1 << 0), + /* + * Set the child process' group id. The user id is supplied in the `gid` + * field of the options struct. This does not work on windows; setting this + * flag will cause uv_spawn() to fail. + */ + UV_PROCESS_SETGID = (1 << 1), + /* + * Do not wrap any arguments in quotes, or perform any other escaping, when + * converting the argument list into a command line string. This option is + * only meaningful on Windows systems. On unix it is silently ignored. + */ + UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2) +}; + /* * uv_process_t is a subclass of uv_handle_t */ @@ -1100,6 +1165,7 @@ struct uv_process_s { UV_EXTERN int uv_spawn(uv_loop_t*, uv_process_t*, uv_process_options_t options); + /* * Kills the process with the specified signal. The user must still * call uv_close on the process. @@ -1236,13 +1302,13 @@ UV_EXTERN int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb); UV_EXTERN int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, - void* buf, size_t length, off_t offset, uv_fs_cb cb); + void* buf, size_t length, int64_t offset, uv_fs_cb cb); UV_EXTERN int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); UV_EXTERN int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, - void* buf, size_t length, off_t offset, uv_fs_cb cb); + void* buf, size_t length, int64_t offset, uv_fs_cb cb); UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb); @@ -1269,10 +1335,10 @@ UV_EXTERN int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); UV_EXTERN int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, - off_t offset, uv_fs_cb cb); + int64_t offset, uv_fs_cb cb); UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, - uv_file in_fd, off_t in_offset, size_t length, uv_fs_cb cb); + uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb); UV_EXTERN int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb); @@ -1501,6 +1567,7 @@ struct uv_loop_s { /* Don't export the private CPP symbols. */ +#undef UV_HANDLE_TYPE_PRIVATE #undef UV_REQ_TYPE_PRIVATE #undef UV_REQ_PRIVATE_FIELDS #undef UV_STREAM_PRIVATE_FIELDS diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c new file mode 100644 index 0000000000..638774c6f7 --- /dev/null +++ b/deps/uv/src/unix/async.c @@ -0,0 +1,58 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + + +static void uv__async(EV_P_ ev_async* w, int revents) { + uv_async_t* async = container_of(w, uv_async_t, async_watcher); + + if (async->async_cb) { + async->async_cb(async, 0); + } +} + + +int uv_async_init(uv_loop_t* loop, uv_async_t* async, uv_async_cb async_cb) { + uv__handle_init(loop, (uv_handle_t*)async, UV_ASYNC); + loop->counters.async_init++; + + ev_async_init(&async->async_watcher, uv__async); + async->async_cb = async_cb; + + /* Note: This does not have symmetry with the other libev wrappers. */ + ev_async_start(loop->ev, &async->async_watcher); + ev_unref(loop->ev); + + return 0; +} + + +int uv_async_send(uv_async_t* async) { + ev_async_send(async->loop->ev, &async->async_watcher); + return 0; +} + + +void uv__async_close(uv_async_t* handle) { + ev_async_stop(handle->loop->ev, &handle->async_watcher); + ev_ref(handle->loop->ev); +} diff --git a/deps/uv/src/unix/cares.c b/deps/uv/src/unix/cares.c index 18cdefe376..03667fda39 100644 --- a/deps/uv/src/unix/cares.c +++ b/deps/uv/src/unix/cares.c @@ -31,17 +31,23 @@ * This is called once per second by loop->timer. It is used to * constantly callback into c-ares for possibly processing timeouts. */ -static void uv__ares_timeout(struct ev_loop* ev, struct ev_timer* watcher, - int revents) { - uv_loop_t* loop = ev_userdata(ev); +static void uv__ares_timeout(uv_timer_t* handle, int status) { + assert(!uv_ares_handles_empty(handle->loop)); + ares_process_fd(handle->loop->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD); +} + + +static void uv__ares_timer_start(uv_loop_t* loop) { + if (uv_is_active((uv_handle_t*)&loop->timer)) return; + uv_timer_start(&loop->timer, uv__ares_timeout, 1000, 1000); + uv_ref(loop); +} - assert(ev == loop->ev); - assert((uv_loop_t*)watcher->data == loop); - assert(watcher == &loop->timer); - assert(revents == EV_TIMER); - assert(!uv_ares_handles_empty(loop)); - ares_process_fd(loop->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD); +static void uv__ares_timer_stop(uv_loop_t* loop) { + if (!uv_is_active((uv_handle_t*)&loop->timer)) return; + uv_timer_stop(&loop->timer); + uv_unref(loop); } @@ -52,7 +58,7 @@ static void uv__ares_io(struct ev_loop* ev, struct ev_io* watcher, assert(ev == loop->ev); /* Reset the idle timer */ - ev_timer_again(ev, &loop->timer); + uv_timer_again(&loop->timer); /* Process DNS responses */ ares_process_fd(loop->channel, @@ -98,9 +104,9 @@ static void uv__ares_sockstate_cb(void* data, ares_socket_t sock, /* New socket */ /* If this is the first socket then start the timer. */ - if (!ev_is_active(&loop->timer)) { + if (!uv_is_active((uv_handle_t*)&loop->timer)) { assert(uv_ares_handles_empty(loop)); - ev_timer_again(loop->ev, &loop->timer); + uv__ares_timer_start(loop); } h = uv__ares_task_create(loop, sock); @@ -134,7 +140,7 @@ static void uv__ares_sockstate_cb(void* data, ares_socket_t sock, free(h); if (uv_ares_handles_empty(loop)) { - ev_timer_stop(loop->ev, &loop->timer); + uv__ares_timer_stop(loop); } } } @@ -169,7 +175,8 @@ int uv_ares_init_options(uv_loop_t* loop, ares_channel *channelptr, * Initialize the timeout timer. The timer won't be started until the * first socket is opened. */ - ev_timer_init(&loop->timer, uv__ares_timeout, 1., 1.); + uv_timer_init(loop, &loop->timer); + uv_unref(loop); loop->timer.data = loop; return rc; @@ -180,7 +187,7 @@ int uv_ares_init_options(uv_loop_t* loop, ares_channel *channelptr, void uv_ares_destroy(uv_loop_t* loop, ares_channel channel) { /* only allow destroy if did init */ if (loop->channel) { - ev_timer_stop(loop->ev, &loop->timer); + uv__ares_timer_stop(loop); ares_destroy(channel); loop->channel = NULL; } diff --git a/deps/uv/src/unix/check.c b/deps/uv/src/unix/check.c new file mode 100644 index 0000000000..a975210072 --- /dev/null +++ b/deps/uv/src/unix/check.c @@ -0,0 +1,80 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + + +static void uv__check(EV_P_ ev_check* w, int revents) { + uv_check_t* check = container_of(w, uv_check_t, check_watcher); + + if (check->check_cb) { + check->check_cb(check, 0); + } +} + + +int uv_check_init(uv_loop_t* loop, uv_check_t* check) { + uv__handle_init(loop, (uv_handle_t*)check, UV_CHECK); + loop->counters.check_init++; + + ev_check_init(&check->check_watcher, uv__check); + check->check_cb = NULL; + + return 0; +} + + +int uv_check_start(uv_check_t* check, uv_check_cb cb) { + int was_active = ev_is_active(&check->check_watcher); + + check->check_cb = cb; + + ev_check_start(check->loop->ev, &check->check_watcher); + + if (!was_active) { + ev_unref(check->loop->ev); + } + + return 0; +} + + +int uv_check_stop(uv_check_t* check) { + int was_active = ev_is_active(&check->check_watcher); + + ev_check_stop(check->loop->ev, &check->check_watcher); + + if (was_active) { + ev_ref(check->loop->ev); + } + + return 0; +} + + +int uv__check_active(const uv_check_t* handle) { + return ev_is_active(&handle->check_watcher); +} + + +void uv__check_close(uv_check_t* handle) { + uv_check_stop(handle); +} diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index e4d481ae4d..9602b64294 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -59,102 +59,78 @@ static uv_loop_t default_loop_struct; static uv_loop_t* default_loop_ptr; -void uv__next(EV_P_ ev_idle* watcher, int revents); static void uv__finish_close(uv_handle_t* handle); void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { - uv_async_t* async; - uv_stream_t* stream; - uv_process_t* process; - handle->close_cb = close_cb; switch (handle->type) { - case UV_NAMED_PIPE: - uv_pipe_cleanup((uv_pipe_t*)handle); - /* Fall through. */ - - case UV_TTY: - case UV_TCP: - stream = (uv_stream_t*)handle; - - uv_read_stop(stream); - ev_io_stop(stream->loop->ev, &stream->write_watcher); - - close(stream->fd); - stream->fd = -1; - - if (stream->accepted_fd >= 0) { - close(stream->accepted_fd); - stream->accepted_fd = -1; - } + case UV_NAMED_PIPE: + uv__pipe_close((uv_pipe_t*)handle); + break; - assert(!ev_is_active(&stream->read_watcher)); - assert(!ev_is_active(&stream->write_watcher)); - break; + case UV_TTY: + case UV_TCP: + uv__stream_close((uv_stream_t*)handle); + break; - case UV_UDP: - uv__udp_start_close((uv_udp_t*)handle); - break; + case UV_UDP: + uv__udp_close((uv_udp_t*)handle); + break; - case UV_PREPARE: - uv_prepare_stop((uv_prepare_t*) handle); - break; + case UV_PREPARE: + uv__prepare_close((uv_prepare_t*)handle); + break; - case UV_CHECK: - uv_check_stop((uv_check_t*) handle); - break; + case UV_CHECK: + uv__check_close((uv_check_t*)handle); + break; - case UV_IDLE: - uv_idle_stop((uv_idle_t*) handle); - break; + case UV_IDLE: + uv__idle_close((uv_idle_t*)handle); + break; - case UV_ASYNC: - async = (uv_async_t*)handle; - ev_async_stop(async->loop->ev, &async->async_watcher); - ev_ref(async->loop->ev); - break; + case UV_ASYNC: + uv__async_close((uv_async_t*)handle); + break; - case UV_TIMER: - uv_timer_stop((uv_timer_t*)handle); - break; + case UV_TIMER: + uv__timer_close((uv_timer_t*)handle); + break; - case UV_PROCESS: - process = (uv_process_t*)handle; - ev_child_stop(process->loop->ev, &process->child_watcher); - break; + case UV_PROCESS: + uv__process_close((uv_process_t*)handle); + break; - case UV_FS_EVENT: - uv__fs_event_destroy((uv_fs_event_t*)handle); - break; + case UV_FS_EVENT: + uv__fs_event_close((uv_fs_event_t*)handle); + break; - default: - assert(0); + default: + assert(0); } handle->flags |= UV_CLOSING; + handle->endgame_next = handle->loop->endgame_handles; + handle->loop->endgame_handles = handle; + uv_unref(handle->loop); +} + - /* This is used to call the on_close callback in the next loop. */ - ev_idle_start(handle->loop->ev, &handle->next_watcher); - ev_feed_event(handle->loop->ev, &handle->next_watcher, EV_IDLE); - assert(ev_is_pending(&handle->next_watcher)); +int uv_is_closing(const uv_handle_t* handle) { + return handle->flags & (UV_CLOSING | UV_CLOSED); } -static int uv__loop_init(uv_loop_t* loop, - struct ev_loop *(ev_loop_new)(unsigned int flags)) { - memset(loop, 0, sizeof(*loop)); - RB_INIT(&loop->uv_ares_handles_); -#if HAVE_KQUEUE - loop->ev = ev_loop_new(EVBACKEND_KQUEUE); -#else - loop->ev = ev_loop_new(EVFLAG_AUTO); -#endif - ev_set_userdata(loop->ev, loop); - eio_channel_init(&loop->uv_eio_channel, loop); - uv__loop_platform_init(loop); - return 0; +uv_loop_t* uv_default_loop(void) { + if (default_loop_ptr) + return default_loop_ptr; + + if (uv__loop_init(&default_loop_struct, /* default_loop? */ 1)) + return NULL; + + return (default_loop_ptr = &default_loop_struct); } @@ -164,7 +140,7 @@ uv_loop_t* uv_loop_new(void) { if ((loop = malloc(sizeof(*loop))) == NULL) return NULL; - if (uv__loop_init(loop, ev_loop_new)) { + if (uv__loop_init(loop, /* default_loop? */ 0)) { free(loop); return NULL; } @@ -174,9 +150,7 @@ uv_loop_t* uv_loop_new(void) { void uv_loop_delete(uv_loop_t* loop) { - uv_ares_destroy(loop, loop->channel); - ev_loop_destroy(loop->ev); - uv__loop_platform_delete(loop); + uv__loop_delete(loop); #ifndef NDEBUG memset(loop, -1, sizeof *loop); #endif @@ -192,26 +166,25 @@ int uv_loop_refcount(const uv_loop_t* loop) { } -uv_loop_t* uv_default_loop(void) { - if (default_loop_ptr) - return default_loop_ptr; - - if (uv__loop_init(&default_loop_struct, ev_default_loop)) - return NULL; +void uv__run(uv_loop_t* loop) { + ev_run(loop->ev, EVRUN_ONCE); - default_loop_ptr = &default_loop_struct; - return default_loop_ptr; + while (loop->endgame_handles) + uv__finish_close(loop->endgame_handles); } int uv_run(uv_loop_t* loop) { - ev_run(loop->ev, 0); + do + uv__run(loop); + while (uv_loop_refcount(loop) > 0); + return 0; } int uv_run_once(uv_loop_t* loop) { - ev_run(loop->ev, EVRUN_ONCE); + uv__run(loop); return 0; } @@ -223,11 +196,8 @@ void uv__handle_init(uv_loop_t* loop, uv_handle_t* handle, handle->loop = loop; handle->type = type; handle->flags = 0; - - ev_init(&handle->next_watcher, uv__next); - - /* Ref the loop until this handle is closed. See uv__finish_close. */ - ev_ref(loop->ev); + handle->endgame_next = NULL; + uv_ref(loop); /* unref'd in uv_close() */ } @@ -284,26 +254,12 @@ void uv__finish_close(uv_handle_t* handle) { break; } - ev_idle_stop(loop->ev, &handle->next_watcher); + + loop->endgame_handles = handle->endgame_next; if (handle->close_cb) { handle->close_cb(handle); } - - ev_unref(loop->ev); -} - - -void uv__next(EV_P_ ev_idle* w, int revents) { - uv_handle_t* handle = container_of(w, uv_handle_t, next_watcher); - - assert(revents == EV_IDLE); - - /* For now this function is only to handle the closing event, but we might - * put more stuff here later. - */ - assert(handle->flags & UV_CLOSING); - uv__finish_close(handle); } @@ -327,305 +283,22 @@ int64_t uv_now(uv_loop_t* loop) { } -void uv__req_init(uv_loop_t* loop, uv_req_t* req) { - loop->counters.req_init++; - req->type = UV_UNKNOWN_REQ; -} - - -static void uv__prepare(EV_P_ ev_prepare* w, int revents) { - uv_prepare_t* prepare = container_of(w, uv_prepare_t, prepare_watcher); - - if (prepare->prepare_cb) { - prepare->prepare_cb(prepare, 0); - } -} - - -int uv_prepare_init(uv_loop_t* loop, uv_prepare_t* prepare) { - uv__handle_init(loop, (uv_handle_t*)prepare, UV_PREPARE); - loop->counters.prepare_init++; - - ev_prepare_init(&prepare->prepare_watcher, uv__prepare); - prepare->prepare_cb = NULL; - - return 0; -} - - -int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb) { - int was_active = ev_is_active(&prepare->prepare_watcher); - - prepare->prepare_cb = cb; - - ev_prepare_start(prepare->loop->ev, &prepare->prepare_watcher); - - if (!was_active) { - ev_unref(prepare->loop->ev); - } - - return 0; -} - - -int uv_prepare_stop(uv_prepare_t* prepare) { - int was_active = ev_is_active(&prepare->prepare_watcher); - - ev_prepare_stop(prepare->loop->ev, &prepare->prepare_watcher); - - if (was_active) { - ev_ref(prepare->loop->ev); - } - return 0; -} - - - -static void uv__check(EV_P_ ev_check* w, int revents) { - uv_check_t* check = container_of(w, uv_check_t, check_watcher); - - if (check->check_cb) { - check->check_cb(check, 0); - } -} - - -int uv_check_init(uv_loop_t* loop, uv_check_t* check) { - uv__handle_init(loop, (uv_handle_t*)check, UV_CHECK); - loop->counters.check_init++; - - ev_check_init(&check->check_watcher, uv__check); - check->check_cb = NULL; - - return 0; -} - - -int uv_check_start(uv_check_t* check, uv_check_cb cb) { - int was_active = ev_is_active(&check->check_watcher); - - check->check_cb = cb; - - ev_check_start(check->loop->ev, &check->check_watcher); - - if (!was_active) { - ev_unref(check->loop->ev); - } - - return 0; -} - - -int uv_check_stop(uv_check_t* check) { - int was_active = ev_is_active(&check->check_watcher); - - ev_check_stop(check->loop->ev, &check->check_watcher); - - if (was_active) { - ev_ref(check->loop->ev); - } - - return 0; -} - - -static void uv__idle(EV_P_ ev_idle* w, int revents) { - uv_idle_t* idle = container_of(w, uv_idle_t, idle_watcher); - - if (idle->idle_cb) { - idle->idle_cb(idle, 0); - } -} - - - -int uv_idle_init(uv_loop_t* loop, uv_idle_t* idle) { - uv__handle_init(loop, (uv_handle_t*)idle, UV_IDLE); - loop->counters.idle_init++; - - ev_idle_init(&idle->idle_watcher, uv__idle); - idle->idle_cb = NULL; - - return 0; -} - - -int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb) { - int was_active = ev_is_active(&idle->idle_watcher); - - idle->idle_cb = cb; - ev_idle_start(idle->loop->ev, &idle->idle_watcher); - - if (!was_active) { - ev_unref(idle->loop->ev); - } - - return 0; -} - - -int uv_idle_stop(uv_idle_t* idle) { - int was_active = ev_is_active(&idle->idle_watcher); - - ev_idle_stop(idle->loop->ev, &idle->idle_watcher); - - if (was_active) { - ev_ref(idle->loop->ev); - } - - return 0; -} - - -int uv_is_active(uv_handle_t* handle) { +int uv_is_active(const uv_handle_t* handle) { switch (handle->type) { - case UV_TIMER: - return ev_is_active(&((uv_timer_t*)handle)->timer_watcher); - - case UV_PREPARE: - return ev_is_active(&((uv_prepare_t*)handle)->prepare_watcher); - - case UV_CHECK: - return ev_is_active(&((uv_check_t*)handle)->check_watcher); - - case UV_IDLE: - return ev_is_active(&((uv_idle_t*)handle)->idle_watcher); - - default: - return 1; - } -} - - -static void uv__async(EV_P_ ev_async* w, int revents) { - uv_async_t* async = container_of(w, uv_async_t, async_watcher); - - if (async->async_cb) { - async->async_cb(async, 0); + case UV_CHECK: + return uv__check_active((const uv_check_t*)handle); + case UV_IDLE: + return uv__idle_active((const uv_idle_t*)handle); + case UV_PREPARE: + return uv__prepare_active((const uv_prepare_t*)handle); + case UV_TIMER: + return uv__timer_active((const uv_timer_t*)handle); + default: + return 1; } } -int uv_async_init(uv_loop_t* loop, uv_async_t* async, uv_async_cb async_cb) { - uv__handle_init(loop, (uv_handle_t*)async, UV_ASYNC); - loop->counters.async_init++; - - ev_async_init(&async->async_watcher, uv__async); - async->async_cb = async_cb; - - /* Note: This does not have symmetry with the other libev wrappers. */ - ev_async_start(loop->ev, &async->async_watcher); - ev_unref(loop->ev); - - return 0; -} - - -int uv_async_send(uv_async_t* async) { - ev_async_send(async->loop->ev, &async->async_watcher); - return 0; -} - - -static int uv__timer_active(const uv_timer_t* timer) { - return timer->flags & UV_TIMER_ACTIVE; -} - - -static int uv__timer_repeating(const uv_timer_t* timer) { - return timer->flags & UV_TIMER_REPEAT; -} - - -static void uv__timer_cb(EV_P_ ev_timer* w, int revents) { - uv_timer_t* timer = container_of(w, uv_timer_t, timer_watcher); - - assert(uv__timer_active(timer)); - - if (!uv__timer_repeating(timer)) { - timer->flags &= ~UV_TIMER_ACTIVE; - ev_ref(EV_A); - } - - if (timer->timer_cb) { - timer->timer_cb(timer, 0); - } -} - - -int uv_timer_init(uv_loop_t* loop, uv_timer_t* timer) { - uv__handle_init(loop, (uv_handle_t*)timer, UV_TIMER); - loop->counters.timer_init++; - - ev_init(&timer->timer_watcher, uv__timer_cb); - - return 0; -} - - -int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb, int64_t timeout, - int64_t repeat) { - if (uv__timer_active(timer)) { - return -1; - } - - timer->timer_cb = cb; - timer->flags |= UV_TIMER_ACTIVE; - - if (repeat) - timer->flags |= UV_TIMER_REPEAT; - else - timer->flags &= ~UV_TIMER_REPEAT; - - ev_timer_set(&timer->timer_watcher, timeout / 1000.0, repeat / 1000.0); - ev_timer_start(timer->loop->ev, &timer->timer_watcher); - ev_unref(timer->loop->ev); - - return 0; -} - - -int uv_timer_stop(uv_timer_t* timer) { - if (uv__timer_active(timer)) { - ev_ref(timer->loop->ev); - } - - timer->flags &= ~(UV_TIMER_ACTIVE | UV_TIMER_REPEAT); - ev_timer_stop(timer->loop->ev, &timer->timer_watcher); - - return 0; -} - - -int uv_timer_again(uv_timer_t* timer) { - if (!uv__timer_active(timer)) { - uv__set_sys_error(timer->loop, EINVAL); - return -1; - } - - assert(uv__timer_repeating(timer)); - ev_timer_again(timer->loop->ev, &timer->timer_watcher); - return 0; -} - - -void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat) { - assert(timer->type == UV_TIMER); - timer->timer_watcher.repeat = repeat / 1000.0; - - if (repeat) - timer->flags |= UV_TIMER_REPEAT; - else - timer->flags &= ~UV_TIMER_REPEAT; -} - - -int64_t uv_timer_get_repeat(uv_timer_t* timer) { - assert(timer->type == UV_TIMER); - return (int64_t)(1000 * timer->timer_watcher.repeat); -} - - static int uv_getaddrinfo_done(eio_req* req) { uv_getaddrinfo_t* handle = req->data; struct addrinfo *res = handle->res; @@ -690,8 +363,7 @@ int uv_getaddrinfo(uv_loop_t* loop, return -1; } - uv__req_init(loop, (uv_req_t*)handle); - handle->type = UV_GETADDRINFO; + uv__req_init(loop, handle, UV_GETADDRINFO); handle->loop = loop; handle->cb = cb; @@ -767,9 +439,8 @@ int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t slen) { assert(sockfd >= 0); while (1) { -#if HAVE_SYS_ACCEPT4 - peerfd = sys_accept4(sockfd, saddr, &slen, SOCK_NONBLOCK | SOCK_CLOEXEC); - +#if __linux__ + peerfd = uv__accept4(sockfd, saddr, &slen, UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC); if (peerfd != -1) break; diff --git a/deps/uv/src/unix/cygwin.c b/deps/uv/src/unix/cygwin.c index aef8d7672e..31b069f9c4 100644 --- a/deps/uv/src/unix/cygwin.c +++ b/deps/uv/src/unix/cygwin.c @@ -79,6 +79,6 @@ int uv_fs_event_init(uv_loop_t* loop, } -void uv__fs_event_destroy(uv_fs_event_t* handle) { +void uv__fs_event_close(uv_fs_event_t* handle) { assert(0 && "implement me"); } diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c index 6b3705f6fb..e6deb3017b 100644 --- a/deps/uv/src/unix/darwin.c +++ b/deps/uv/src/unix/darwin.c @@ -73,6 +73,7 @@ uint64_t uv_hrtime() { int uv_exepath(char* buffer, size_t* size) { uint32_t usize; int result; + char* path; char* fullpath; if (!buffer || !size) { @@ -83,9 +84,11 @@ int uv_exepath(char* buffer, size_t* size) { result = _NSGetExecutablePath(buffer, &usize); if (result) return result; - fullpath = realpath(buffer, NULL); + path = (char*)malloc(2 * PATH_MAX); + fullpath = realpath(buffer, path); if (fullpath == NULL) { + free(path); return -1; } diff --git a/deps/uv/src/unix/error.c b/deps/uv/src/unix/error.c index 7ba2c89e23..aaeaf76e4f 100644 --- a/deps/uv/src/unix/error.c +++ b/deps/uv/src/unix/error.c @@ -68,6 +68,9 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case EBADF: return UV_EBADF; case EPIPE: return UV_EPIPE; case EAGAIN: return UV_EAGAIN; +#if EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: return UV_EAGAIN; +#endif case ECONNRESET: return UV_ECONNRESET; case EFAULT: return UV_EFAULT; case EMFILE: return UV_EMFILE; @@ -92,6 +95,8 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case EBUSY: return UV_EBUSY; case ENOTEMPTY: return UV_ENOTEMPTY; case ENOSPC: return UV_ENOSPC; + case EROFS: return UV_EROFS; + case ENOMEM: return UV_ENOMEM; default: return UV_UNKNOWN; } UNREACHABLE(); diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 6615516885..3417fa62b3 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -66,8 +66,7 @@ static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req, uv_fs_type fs_type, /* Make sure the thread pool is initialized. */ uv_eio_init(loop); - uv__req_init(loop, (uv_req_t*)req); - req->type = UV_FS; + uv__req_init(loop, req, UV_FS); req->loop = loop; req->fs_type = fs_type; req->cb = cb; @@ -215,7 +214,7 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file fd, void* buf, - size_t length, off_t offset, uv_fs_cb cb) { + size_t length, int64_t offset, uv_fs_cb cb) { uv_fs_req_init(loop, req, UV_FS_READ, NULL, cb); if (cb) { @@ -253,7 +252,7 @@ int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf, - size_t length, off_t offset, uv_fs_cb cb) { + size_t length, int64_t offset, uv_fs_cb cb) { uv_fs_req_init(loop, req, UV_FS_WRITE, NULL, cb); if (cb) { @@ -461,7 +460,7 @@ int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { } -int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, off_t offset, +int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int64_t offset, uv_fs_cb cb) { char* path = NULL; WRAP_EIO(UV_FS_FTRUNCATE, eio_ftruncate, ftruncate, ARGS2(file, offset)) @@ -469,7 +468,7 @@ int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, off_t offset, int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, - off_t in_offset, size_t length, uv_fs_cb cb) { + int64_t in_offset, size_t length, uv_fs_cb cb) { char* path = NULL; WRAP_EIO(UV_FS_SENDFILE, eio_sendfile, eio_sendfile_sync, ARGS4(out_fd, in_fd, in_offset, length)) @@ -497,23 +496,27 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, #if HAVE_FUTIMES -static int _futime(const uv_file file, double atime, double mtime) { +static int _futime(const uv_file fd, double atime, double mtime) { +#if __linux__ + /* utimesat() has nanosecond resolution but we stick to microseconds + * for the sake of consistency with other platforms. + */ + struct timespec ts[2]; + ts[0].tv_sec = atime; + ts[0].tv_nsec = (unsigned long)(atime * 1000000) % 1000000 * 1000; + ts[1].tv_sec = mtime; + ts[1].tv_nsec = (unsigned long)(mtime * 1000000) % 1000000 * 1000; + return uv__utimesat(fd, NULL, ts, 0); +#else struct timeval tv[2]; - - /* FIXME possible loss of precision in floating-point arithmetic? */ tv[0].tv_sec = atime; tv[0].tv_usec = (unsigned long)(atime * 1000000) % 1000000; - tv[1].tv_sec = mtime; tv[1].tv_usec = (unsigned long)(mtime * 1000000) % 1000000; - -#ifdef __sun - return futimesat(file, NULL, tv); -#else - return futimes(file, tv); -#endif + return futimes(fd, tv); +#endif /* __linux__ */ } -#endif +#endif /* HAVE_FUTIMES */ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, @@ -685,7 +688,7 @@ int uv_queue_work(uv_loop_t* loop, uv_work_t* req, uv_work_cb work_cb, uv_eio_init(loop); - uv__req_init(loop, (uv_req_t*)req); + uv__req_init(loop, req, UV_WORK); uv_ref(loop); req->loop = loop; req->data = data; diff --git a/deps/uv/src/unix/idle.c b/deps/uv/src/unix/idle.c new file mode 100644 index 0000000000..5b4cf57747 --- /dev/null +++ b/deps/uv/src/unix/idle.c @@ -0,0 +1,79 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + + +static void uv__idle(EV_P_ ev_idle* w, int revents) { + uv_idle_t* idle = container_of(w, uv_idle_t, idle_watcher); + + if (idle->idle_cb) { + idle->idle_cb(idle, 0); + } +} + + +int uv_idle_init(uv_loop_t* loop, uv_idle_t* idle) { + uv__handle_init(loop, (uv_handle_t*)idle, UV_IDLE); + loop->counters.idle_init++; + + ev_idle_init(&idle->idle_watcher, uv__idle); + idle->idle_cb = NULL; + + return 0; +} + + +int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb) { + int was_active = ev_is_active(&idle->idle_watcher); + + idle->idle_cb = cb; + ev_idle_start(idle->loop->ev, &idle->idle_watcher); + + if (!was_active) { + ev_unref(idle->loop->ev); + } + + return 0; +} + + +int uv_idle_stop(uv_idle_t* idle) { + int was_active = ev_is_active(&idle->idle_watcher); + + ev_idle_stop(idle->loop->ev, &idle->idle_watcher); + + if (was_active) { + ev_ref(idle->loop->ev); + } + + return 0; +} + + +int uv__idle_active(const uv_idle_t* handle) { + return ev_is_active(&handle->idle_watcher); +} + + +void uv__idle_close(uv_idle_t* handle) { + uv_idle_stop(handle); +} diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index bd2ee0ffd3..e8701a3f26 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -37,79 +37,9 @@ #undef HAVE_KQUEUE #undef HAVE_PORTS_FS -#if defined(__linux__) - -# undef HAVE_SYS_UTIMESAT -# undef HAVE_SYS_PIPE2 -# undef HAVE_SYS_ACCEPT4 - -# undef _GNU_SOURCE -# define _GNU_SOURCE - -# include -# include -# include -# include - -# if __NR_utimensat -# define HAVE_SYS_UTIMESAT 1 -# endif -# if __NR_pipe2 -# define HAVE_SYS_PIPE2 1 -# endif -# if __NR_accept4 -# define HAVE_SYS_ACCEPT4 1 -# endif - -# ifndef O_CLOEXEC -# define O_CLOEXEC 02000000 -# endif - -# ifndef SOCK_CLOEXEC -# define SOCK_CLOEXEC O_CLOEXEC -# endif - -# ifndef SOCK_NONBLOCK -# define SOCK_NONBLOCK O_NONBLOCK -# endif - -# if HAVE_SYS_UTIMESAT -inline static int sys_utimesat(int dirfd, - const char* path, - const struct timespec times[2], - int flags) -{ - return syscall(__NR_utimensat, dirfd, path, times, flags); -} -inline static int sys_futimes(int fd, const struct timeval times[2]) -{ - struct timespec ts[2]; - ts[0].tv_sec = times[0].tv_sec, ts[0].tv_nsec = times[0].tv_usec * 1000; - ts[1].tv_sec = times[1].tv_sec, ts[1].tv_nsec = times[1].tv_usec * 1000; - return sys_utimesat(fd, NULL, ts, 0); -} -# undef HAVE_FUTIMES -# define HAVE_FUTIMES 1 -# define futimes(fd, times) sys_futimes(fd, times) -# endif /* HAVE_SYS_FUTIMESAT */ - -# if HAVE_SYS_PIPE2 -inline static int sys_pipe2(int pipefd[2], int flags) -{ - return syscall(__NR_pipe2, pipefd, flags); -} -# endif /* HAVE_SYS_PIPE2 */ - -# if HAVE_SYS_ACCEPT4 -inline static int sys_accept4(int fd, - struct sockaddr* addr, - socklen_t* addrlen, - int flags) -{ - return syscall(__NR_accept4, fd, addr, addrlen, flags); -} -# endif /* HAVE_SYS_ACCEPT4 */ - +#if __linux__ +# include "linux/syscalls.h" +# define HAVE_FUTIMES 1 /* emulated with utimesat() */ #endif /* __linux__ */ #if defined(__sun) @@ -118,6 +48,8 @@ inline static int sys_accept4(int fd, # ifdef PORT_SOURCE_FILE # define HAVE_PORTS_FS 1 # endif +# define HAVE_FUTIMES 1 +# define futimes(fd, tv) futimesat(fd, (void*)0, tv) #endif /* __sun */ #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun) @@ -165,6 +97,15 @@ enum { UV_TIMER_REPEAT = 0x100 }; +inline static void uv__req_init(uv_loop_t* loop, + uv_req_t* req, + uv_req_type type) { + loop->counters.req_init++; + req->type = type; +} +#define uv__req_init(loop, req, type) \ + uv__req_init((loop), (uv_req_t*)(req), (type)) + /* core */ void uv__handle_init(uv_loop_t* loop, uv_handle_t* handle, uv_handle_type type); int uv__nonblock(int fd, int set) __attribute__((unused)); @@ -172,13 +113,14 @@ int uv__cloexec(int fd, int set) __attribute__((unused)); int uv__socket(int domain, int type, int protocol); int uv__dup(int fd); +/* loop */ +int uv__loop_init(uv_loop_t* loop, int default_loop); +void uv__loop_delete(uv_loop_t* loop); + /* error */ uv_err_code uv_translate_sys_error(int sys_errno); void uv_fatal_error(const int errorno, const char* syscall); -/* requests */ -void uv__req_init(uv_loop_t* loop, uv_req_t*); - /* stream */ void uv__stream_init(uv_loop_t* loop, uv_stream_t* stream, uv_handle_type type); @@ -198,28 +140,28 @@ int uv__tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay); /* pipe */ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); void uv__pipe_accept(EV_P_ ev_io* watcher, int revents); -int uv_pipe_cleanup(uv_pipe_t* handle); -/* udp */ -void uv__udp_start_close(uv_udp_t* handle); +/* various */ +int uv__check_active(const uv_check_t* handle); +int uv__idle_active(const uv_idle_t* handle); +int uv__prepare_active(const uv_prepare_t* handle); +int uv__timer_active(const uv_timer_t* handle); + +void uv__async_close(uv_async_t* handle); +void uv__check_close(uv_check_t* handle); +void uv__fs_event_close(uv_fs_event_t* handle); +void uv__idle_close(uv_idle_t* handle); +void uv__pipe_close(uv_pipe_t* handle); +void uv__prepare_close(uv_prepare_t* handle); +void uv__process_close(uv_process_t* handle); +void uv__stream_close(uv_stream_t* handle); +void uv__timer_close(uv_timer_t* handle); +void uv__udp_close(uv_udp_t* handle); void uv__udp_finish_close(uv_udp_t* handle); -/* fs */ -void uv__fs_event_destroy(uv_fs_event_t* handle); - #define UV__F_IPC (1 << 0) #define UV__F_NONBLOCK (1 << 1) int uv__make_socketpair(int fds[2], int flags); int uv__make_pipe(int fds[2], int flags); -#if __linux__ -void uv__inotify_loop_init(uv_loop_t* loop); -void uv__inotify_loop_delete(uv_loop_t* loop); -# define uv__loop_platform_init(loop) uv__inotify_loop_init(loop) -# define uv__loop_platform_delete(loop) uv__inotify_loop_delete(loop) -#else -# define uv__loop_platform_init(loop) -# define uv__loop_platform_delete(loop) -#endif - #endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index ec3ba32e82..404632329c 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -97,11 +97,6 @@ int uv_fs_event_init(uv_loop_t* loop, /* We don't support any flags yet. */ assert(!flags); - if (cb == NULL) { - uv__set_sys_error(loop, EINVAL); - return -1; - } - /* TODO open asynchronously - but how do we report back errors? */ if ((fd = open(filename, O_RDONLY)) == -1) { uv__set_sys_error(loop, errno); @@ -119,7 +114,7 @@ int uv_fs_event_init(uv_loop_t* loop, } -void uv__fs_event_destroy(uv_fs_event_t* handle) { +void uv__fs_event_close(uv_fs_event_t* handle) { uv__fs_event_stop(handle); free(handle->filename); close(handle->fd); diff --git a/deps/uv/src/unix/linux/inotify.c b/deps/uv/src/unix/linux/inotify.c index 9819f5528c..24ddbcbcee 100644 --- a/deps/uv/src/unix/linux/inotify.c +++ b/deps/uv/src/unix/linux/inotify.c @@ -21,6 +21,7 @@ #include "uv.h" #include "tree.h" #include "../internal.h" +#include "syscalls.h" #include #include @@ -31,91 +32,6 @@ #include #include -#include - -#undef HAVE_INOTIFY_INIT -#undef HAVE_INOTIFY_INIT1 -#undef HAVE_INOTIFY_ADD_WATCH -#undef HAVE_INOTIFY_RM_WATCH - -#if __NR_inotify_init -# define HAVE_INOTIFY_INIT 1 -#endif -#if __NR_inotify_init1 -# define HAVE_INOTIFY_INIT1 1 -#endif -#if __NR_inotify_add_watch -# define HAVE_INOTIFY_ADD_WATCH 1 -#endif -#if __NR_inotify_rm_watch -# define HAVE_INOTIFY_RM_WATCH 1 -#endif - -#if HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 -# undef IN_ACCESS -# undef IN_MODIFY -# undef IN_ATTRIB -# undef IN_CLOSE_WRITE -# undef IN_CLOSE_NOWRITE -# undef IN_OPEN -# undef IN_MOVED_FROM -# undef IN_MOVED_TO -# undef IN_CREATE -# undef IN_DELETE -# undef IN_DELETE_SELF -# undef IN_MOVE_SELF -# define IN_ACCESS 0x001 -# define IN_MODIFY 0x002 -# define IN_ATTRIB 0x004 -# define IN_CLOSE_WRITE 0x008 -# define IN_CLOSE_NOWRITE 0x010 -# define IN_OPEN 0x020 -# define IN_MOVED_FROM 0x040 -# define IN_MOVED_TO 0x080 -# define IN_CREATE 0x100 -# define IN_DELETE 0x200 -# define IN_DELETE_SELF 0x400 -# define IN_MOVE_SELF 0x800 -struct inotify_event { - int32_t wd; - uint32_t mask; - uint32_t cookie; - uint32_t len; - /* char name[0]; */ -}; -#endif /* HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */ - -#undef IN_CLOEXEC -#undef IN_NONBLOCK - -#if HAVE_INOTIFY_INIT1 -# define IN_CLOEXEC O_CLOEXEC -# define IN_NONBLOCK O_NONBLOCK -#endif /* HAVE_INOTIFY_INIT1 */ - -#if HAVE_INOTIFY_INIT -inline static int inotify_init(void) { - return syscall(__NR_inotify_init); -} -#endif /* HAVE_INOTIFY_INIT */ - -#if HAVE_INOTIFY_INIT1 -inline static int inotify_init1(int flags) { - return syscall(__NR_inotify_init1, flags); -} -#endif /* HAVE_INOTIFY_INIT1 */ - -#if HAVE_INOTIFY_ADD_WATCH -inline static int inotify_add_watch(int fd, const char* path, uint32_t mask) { - return syscall(__NR_inotify_add_watch, fd, path, mask); -} -#endif /* HAVE_INOTIFY_ADD_WATCH */ - -#if HAVE_INOTIFY_RM_WATCH -inline static int inotify_rm_watch(int fd, uint32_t wd) { - return syscall(__NR_inotify_rm_watch, fd, wd); -} -#endif /* HAVE_INOTIFY_RM_WATCH */ /* Don't look aghast, this is exactly how glibc's basename() works. */ @@ -135,37 +51,19 @@ static int compare_watchers(const uv_fs_event_t* a, const uv_fs_event_t* b) { RB_GENERATE_STATIC(uv__inotify_watchers, uv_fs_event_s, node, compare_watchers) -void uv__inotify_loop_init(uv_loop_t* loop) { - RB_INIT(&loop->inotify_watchers); - loop->inotify_fd = -1; -} - - -void uv__inotify_loop_delete(uv_loop_t* loop) { - if (loop->inotify_fd == -1) return; - ev_io_stop(loop->ev, &loop->inotify_read_watcher); - close(loop->inotify_fd); - loop->inotify_fd = -1; -} - - -#if HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 - static void uv__inotify_read(EV_P_ ev_io* w, int revents); static int new_inotify_fd(void) { int fd; -#if HAVE_INOTIFY_INIT1 - fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); + fd = uv__inotify_init1(UV__IN_NONBLOCK | UV__IN_CLOEXEC); if (fd != -1) return fd; if (errno != ENOSYS) return -1; -#endif - if ((fd = inotify_init()) == -1) + if ((fd = uv__inotify_init()) == -1) return -1; if (uv__cloexec(fd, 1) || uv__nonblock(fd, 1)) { @@ -216,7 +114,7 @@ static void remove_watcher(uv_fs_event_t* handle) { static void uv__inotify_read(EV_P_ ev_io* w, int revents) { - const struct inotify_event* e; + const struct uv__inotify_event* e; uv_fs_event_t* handle; uv_loop_t* uv_loop; const char* filename; @@ -243,12 +141,12 @@ static void uv__inotify_read(EV_P_ ev_io* w, int revents) { /* Now we have one or more inotify_event structs. */ for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { - e = (const struct inotify_event*)p; + e = (const struct uv__inotify_event*)p; events = 0; - if (e->mask & (IN_ATTRIB|IN_MODIFY)) + if (e->mask & (UV__IN_ATTRIB|UV__IN_MODIFY)) events |= UV_CHANGE; - if (e->mask & ~(IN_ATTRIB|IN_MODIFY)) + if (e->mask & ~(UV__IN_ATTRIB|UV__IN_MODIFY)) events |= UV_RENAME; handle = find_watcher(uv_loop, e->wd); @@ -282,15 +180,16 @@ int uv_fs_event_init(uv_loop_t* loop, if (init_inotify(loop)) return -1; - events = IN_ATTRIB - | IN_CREATE - | IN_MODIFY - | IN_DELETE - | IN_DELETE_SELF - | IN_MOVED_FROM - | IN_MOVED_TO; + events = UV__IN_ATTRIB + | UV__IN_CREATE + | UV__IN_MODIFY + | UV__IN_DELETE + | UV__IN_DELETE_SELF + | UV__IN_MOVE_SELF + | UV__IN_MOVED_FROM + | UV__IN_MOVED_TO; - wd = inotify_add_watch(loop->inotify_fd, filename, events); + wd = uv__inotify_add_watch(loop->inotify_fd, filename, events); if (wd == -1) return uv__set_sys_error(loop, errno); uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); @@ -303,30 +202,11 @@ int uv_fs_event_init(uv_loop_t* loop, } -void uv__fs_event_destroy(uv_fs_event_t* handle) { - inotify_rm_watch(handle->loop->inotify_fd, handle->fd); +void uv__fs_event_close(uv_fs_event_t* handle) { + uv__inotify_rm_watch(handle->loop->inotify_fd, handle->fd); remove_watcher(handle); handle->fd = -1; free(handle->filename); handle->filename = NULL; } - -#else /* !HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */ - -int uv_fs_event_init(uv_loop_t* loop, - uv_fs_event_t* handle, - const char* filename, - uv_fs_event_cb cb, - int flags) { - loop->counters.fs_event_init++; - uv__set_sys_error(loop, ENOSYS); - return -1; -} - - -void uv__fs_event_destroy(uv_fs_event_t* handle) { - UNREACHABLE(); -} - -#endif /* HAVE_INOTIFY_INIT || HAVE_INOTIFY_INIT1 */ diff --git a/deps/uv/src/unix/linux/syscalls.c b/deps/uv/src/unix/linux/syscalls.c new file mode 100644 index 0000000000..bdf90cf30d --- /dev/null +++ b/deps/uv/src/unix/linux/syscalls.c @@ -0,0 +1,230 @@ +/* Copyright Joyent, Inc. and other Node 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 "syscalls.h" +#include +#include +#include +#include + +#if __i386__ +# ifndef __NR_socketcall +# define __NR_socketcall 102 +# endif +#endif + +#if __arm__ +# if __thumb__ || __ARM_EABI__ +# define UV_SYSCALL_BASE 0 +# else +# define UV_SYSCALL_BASE 0x900000 +# endif +#endif /* __arm__ */ + +#ifndef __NR_accept4 +# if __x86_64__ +# define __NR_accept4 288 +# elif __i386__ + /* Nothing. Handled through socketcall(). */ +# elif __arm__ +# define __NR_accept4 (UV_SYSCALL_BASE + 366) +# endif +#endif /* __NR_accept4 */ + +#ifndef __NR_inotify_init +# if __x86_64__ +# define __NR_inotify_init 253 +# elif __i386__ +# define __NR_inotify_init 291 +# elif __arm__ +# define __NR_inotify_init (UV_SYSCALL_BASE + 316) +# endif +#endif /* __NR_inotify_init */ + +#ifndef __NR_inotify_init1 +# if __x86_64__ +# define __NR_inotify_init1 294 +# elif __i386__ +# define __NR_inotify_init1 332 +# elif __arm__ +# define __NR_inotify_init1 (UV_SYSCALL_BASE + 360) +# endif +#endif /* __NR_inotify_init1 */ + +#ifndef __NR_inotify_add_watch +# if __x86_64__ +# define __NR_inotify_add_watch 254 +# elif __i386__ +# define __NR_inotify_add_watch 292 +# elif __arm__ +# define __NR_inotify_add_watch (UV_SYSCALL_BASE + 317) +# endif +#endif /* __NR_inotify_add_watch */ + +#ifndef __NR_inotify_rm_watch +# if __x86_64__ +# define __NR_inotify_rm_watch 255 +# elif __i386__ +# define __NR_inotify_rm_watch 293 +# elif __arm__ +# define __NR_inotify_rm_watch (UV_SYSCALL_BASE + 318) +# endif +#endif /* __NR_inotify_rm_watch */ + +#ifndef __NR_pipe2 +# if __x86_64__ +# define __NR_pipe2 293 +# elif __i386__ +# define __NR_pipe2 331 +# elif __arm__ +# define __NR_pipe2 (UV_SYSCALL_BASE + 359) +# endif +#endif /* __NR_pipe2 */ + +#ifndef __NR_recvmmsg +# if __x86_64__ +# define __NR_recvmmsg 299 +# elif __i386__ +# define __NR_recvmmsg 337 +# elif __arm__ +# define __NR_recvmmsg (UV_SYSCALL_BASE + 365) +# endif +#endif /* __NR_recvmsg */ + +#ifndef __NR_sendmmsg +# if __x86_64__ +# define __NR_sendmmsg 307 +# elif __i386__ +# define __NR_sendmmsg 345 +# elif __arm__ +# define __NR_recvmmsg (UV_SYSCALL_BASE + 374) +# endif +#endif /* __NR_sendmmsg */ + +#ifndef __NR_utimensat +# if __x86_64__ +# define __NR_utimensat 280 +# elif __i386__ +# define __NR_utimensat 320 +# elif __arm__ +# define __NR_utimensat (UV_SYSCALL_BASE + 348) +# endif +#endif /* __NR_utimensat */ + + +int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) { +#if __i386__ + unsigned long args[] = { + (unsigned long) fd, + (unsigned long) addr, + (unsigned long) addrlen, + (unsigned long) flags + }; + return syscall(__NR_socketcall, 18 /* SYS_ACCEPT4 */, args); +#elif __NR_accept4 + return syscall(__NR_accept4, fd, addr, addrlen, flags); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__inotify_init(void) { +#if __NR_inotify_init + return syscall(__NR_inotify_init); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__inotify_init1(int flags) { +#if __NR_inotify_init1 + return syscall(__NR_inotify_init1, flags); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__inotify_add_watch(int fd, const char* path, __u32 mask) { +#if __NR_inotify_add_watch + return syscall(__NR_inotify_add_watch, fd, path, mask); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__inotify_rm_watch(int fd, __s32 wd) { +#if __NR_inotify_rm_watch + return syscall(__NR_inotify_rm_watch, fd, wd); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__pipe2(int pipefd[2], int flags) { +#if __NR_pipe2 + return syscall(__NR_pipe2, pipefd, flags); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__sendmmsg(int fd, + struct uv__mmsghdr* mmsg, + unsigned int vlen, + unsigned int flags) { +#if __NR_sendmmsg + return syscall(__NR_sendmmsg, fd, mmsg, vlen, flags); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__recvmmsg(int fd, + struct uv__mmsghdr* mmsg, + unsigned int vlen, + unsigned int flags, + struct timespec* timeout) { +#if __NR_recvmmsg + return syscall(__NR_recvmmsg, fd, mmsg, vlen, flags, timeout); +#else + return errno = ENOSYS, -1; +#endif +} + + +int uv__utimesat(int dirfd, + const char* path, + const struct timespec times[2], + int flags) +{ +#if __NR_utimensat + return syscall(__NR_utimensat, dirfd, path, times, flags); +#else + return errno = ENOSYS, -1; +#endif +} diff --git a/deps/uv/src/unix/linux/syscalls.h b/deps/uv/src/unix/linux/syscalls.h new file mode 100644 index 0000000000..5d42044a3b --- /dev/null +++ b/deps/uv/src/unix/linux/syscalls.h @@ -0,0 +1,87 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UV_LINUX_SYSCALL_H_ +#define UV_LINUX_SYSCALL_H_ + +#undef _GNU_SOURCE +#define _GNU_SOURCE + +#include +#include +#include + +#define UV__O_NONBLOCK 0x800 +#define UV__O_CLOEXEC 0x80000 + +#define UV__SOCK_CLOEXEC UV__O_CLOEXEC +#define UV__SOCK_NONBLOCK UV__O_NONBLOCK + +#define UV__IN_CLOEXEC UV__O_CLOEXEC +#define UV__IN_NONBLOCK UV__O_NONBLOCK + +#define UV__IN_ACCESS 0x001 +#define UV__IN_MODIFY 0x002 +#define UV__IN_ATTRIB 0x004 +#define UV__IN_CLOSE_WRITE 0x008 +#define UV__IN_CLOSE_NOWRITE 0x010 +#define UV__IN_OPEN 0x020 +#define UV__IN_MOVED_FROM 0x040 +#define UV__IN_MOVED_TO 0x080 +#define UV__IN_CREATE 0x100 +#define UV__IN_DELETE 0x200 +#define UV__IN_DELETE_SELF 0x400 +#define UV__IN_MOVE_SELF 0x800 + +struct uv__inotify_event { + __s32 wd; + __u32 mask; + __u32 cookie; + __u32 len; + /* char name[0]; */ +}; + +struct uv__mmsghdr { + struct msghdr msg_hdr; + unsigned int msg_len; +}; + +int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags); +int uv__inotify_init(void); +int uv__inotify_init1(int flags); +int uv__inotify_add_watch(int fd, const char* path, __u32 mask); +int uv__inotify_rm_watch(int fd, __s32 wd); +int uv__pipe2(int pipefd[2], int flags); +int uv__recvmmsg(int fd, + struct uv__mmsghdr* mmsg, + unsigned int vlen, + unsigned int flags, + struct timespec* timeout); +int uv__sendmmsg(int fd, + struct uv__mmsghdr* mmsg, + unsigned int vlen, + unsigned int flags); +int uv__utimesat(int dirfd, + const char* path, + const struct timespec times[2], + int flags); + +#endif /* UV_LINUX_SYSCALL_H_ */ diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c new file mode 100644 index 0000000000..5580aba3fe --- /dev/null +++ b/deps/uv/src/unix/loop.c @@ -0,0 +1,58 @@ +/* Copyright Joyent, Inc. and other Node 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 "tree.h" +#include "internal.h" +#include +#include +#include + + +int uv__loop_init(uv_loop_t* loop, int default_loop) { +#if HAVE_KQUEUE + int flags = EVBACKEND_KQUEUE; +#else + int flags = EVFLAG_AUTO; +#endif + RB_INIT(&loop->uv_ares_handles_); + loop->endgame_handles = NULL; + loop->ev = (default_loop ? ev_default_loop : ev_loop_new)(flags); + ev_set_userdata(loop->ev, loop); + eio_channel_init(&loop->uv_eio_channel, loop); +#if __linux__ + RB_INIT(&loop->inotify_watchers); + loop->inotify_fd = -1; +#endif + return 0; +} + + +void uv__loop_delete(uv_loop_t* loop) { + uv_ares_destroy(loop, loop->channel); + ev_loop_destroy(loop->ev); +#if __linux__ + if (loop->inotify_fd == -1) return; + ev_io_stop(loop->ev, &loop->inotify_read_watcher); + close(loop->inotify_fd); + loop->inotify_fd = -1; +#endif +} diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c index 3573a57105..7d0b2ec70b 100644 --- a/deps/uv/src/unix/pipe.c +++ b/deps/uv/src/unix/pipe.c @@ -146,29 +146,19 @@ out: } -int uv_pipe_cleanup(uv_pipe_t* handle) { - int saved_errno; - int status; - - saved_errno = errno; - status = -1; - +void uv__pipe_close(uv_pipe_t* handle) { if (handle->pipe_fname) { /* * Unlink the file system entity before closing the file descriptor. * Doing it the other way around introduces a race where our process * unlinks a socket with the same name that's just been created by * another thread or process. - * - * This is less of an issue now that we attach a file lock - * to the socket but it's still a best practice. */ unlink(handle->pipe_fname); free((void*)handle->pipe_fname); } - errno = saved_errno; - return status; + uv__stream_close((uv_stream_t*)handle); } @@ -254,16 +244,15 @@ void uv__pipe_accept(EV_P_ ev_io* watcher, int revents) { sockfd = uv__accept(pipe->fd, (struct sockaddr *)&saddr, sizeof saddr); if (sockfd == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - assert(0 && "EAGAIN on uv__accept(pipefd)"); - } else { + if (errno != EAGAIN && errno != EWOULDBLOCK) { uv__set_sys_error(pipe->loop, errno); + pipe->connection_cb((uv_stream_t*)pipe, -1); } } else { pipe->accepted_fd = sockfd; pipe->connection_cb((uv_stream_t*)pipe, 0); if (pipe->accepted_fd == sockfd) { - /* The user hasn't yet accepted called uv_accept() */ + /* The user hasn't called uv_accept() yet */ ev_io_stop(pipe->loop->ev, &pipe->read_watcher); } } diff --git a/deps/uv/src/unix/prepare.c b/deps/uv/src/unix/prepare.c new file mode 100644 index 0000000000..6c18fbd7fc --- /dev/null +++ b/deps/uv/src/unix/prepare.c @@ -0,0 +1,79 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + + +static void uv__prepare(EV_P_ ev_prepare* w, int revents) { + uv_prepare_t* prepare = container_of(w, uv_prepare_t, prepare_watcher); + + if (prepare->prepare_cb) { + prepare->prepare_cb(prepare, 0); + } +} + + +int uv_prepare_init(uv_loop_t* loop, uv_prepare_t* prepare) { + uv__handle_init(loop, (uv_handle_t*)prepare, UV_PREPARE); + loop->counters.prepare_init++; + + ev_prepare_init(&prepare->prepare_watcher, uv__prepare); + prepare->prepare_cb = NULL; + + return 0; +} + + +int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb) { + int was_active = ev_is_active(&prepare->prepare_watcher); + + prepare->prepare_cb = cb; + + ev_prepare_start(prepare->loop->ev, &prepare->prepare_watcher); + + if (!was_active) { + ev_unref(prepare->loop->ev); + } + + return 0; +} + + +int uv_prepare_stop(uv_prepare_t* prepare) { + int was_active = ev_is_active(&prepare->prepare_watcher); + + ev_prepare_stop(prepare->loop->ev, &prepare->prepare_watcher); + + if (was_active) { + ev_ref(prepare->loop->ev); + } + return 0; +} + + +int uv__prepare_active(const uv_prepare_t* handle) { + return ev_is_active(&handle->prepare_watcher); +} + + +void uv__prepare_close(uv_prepare_t* handle) { + uv_prepare_stop(handle); +} diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index ffe014514b..10872cce61 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -105,7 +105,7 @@ int uv__make_socketpair(int fds[2], int flags) { int uv__make_pipe(int fds[2], int flags) { -#if HAVE_SYS_PIPE2 +#if __linux__ int fl; fl = O_CLOEXEC; @@ -113,17 +113,11 @@ int uv__make_pipe(int fds[2], int flags) { if (flags & UV__F_NONBLOCK) fl |= O_NONBLOCK; - if (sys_pipe2(fds, fl) == 0) + if (uv__pipe2(fds, fl) == 0) return 0; if (errno != ENOSYS) return -1; - - /* errno == ENOSYS so maybe the kernel headers lied about - * the availability of pipe2(). This can happen if people - * build libuv against newer kernel headers than the kernel - * they actually run the software on. - */ #endif if (pipe(fds)) @@ -180,6 +174,12 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, pid_t pid; int flags; + assert(options.file != NULL); + assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS | + UV_PROCESS_SETGID | + UV_PROCESS_SETUID))); + + uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS); loop->counters.process_init++; @@ -269,6 +269,16 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, _exit(127); } + if ((options.flags & UV_PROCESS_SETGID) && setgid(options.gid)) { + perror("setgid()"); + _exit(127); + } + + if ((options.flags & UV_PROCESS_SETUID) && setuid(options.uid)) { + perror("setuid()"); + _exit(127); + } + environ = options.env; execvp(options.file, options.args); @@ -368,3 +378,8 @@ uv_err_t uv_kill(int pid, int signum) { return uv_ok_; } } + + +void uv__process_close(uv_process_t* handle) { + ev_child_stop(handle->loop->ev, &handle->child_watcher); +} diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index fd24caaa6b..b71f9bdde6 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -152,6 +152,14 @@ void uv__stream_destroy(uv_stream_t* stream) { req->cb(req, req->error ? -1 : 0); } } + + if (stream->flags & UV_SHUTTING) { + uv_shutdown_t* req = stream->shutdown_req; + if (req && req->cb) { + uv__set_artificial_error(stream->loop, UV_EINTR); + req->cb(req, -1); + } + } } @@ -179,7 +187,7 @@ void uv__server_io(EV_P_ ev_io* watcher, int revents) { fd = uv__accept(stream->fd, (struct sockaddr*)&addr, sizeof addr); if (fd < 0) { - if (errno == EAGAIN) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { /* No problem. */ return; } else if (errno == EMFILE) { @@ -291,6 +299,7 @@ static void uv__drain(uv_stream_t* stream) { assert(stream->shutdown_req); req = stream->shutdown_req; + stream->shutdown_req = NULL; if (shutdown(stream->fd, SHUT_WR)) { /* Error. Report it. User should call uv_close(). */ @@ -419,7 +428,7 @@ start: } if (n < 0) { - if (errno != EAGAIN) { + if (errno != EAGAIN && errno != EWOULDBLOCK) { /* Error */ req->error = errno; stream->write_queue_size -= uv__write_req_size(req); @@ -587,7 +596,7 @@ static void uv__read(uv_stream_t* stream) { if (nread < 0) { /* Error */ - if (errno == EAGAIN) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { /* Wait for the next one. */ if (stream->flags & UV_READING) { ev_io_start(ev, &stream->read_watcher); @@ -691,12 +700,10 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { } /* Initialize request */ - uv__req_init(stream->loop, (uv_req_t*)req); + uv__req_init(stream->loop, req, UV_SHUTDOWN); req->handle = stream; req->cb = cb; - stream->shutdown_req = req; - req->type = UV_SHUTDOWN; ((uv_handle_t*)stream)->flags |= UV_SHUTTING; @@ -801,10 +808,9 @@ int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr, } } - uv__req_init(stream->loop, (uv_req_t*)req); + uv__req_init(stream->loop, req, UV_CONNECT); req->cb = cb; req->handle = stream; - req->type = UV_CONNECT; ngx_queue_init(&req->queue); if (stream->connect_req) { @@ -878,12 +884,11 @@ int uv_write2(uv_write_t* req, uv_stream_t* stream, uv_buf_t bufs[], int bufcnt, empty_queue = (stream->write_queue_size == 0); /* Initialize the req */ - uv__req_init(stream->loop, (uv_req_t*)req); + uv__req_init(stream->loop, req, UV_WRITE); req->cb = cb; req->handle = stream; req->error = 0; req->send_handle = send_handle; - req->type = UV_WRITE; ngx_queue_init(&req->queue); if (bufcnt <= UV_REQ_BUFSML_SIZE) { @@ -997,11 +1002,28 @@ int uv_read_stop(uv_stream_t* stream) { } -int uv_is_readable(uv_stream_t* stream) { +int uv_is_readable(const uv_stream_t* stream) { return stream->flags & UV_READABLE; } -int uv_is_writable(uv_stream_t* stream) { +int uv_is_writable(const uv_stream_t* stream) { return stream->flags & UV_WRITABLE; } + + +void uv__stream_close(uv_stream_t* handle) { + uv_read_stop(handle); + ev_io_stop(handle->loop->ev, &handle->write_watcher); + + close(handle->fd); + handle->fd = -1; + + if (handle->accepted_fd >= 0) { + close(handle->accepted_fd); + handle->accepted_fd = -1; + } + + assert(!ev_is_active(&handle->read_watcher)); + assert(!ev_is_active(&handle->write_watcher)); +} diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index 37fdd8982f..0057e68651 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -37,6 +37,7 @@ #include #include #include +#include #if HAVE_PORTS_FS # include @@ -190,7 +191,7 @@ int uv_fs_event_init(uv_loop_t* loop, } -void uv__fs_event_destroy(uv_fs_event_t* handle) { +void uv__fs_event_close(uv_fs_event_t* handle) { ev_ref(handle->loop->ev); ev_io_stop(handle->loop->ev, &handle->event_watcher); close(handle->fd); @@ -213,7 +214,7 @@ int uv_fs_event_init(uv_loop_t* loop, } -void uv__fs_event_destroy(uv_fs_event_t* handle) { +void uv__fs_event_close(uv_fs_event_t* handle) { UNREACHABLE(); } @@ -239,28 +240,24 @@ uv_err_t uv_get_process_title(char* buffer, size_t size) { uv_err_t uv_resident_set_memory(size_t* rss) { - pid_t pid = getpid(); psinfo_t psinfo; - char pidpath[1024]; - FILE *f; + uv_err_t err; + int fd; - sprintf(pidpath, "/proc/%d/psinfo", (int)pid); - - f = fopen(pidpath, "r"); - if (!f) return uv__new_sys_error(errno); - - if (fread(&psinfo, sizeof(psinfo_t), 1, f) != 1) { - fclose (f); + fd = open("/proc/self/psinfo", O_RDONLY); + if (fd == -1) return uv__new_sys_error(errno); - } - /* XXX correct? */ + err = uv_ok_; - *rss = (size_t) psinfo.pr_rssize * 1024; + if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) + *rss = (size_t)psinfo.pr_rssize * 1024; + else + err = uv__new_sys_error(EINVAL); - fclose (f); + close(fd); - return uv_ok_; + return err; } diff --git a/deps/uv/src/unix/timer.c b/deps/uv/src/unix/timer.c new file mode 100644 index 0000000000..6a002294c9 --- /dev/null +++ b/deps/uv/src/unix/timer.c @@ -0,0 +1,127 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" +#include + + +static int uv__timer_repeating(const uv_timer_t* timer) { + return timer->flags & UV_TIMER_REPEAT; +} + + +static void uv__timer_cb(EV_P_ ev_timer* w, int revents) { + uv_timer_t* timer = container_of(w, uv_timer_t, timer_watcher); + + assert(uv__timer_active(timer)); + + if (!uv__timer_repeating(timer)) { + timer->flags &= ~UV_TIMER_ACTIVE; + ev_ref(EV_A); + } + + if (timer->timer_cb) { + timer->timer_cb(timer, 0); + } +} + + +int uv_timer_init(uv_loop_t* loop, uv_timer_t* timer) { + uv__handle_init(loop, (uv_handle_t*)timer, UV_TIMER); + loop->counters.timer_init++; + + ev_init(&timer->timer_watcher, uv__timer_cb); + + return 0; +} + + +int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb, int64_t timeout, + int64_t repeat) { + if (uv__timer_active(timer)) { + return -1; + } + + timer->timer_cb = cb; + timer->flags |= UV_TIMER_ACTIVE; + + if (repeat) + timer->flags |= UV_TIMER_REPEAT; + else + timer->flags &= ~UV_TIMER_REPEAT; + + ev_timer_set(&timer->timer_watcher, timeout / 1000.0, repeat / 1000.0); + ev_timer_start(timer->loop->ev, &timer->timer_watcher); + ev_unref(timer->loop->ev); + + return 0; +} + + +int uv_timer_stop(uv_timer_t* timer) { + if (uv__timer_active(timer)) { + ev_ref(timer->loop->ev); + } + + timer->flags &= ~(UV_TIMER_ACTIVE | UV_TIMER_REPEAT); + ev_timer_stop(timer->loop->ev, &timer->timer_watcher); + + return 0; +} + + +int uv_timer_again(uv_timer_t* timer) { + if (!uv__timer_active(timer)) { + uv__set_artificial_error(timer->loop, UV_EINVAL); + return -1; + } + + assert(uv__timer_repeating(timer)); + ev_timer_again(timer->loop->ev, &timer->timer_watcher); + return 0; +} + + +void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat) { + assert(timer->type == UV_TIMER); + timer->timer_watcher.repeat = repeat / 1000.0; + + if (repeat) + timer->flags |= UV_TIMER_REPEAT; + else + timer->flags &= ~UV_TIMER_REPEAT; +} + + +int64_t uv_timer_get_repeat(uv_timer_t* timer) { + assert(timer->type == UV_TIMER); + return (int64_t)(1000 * timer->timer_watcher.repeat); +} + + +int uv__timer_active(const uv_timer_t* timer) { + return timer->flags & UV_TIMER_ACTIVE; +} + + +void uv__timer_close(uv_timer_t* handle) { + uv_timer_stop(handle); +} diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index e1c7621cdd..105bdc048a 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -85,7 +85,7 @@ static void uv__udp_stop_write_watcher(uv_udp_t* handle) { } -void uv__udp_start_close(uv_udp_t* handle) { +void uv__udp_close(uv_udp_t* handle) { uv__udp_stop_write_watcher(handle); uv__udp_stop_read_watcher(handle); close(handle->fd); @@ -437,14 +437,13 @@ static int uv__udp_send(uv_udp_send_t* req, if (uv__udp_maybe_deferred_bind(handle, addr->sa_family)) return -1; - uv__req_init(handle->loop, (uv_req_t*)req); + uv__req_init(handle->loop, req, UV_UDP_SEND); memcpy(&req->addr, addr, addrlen); req->addrlen = addrlen; req->send_cb = send_cb; req->handle = handle; req->bufcnt = bufcnt; - req->type = UV_UDP_SEND; if (bufcnt <= UV_REQ_BUFSML_SIZE) { req->bufs = req->bufsml; @@ -530,21 +529,6 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, } -#define X(name, level, option) \ - int uv_udp_set_##name(uv_udp_t* handle, int flag) { \ - if (setsockopt(handle->fd, level, option, &flag, sizeof(flag))) { \ - uv__set_sys_error(handle->loop, errno); \ - return -1; \ - } \ - return 0; \ - } - -X(broadcast, SOL_SOCKET, SO_BROADCAST) -X(ttl, IPPROTO_IP, IP_TTL) - -#undef X - - static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) { #if __sun char arg = val; @@ -552,17 +536,30 @@ static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) { int arg = val; #endif -#if __sun - if (val < 0 || val > 255) { - uv__set_sys_error(handle->loop, EINVAL); - return -1; - } -#endif + if (val < 0 || val > 255) + return uv__set_sys_error(handle->loop, EINVAL); - if (setsockopt(handle->fd, IPPROTO_IP, option, &arg, sizeof(arg))) { - uv__set_sys_error(handle->loop, errno); - return -1; - } + if (setsockopt(handle->fd, IPPROTO_IP, option, &arg, sizeof(arg))) + return uv__set_sys_error(handle->loop, errno); + + return 0; +} + + +int uv_udp_set_broadcast(uv_udp_t* handle, int on) { + if (setsockopt(handle->fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on))) + return uv__set_sys_error(handle->loop, errno); + + return 0; +} + + +int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { + if (ttl < 1 || ttl > 255) + return uv__set_sys_error(handle->loop, EINVAL); + + if (setsockopt(handle->fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl))) + return uv__set_sys_error(handle->loop, errno); return 0; } diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 2e424a9cd6..c8192bd7db 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -32,6 +32,25 @@ #include "ares/inet_net_pton.h" #include "ares/inet_ntop.h" +#define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t); + +size_t uv_handle_size(uv_handle_type type) { + switch (type) { + UV_HANDLE_TYPE_MAP(XX) + default: + return -1; + } +} + +size_t uv_req_size(uv_req_type type) { + switch(type) { + UV_REQ_TYPE_MAP(XX) + default: + return -1; + } +} + +#undef XX size_t uv_strlcpy(char* dst, const char* src, size_t size) { size_t n; diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index e1f16b6cd3..e82f584272 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -35,7 +35,17 @@ struct uv_ares_task_s { UV_HANDLE_FIELDS - UV_ARES_TASK_PRIVATE_FIELDS +#if _WIN32 + struct uv_req_s ares_req; + SOCKET sock; + HANDLE h_wait; + WSAEVENT h_event; + HANDLE h_close_event; +#else + int sock; + ev_io read_watcher; + ev_io write_watcher; +#endif RB_ENTRY(uv_ares_task_s) node; }; diff --git a/deps/uv/src/win/async.c b/deps/uv/src/win/async.c index ee5faea272..b68a868054 100644 --- a/deps/uv/src/win/async.c +++ b/deps/uv/src/win/async.c @@ -118,10 +118,10 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, assert(req->type == UV_WAKEUP); handle->async_sent = 0; - if (handle->async_cb) { + + if (!(handle->flags & UV_HANDLE_CLOSING)) { handle->async_cb((uv_async_t*) handle, 0); - } - if (handle->flags & UV_HANDLE_CLOSING) { + } else { uv_want_endgame(loop, (uv_handle_t*)handle); } } diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index 1983361bad..1358cb29cb 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -91,6 +91,8 @@ static void uv_loop_init(uv_loop_t* loop) { loop->active_udp_streams = 0; loop->last_err = uv_ok_; + + memset(&loop->counters, 0, sizeof loop->counters); } diff --git a/deps/uv/src/win/dl.c b/deps/uv/src/win/dl.c index a7d4ced46c..08374d37fb 100644 --- a/deps/uv/src/win/dl.c +++ b/deps/uv/src/win/dl.c @@ -35,7 +35,7 @@ uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) { return uv__new_sys_error(saved_errno); } - handle = LoadLibraryW(filename_w); + handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (handle == NULL) { saved_errno = GetLastError(); return uv__new_sys_error(saved_errno); diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c index 7bdc3cda39..499abe3ead 100644 --- a/deps/uv/src/win/error.c +++ b/deps/uv/src/win/error.c @@ -68,6 +68,8 @@ uv_err_code uv_translate_sys_error(int sys_errno) { switch (sys_errno) { case ERROR_SUCCESS: return UV_OK; case ERROR_FILE_NOT_FOUND: return UV_ENOENT; + case ERROR_INVALID_NAME: return UV_ENOENT; + case ERROR_MOD_NOT_FOUND: return UV_ENOENT; case ERROR_PATH_NOT_FOUND: return UV_ENOENT; case ERROR_ACCESS_DENIED: return UV_EPERM; case ERROR_NOACCESS: return UV_EACCES; @@ -109,6 +111,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case ERROR_EA_TABLE_FULL: return UV_ENOSPC; case ERROR_END_OF_MEDIA: return UV_ENOSPC; case ERROR_HANDLE_DISK_FULL: return UV_ENOSPC; + case ERROR_WRITE_PROTECT: return UV_EROFS; case ERROR_NOT_CONNECTED: return UV_ENOTCONN; case WSAENOTCONN: return UV_ENOTCONN; case ERROR_DIR_NOT_EMPTY: return UV_ENOTEMPTY; diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 507336eed4..3cbb66f242 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -34,8 +34,8 @@ #include "internal.h" #define UV_FS_ASYNC_QUEUED 0x0001 -#define UV_FS_FREE_ARG0 0x0002 -#define UV_FS_FREE_ARG1 0x0004 +#define UV_FS_FREE_PATH 0x0002 +#define UV_FS_FREE_NEW_PATH 0x0004 #define UV_FS_FREE_PTR 0x0008 #define UV_FS_CLEANEDUP 0x0010 @@ -51,31 +51,6 @@ return -1; \ } -#define STRDUP_ARG(req, i) \ - req->arg##i = (void*)strdup((const char*)req->arg##i); \ - if (!req->arg##i) { \ - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); \ - } \ - req->flags |= UV_FS_FREE_ARG##i; - -#define SET_ALLOCED_ARG(req, i) \ - req->flags |= UV_FS_FREE_ARG##i; - -#define WRAP_REQ_ARGS1(req, a0) \ - req->arg0 = (void*)a0; - -#define WRAP_REQ_ARGS2(req, a0, a1) \ - WRAP_REQ_ARGS1(req, a0) \ - req->arg1 = (void*)a1; - -#define WRAP_REQ_ARGS3(req, a0, a1, a2) \ - WRAP_REQ_ARGS2(req, a0, a1) \ - req->arg2 = (void*)a2; - -#define WRAP_REQ_ARGS4(req, a0, a1, a2, a3) \ - WRAP_REQ_ARGS3(req, a0, a1, a2) \ - req->arg3 = (void*)a3; - #define QUEUE_FS_TP_JOB(loop, req) \ if (!QueueUserWorkItem(&uv_fs_thread_proc, \ req, \ @@ -289,7 +264,7 @@ void fs__close(uv_fs_t* req, uv_file file) { void fs__read(uv_fs_t* req, uv_file file, void *buf, size_t length, - off_t offset) { + int64_t offset) { HANDLE handle; OVERLAPPED overlapped, *overlapped_ptr; LARGE_INTEGER offset_; @@ -335,7 +310,7 @@ void fs__read(uv_fs_t* req, uv_file file, void *buf, size_t length, void fs__write(uv_fs_t* req, uv_file file, void *buf, size_t length, - off_t offset) { + int64_t offset) { HANDLE handle; OVERLAPPED overlapped, *overlapped_ptr; LARGE_INTEGER offset_; @@ -597,31 +572,34 @@ void fs__fsync(uv_fs_t* req, uv_file file) { } -void fs__ftruncate(uv_fs_t* req, uv_file file, off_t offset) { +void fs__ftruncate(uv_fs_t* req, uv_file file, int64_t offset) { int result; VERIFY_UV_FILE(file, req); - result = _chsize(file, offset); + result = _chsize_s(file, offset); SET_REQ_RESULT(req, result); } void fs__sendfile(uv_fs_t* req, uv_file out_file, uv_file in_file, - off_t in_offset, size_t length) { + int64_t in_offset, size_t length) { const size_t max_buf_size = 65536; size_t buf_size = length < max_buf_size ? length : max_buf_size; int n, result = 0; + int64_t result_offset = 0; char* buf = (char*)malloc(buf_size); if (!buf) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } if (in_offset != -1) { - result = _lseek(in_file, in_offset, SEEK_SET); + result_offset = _lseeki64(in_file, in_offset, SEEK_SET); } - if (result != -1) { + if (result_offset == -1) { + result = -1; + } else { while (length > 0) { n = _read(in_file, buf, length < buf_size ? length : buf_size); if (n == 0) { @@ -868,78 +846,66 @@ static DWORD WINAPI uv_fs_thread_proc(void* parameter) { switch (req->fs_type) { case UV_FS_OPEN: - fs__open(req, req->pathw, (int)req->arg0, (int)req->arg1); + fs__open(req, req->pathw, req->file_flags, (int)req->mode); break; case UV_FS_CLOSE: - fs__close(req, (uv_file)req->arg0); + fs__close(req, req->file); break; case UV_FS_READ: - fs__read(req, - (uv_file) req->arg0, - req->arg1, - (size_t) req->arg2, - (off_t) req->arg3); + fs__read(req, req->file, req->buf, req->length, req->offset); break; case UV_FS_WRITE: - fs__write(req, - (uv_file)req->arg0, - req->arg1, - (size_t) req->arg2, - (off_t) req->arg3); + fs__write(req, req->file, req->buf, req->length, req->offset); break; case UV_FS_UNLINK: fs__unlink(req, req->pathw); break; case UV_FS_MKDIR: - fs__mkdir(req, req->pathw, (int)req->arg0); + fs__mkdir(req, req->pathw, req->mode); break; case UV_FS_RMDIR: fs__rmdir(req, req->pathw); break; case UV_FS_READDIR: - fs__readdir(req, req->pathw, (int)req->arg0); + fs__readdir(req, req->pathw, req->file_flags); break; case UV_FS_STAT: case UV_FS_LSTAT: fs__stat(req, req->pathw); break; case UV_FS_FSTAT: - fs__fstat(req, (uv_file)req->arg0); + fs__fstat(req, req->file); break; case UV_FS_RENAME: - fs__rename(req, req->pathw, (const wchar_t*)req->arg0); + fs__rename(req, req->pathw, req->new_pathw); break; case UV_FS_FSYNC: case UV_FS_FDATASYNC: - fs__fsync(req, (uv_file)req->arg0); + fs__fsync(req, req->file); break; case UV_FS_FTRUNCATE: - fs__ftruncate(req, (uv_file)req->arg0, (off_t)req->arg1); + fs__ftruncate(req, req->file, req->offset); break; case UV_FS_SENDFILE: - fs__sendfile(req, - (uv_file) req->arg0, - (uv_file) req->arg1, - (off_t) req->arg2, - (size_t) req->arg3); + fs__sendfile(req, req->file_out, req->file, req->offset, req->length); break; case UV_FS_CHMOD: - fs__chmod(req, req->pathw, (int)req->arg0); + fs__chmod(req, req->pathw, req->mode); break; case UV_FS_FCHMOD: - fs__fchmod(req, (uv_file)req->arg0, (int)req->arg1); + fs__fchmod(req, req->file, req->mode); break; case UV_FS_UTIME: - fs__utime(req, req->pathw, req->arg4, req->arg5); + fs__utime(req, req->pathw, req->atime, req->mtime); break; case UV_FS_FUTIME: - fs__futime(req, (uv_file)req->arg0, req->arg4, req->arg5); + fs__futime(req, req->file, req->atime, req->mtime); break; case UV_FS_LINK: - fs__link(req, req->pathw, (const wchar_t*)req->arg0); + fs__link(req, req->pathw, req->new_pathw); break; case UV_FS_SYMLINK: - fs__symlink(req, req->pathw, (const wchar_t*)req->arg0, (int)req->arg1); + fs__symlink(req, req->pathw, req->new_pathw, req->file_flags); break; case UV_FS_READLINK: fs__readlink(req, req->pathw); @@ -968,7 +934,8 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, if (cb) { uv_fs_req_init_async(loop, req, UV_FS_OPEN, path, pathw, cb); - WRAP_REQ_ARGS2(req, flags, mode); + req->file_flags = flags; + req->mode = mode; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_OPEN); @@ -985,7 +952,7 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { if (cb) { uv_fs_req_init_async(loop, req, UV_FS_CLOSE, NULL, NULL, cb); - WRAP_REQ_ARGS1(req, file); + req->file = file; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_CLOSE); @@ -999,10 +966,13 @@ int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf, - size_t length, off_t offset, uv_fs_cb cb) { + size_t length, int64_t offset, uv_fs_cb cb) { if (cb) { uv_fs_req_init_async(loop, req, UV_FS_READ, NULL, NULL, cb); - WRAP_REQ_ARGS4(req, file, buf, length, offset); + req->file = file; + req->buf = buf; + req->length = length; + req->offset = offset; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_READ); @@ -1016,10 +986,13 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf, int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf, - size_t length, off_t offset, uv_fs_cb cb) { + size_t length, int64_t offset, uv_fs_cb cb) { if (cb) { uv_fs_req_init_async(loop, req, UV_FS_WRITE, NULL, NULL, cb); - WRAP_REQ_ARGS4(req, file, buf, length, offset); + req->file = file; + req->buf = buf; + req->length = length; + req->offset = offset; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_WRITE); @@ -1065,7 +1038,7 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, if (cb) { uv_fs_req_init_async(loop, req, UV_FS_MKDIR, path, pathw, cb); - WRAP_REQ_ARGS1(req, mode); + req->mode = mode; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_MKDIR); @@ -1111,7 +1084,7 @@ int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, if (cb) { uv_fs_req_init_async(loop, req, UV_FS_READDIR, path, pathw, cb); - WRAP_REQ_ARGS1(req, flags); + req->file_flags = flags; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_READDIR); @@ -1137,8 +1110,8 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, if (cb) { uv_fs_req_init_async(loop, req, UV_FS_LINK, path, pathw, cb); - WRAP_REQ_ARGS1(req, new_pathw); - SET_ALLOCED_ARG(req, 0); + req->new_pathw = new_pathw; + req->flags |= UV_FS_FREE_NEW_PATH; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_LINK); @@ -1165,8 +1138,8 @@ int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, if (cb) { uv_fs_req_init_async(loop, req, UV_FS_SYMLINK, path, pathw, cb); - WRAP_REQ_ARGS2(req, new_pathw, flags); - SET_ALLOCED_ARG(req, 0); + req->new_pathw = new_pathw; + req->flags |= UV_FS_FREE_NEW_PATH; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_SYMLINK); @@ -1214,7 +1187,6 @@ int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, int uid, if (cb) { uv_fs_req_init_async(loop, req, UV_FS_CHOWN, path, pathw, cb); - WRAP_REQ_ARGS2(req, uid, gid); QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_CHOWN); @@ -1232,7 +1204,6 @@ int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, int uid, int gid, uv_fs_cb cb) { if (cb) { uv_fs_req_init_async(loop, req, UV_FS_FCHOWN, NULL, NULL, cb); - WRAP_REQ_ARGS3(req, file, uid, gid); QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_FCHOWN); @@ -1335,7 +1306,7 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { if (cb) { uv_fs_req_init_async(loop, req, UV_FS_FSTAT, NULL, NULL, cb); - WRAP_REQ_ARGS1(req, file); + req->file = file; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_FSTAT); @@ -1360,8 +1331,8 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, if (cb) { uv_fs_req_init_async(loop, req, UV_FS_RENAME, path, pathw, cb); - WRAP_REQ_ARGS1(req, new_pathw); - SET_ALLOCED_ARG(req, 0); + req->new_pathw = new_pathw; + req->flags |= UV_FS_FREE_NEW_PATH; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_RENAME); @@ -1379,7 +1350,7 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { if (cb) { uv_fs_req_init_async(loop, req, UV_FS_FDATASYNC, NULL, NULL, cb); - WRAP_REQ_ARGS1(req, file); + req->file = file; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_FDATASYNC); @@ -1395,7 +1366,7 @@ int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { if (cb) { uv_fs_req_init_async(loop, req, UV_FS_FSYNC, NULL, NULL, cb); - WRAP_REQ_ARGS1(req, file); + req->file = file; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_FSYNC); @@ -1409,10 +1380,11 @@ int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, - off_t offset, uv_fs_cb cb) { + int64_t offset, uv_fs_cb cb) { if (cb) { uv_fs_req_init_async(loop, req, UV_FS_FTRUNCATE, NULL, NULL, cb); - WRAP_REQ_ARGS2(req, file, offset); + req->file = file; + req->offset = offset; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_FTRUNCATE); @@ -1426,10 +1398,13 @@ int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, - uv_file in_fd, off_t in_offset, size_t length, uv_fs_cb cb) { + uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb) { if (cb) { uv_fs_req_init_async(loop, req, UV_FS_SENDFILE, NULL, NULL, cb); - WRAP_REQ_ARGS4(req, out_fd, in_fd, in_offset, length); + req->file_out = out_fd; + req->file = in_fd; + req->offset = in_offset; + req->length = length; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_SENDFILE); @@ -1452,7 +1427,7 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, if (cb) { uv_fs_req_init_async(loop, req, UV_FS_CHMOD, path, pathw, cb); - WRAP_REQ_ARGS1(req, mode); + req->mode = mode; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_CHMOD); @@ -1470,7 +1445,8 @@ int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb) { if (cb) { uv_fs_req_init_async(loop, req, UV_FS_FCHMOD, NULL, NULL, cb); - WRAP_REQ_ARGS2(req, file, mode); + req->file = file; + req->mode = mode; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_FCHMOD); @@ -1493,8 +1469,8 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, if (cb) { uv_fs_req_init_async(loop, req, UV_FS_UTIME, path, pathw, cb); - req->arg4 = (ssize_t)atime; - req->arg5 = (ssize_t)mtime; + req->atime = atime; + req->mtime = mtime; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_UTIME); @@ -1512,9 +1488,9 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb) { if (cb) { uv_fs_req_init_async(loop, req, UV_FS_FUTIME, NULL, NULL, cb); - WRAP_REQ_ARGS1(req, file); - req->arg4 = (ssize_t)atime; - req->arg5 = (ssize_t)mtime; + req->file = file; + req->atime = atime; + req->mtime = mtime; QUEUE_FS_TP_JOB(loop, req); } else { uv_fs_req_init_sync(loop, req, UV_FS_FUTIME); @@ -1541,14 +1517,14 @@ void uv_fs_req_cleanup(uv_fs_t* req) { return; } - if (req->flags & UV_FS_FREE_ARG0 && req->arg0) { - free(req->arg0); - req->arg0 = NULL; + if (req->flags & UV_FS_FREE_PATH && req->pathw) { + free(req->pathw); + req->pathw = NULL; } - if (req->flags & UV_FS_FREE_ARG1 && req->arg1) { - free(req->arg1); - req->arg1 = NULL; + if (req->flags & UV_FS_FREE_NEW_PATH && req->new_pathw) { + free(req->new_pathw); + req->new_pathw = NULL; } if (req->flags & UV_FS_FREE_PTR && req->ptr) { @@ -1562,11 +1538,6 @@ void uv_fs_req_cleanup(uv_fs_t* req) { req->path = NULL; } - if (req->pathw) { - free(req->pathw); - req->pathw = NULL; - } - if (req->flags & UV_FS_ASYNC_QUEUED) { uv_unref(loop); } diff --git a/deps/uv/src/win/handle.c b/deps/uv/src/win/handle.c index 2e053b00d3..797b0716c6 100644 --- a/deps/uv/src/win/handle.c +++ b/deps/uv/src/win/handle.c @@ -56,7 +56,7 @@ uv_handle_type uv_guess_handle(uv_file file) { } -int uv_is_active(uv_handle_t* handle) { +int uv_is_active(const uv_handle_t* handle) { switch (handle->type) { case UV_TIMER: case UV_IDLE: @@ -154,6 +154,11 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) { } +int uv_is_closing(const uv_handle_t* handle) { + return handle->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED); +} + + void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) { if (!(handle->flags & UV_HANDLE_ENDGAME_QUEUED)) { handle->flags |= UV_HANDLE_ENDGAME_QUEUED; diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index 470aed1c82..7cc469dcdf 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -150,6 +150,8 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info, int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, LPWSAPROTOCOL_INFOW protocol_info); +void uv_tcp_close(uv_tcp_t* tcp); + /* * UDP @@ -279,7 +281,8 @@ void uv_process_work_req(uv_loop_t* loop, uv_work_t* req); /* * FS Event */ -void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, uv_fs_event_t* handle); +void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, + uv_fs_event_t* handle); void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle); void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle); diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index 43aff62610..35da85e6ed 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -161,7 +161,7 @@ static HANDLE open_named_pipe(WCHAR* name, DWORD* duplex_flags) { int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, char* name, size_t nameSize) { HANDLE pipeHandle; - int errno; + int errorno; int err; char* ptr = (char*)handle; @@ -178,9 +178,9 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access, break; } - errno = GetLastError(); - if (errno != ERROR_PIPE_BUSY && errno != ERROR_ACCESS_DENIED) { - uv__set_sys_error(loop, errno); + errorno = GetLastError(); + if (errorno != ERROR_PIPE_BUSY && errorno != ERROR_ACCESS_DENIED) { + uv__set_sys_error(loop, errorno); err = -1; goto done; } @@ -259,7 +259,6 @@ static int uv_set_pipe_handle(uv_loop_t* loop, uv_pipe_t* handle, static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) { - int errno; uv_loop_t* loop; uv_pipe_t* handle; uv_shutdown_t* req; @@ -407,7 +406,7 @@ void uv_pipe_pending_instances(uv_pipe_t* handle, int count) { /* Creates a pipe server. */ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { uv_loop_t* loop = handle->loop; - int i, errno, nameSize; + int i, errorno, nameSize; uv_pipe_accept_t* req; if (handle->flags & UV_HANDLE_BOUND) { @@ -462,13 +461,13 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL); if (handle->accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) { - errno = GetLastError(); - if (errno == ERROR_ACCESS_DENIED) { - uv__set_error(loop, UV_EADDRINUSE, errno); - } else if (errno == ERROR_PATH_NOT_FOUND || errno == ERROR_INVALID_NAME) { - uv__set_error(loop, UV_EACCES, errno); + errorno = GetLastError(); + if (errorno == ERROR_ACCESS_DENIED) { + uv__set_error(loop, UV_EADDRINUSE, errorno); + } else if (errorno == ERROR_PATH_NOT_FOUND || errorno == ERROR_INVALID_NAME) { + uv__set_error(loop, UV_EACCES, errorno); } else { - uv__set_sys_error(loop, errno); + uv__set_sys_error(loop, errorno); } goto error; } @@ -500,7 +499,6 @@ error: static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { - int errno; uv_loop_t* loop; uv_pipe_t* handle; uv_connect_t* req; @@ -543,7 +541,7 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb) { uv_loop_t* loop = handle->loop; - int errno, nameSize; + int errorno, nameSize; HANDLE pipeHandle = INVALID_HANDLE_VALUE; DWORD duplex_flags; @@ -560,7 +558,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, } if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(wchar_t))) { - errno = GetLastError(); + errorno = GetLastError(); goto error; } @@ -571,7 +569,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, if (!QueueUserWorkItem(&pipe_connect_thread_proc, req, WT_EXECUTELONGFUNCTION)) { - errno = GetLastError(); + errorno = GetLastError(); goto error; } @@ -581,7 +579,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, return; } - errno = GetLastError(); + errorno = GetLastError(); goto error; } @@ -591,7 +589,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, (uv_pipe_t*) req->handle, pipeHandle, duplex_flags)) { - errno = GetLastError(); + errorno = GetLastError(); goto error; } @@ -612,7 +610,7 @@ error: } /* Make this req pending reporting an error. */ - SET_REQ_ERROR(req, errno); + SET_REQ_ERROR(req, errorno); uv_insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; uv_ref(loop); @@ -756,7 +754,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { uv_loop_t* loop = handle->loop; - int i, errno; + int i; if (!(handle->flags & UV_HANDLE_BOUND)) { uv__set_artificial_error(loop, UV_EINVAL); diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c index 74744860a6..aacb06176a 100644 --- a/deps/uv/src/win/process.c +++ b/deps/uv/src/win/process.c @@ -872,17 +872,22 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process, STARTUPINFOW startup; PROCESS_INFORMATION info; - if (!options.file) { - uv__set_artificial_error(loop, UV_EINVAL); + if (options.flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) { + uv__set_artificial_error(loop, UV_ENOTSUP); return -1; } + assert(options.file != NULL); + assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS | + UV_PROCESS_SETGID | + UV_PROCESS_SETUID))); + uv_process_init(loop, process); process->exit_cb = options.exit_cb; UTF8_TO_UTF16(options.file, application); arguments = options.args ? make_program_args(options.args, - options.windows_verbatim_arguments) : NULL; + options.flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS) : NULL; env = options.env ? make_program_env(options.env) : NULL; if (options.cwd) { diff --git a/deps/uv/src/win/stream.c b/deps/uv/src/win/stream.c index d36bc682a8..4275bce195 100644 --- a/deps/uv/src/win/stream.c +++ b/deps/uv/src/win/stream.c @@ -191,11 +191,11 @@ size_t uv_count_bufs(uv_buf_t bufs[], int count) { } -int uv_is_readable(uv_stream_t* handle) { +int uv_is_readable(const uv_stream_t* handle) { return !(handle->flags & UV_HANDLE_EOF); } -int uv_is_writable(uv_stream_t* handle) { +int uv_is_writable(const uv_stream_t* handle) { return !(handle->flags & UV_HANDLE_SHUTTING); } diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index 21409edea5..51ef604eb1 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -252,10 +252,9 @@ static int uv__bind(uv_tcp_t* handle, int addrsize) { DWORD err; int r; - SOCKET sock; if (handle->socket == INVALID_SOCKET) { - sock = socket(domain, SOCK_STREAM, 0); + SOCKET sock = socket(domain, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c index 1964401e44..42069aff9c 100644 --- a/deps/uv/src/win/udp.c +++ b/deps/uv/src/win/udp.c @@ -163,7 +163,6 @@ static int uv__bind(uv_udp_t* handle, int addrsize, unsigned int flags) { int r; - SOCKET sock; DWORD no = 0, yes = 1; if ((flags & UV_UDP_IPV6ONLY) && domain != AF_INET6) { @@ -173,7 +172,7 @@ static int uv__bind(uv_udp_t* handle, } if (handle->socket == INVALID_SOCKET) { - sock = socket(domain, SOCK_DGRAM, 0); + SOCKET sock = socket(domain, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) { uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; @@ -192,14 +191,14 @@ static int uv__bind(uv_udp_t* handle, /* TODO: how to handle errors? This may fail if there is no ipv4 stack */ /* available, or when run on XP/2003 which have no support for dualstack */ /* sockets. For now we're silently ignoring the error. */ - setsockopt(sock, + setsockopt(handle->socket, IPPROTO_IPV6, IPV6_V6ONLY, (char*) &no, sizeof no); } - r = setsockopt(sock, + r = setsockopt(handle->socket, SOL_SOCKET, SO_REUSEADDR, (char*) &yes, @@ -648,10 +647,15 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) { } -#define SOCKOPT_SETTER(name, option4, option6) \ +#define SOCKOPT_SETTER(name, option4, option6, validate) \ int uv_udp_set_##name(uv_udp_t* handle, int value) { \ DWORD optval = (DWORD) value; \ \ + if (!(validate(value))) { \ + uv__set_artificial_error(handle->loop, UV_EINVAL); \ + return -1; \ + } \ + \ /* If the socket is unbound, bind to inaddr_any. */ \ if (!(handle->flags & UV_HANDLE_BOUND) && \ uv_udp_bind(handle, uv_addr_ip4_any_, 0) < 0) { \ @@ -682,8 +686,24 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) { return 0; \ } -SOCKOPT_SETTER(multicast_loop, IP_MULTICAST_LOOP, IPV6_MULTICAST_LOOP) -SOCKOPT_SETTER(multicast_ttl, IP_MULTICAST_TTL, IPV6_MULTICAST_HOPS) -SOCKOPT_SETTER(ttl, IP_TTL, IPV6_HOPLIMIT) +#define VALIDATE_TTL(value) ((value) >= 1 && (value) <= 255) +#define VALIDATE_MULTICAST_TTL(value) ((value) >= -1 && (value) <= 255) +#define VALIDATE_MULTICAST_LOOP(value) (1) + +SOCKOPT_SETTER(ttl, + IP_TTL, + IPV6_HOPLIMIT, + VALIDATE_TTL) +SOCKOPT_SETTER(multicast_ttl, + IP_MULTICAST_TTL, + IPV6_MULTICAST_HOPS, + VALIDATE_MULTICAST_TTL) +SOCKOPT_SETTER(multicast_loop, + IP_MULTICAST_LOOP, + IPV6_MULTICAST_LOOP, + VALIDATE_MULTICAST_LOOP) #undef SOCKOPT_SETTER +#undef VALIDATE_TTL +#undef VALIDATE_MULTICAST_TTL +#undef VALIDATE_MULTICAST_LOOP diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 9f731ecfad..f4d5fdbea9 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "uv.h" #include "internal.h" @@ -359,9 +360,9 @@ uv_err_t uv_get_process_title(char* buffer, size_t size) { if (!process_title && uv__get_process_title() == -1) { return uv__new_sys_error(GetLastError()); } - + assert(process_title); - strncpy(buffer, process_title, size); + strncpy(buffer, process_title, size); LeaveCriticalSection(&process_title_lock); return uv_ok_; @@ -385,8 +386,103 @@ uv_err_t uv_resident_set_memory(size_t* rss) { uv_err_t uv_uptime(double* uptime) { - *uptime = (double)GetTickCount()/1000.0; - return uv_ok_; + BYTE stack_buffer[4096]; + BYTE* malloced_buffer = NULL; + BYTE* buffer = (BYTE*) stack_buffer; + size_t buffer_size = sizeof(stack_buffer); + DWORD data_size; + + PERF_DATA_BLOCK* data_block; + PERF_OBJECT_TYPE* object_type; + PERF_COUNTER_DEFINITION* counter_definition; + + DWORD i; + + for (;;) { + LONG result; + + data_size = (DWORD) buffer_size; + result = RegQueryValueExW(HKEY_PERFORMANCE_DATA, + L"2", + NULL, + NULL, + buffer, + &data_size); + if (result == ERROR_SUCCESS) { + break; + } else if (result != ERROR_MORE_DATA) { + *uptime = 0; + return uv__new_sys_error(result); + } + + free(malloced_buffer); + + buffer_size *= 2; + /* Don't let the buffer grow infinitely. */ + if (buffer_size > 1 << 20) { + goto internalError; + } + + buffer = malloced_buffer = (BYTE*) malloc(buffer_size); + if (malloced_buffer == NULL) { + *uptime = 0; + return uv__new_artificial_error(UV_ENOMEM); + } + } + + if (data_size < sizeof(*data_block)) + goto internalError; + + data_block = (PERF_DATA_BLOCK*) buffer; + + if (wmemcmp(data_block->Signature, L"PERF", 4) != 0) + goto internalError; + + if (data_size < data_block->HeaderLength + sizeof(*object_type)) + goto internalError; + + object_type = (PERF_OBJECT_TYPE*) (buffer + data_block->HeaderLength); + + if (object_type->NumInstances != PERF_NO_INSTANCES) + goto internalError; + + counter_definition = (PERF_COUNTER_DEFINITION*) (buffer + + data_block->HeaderLength + object_type->HeaderLength); + for (i = 0; i < object_type->NumCounters; i++) { + if ((BYTE*) counter_definition + sizeof(*counter_definition) > + buffer + data_size) { + break; + } + + if (counter_definition->CounterNameTitleIndex == 674 && + counter_definition->CounterSize == sizeof(uint64_t)) { + if (counter_definition->CounterOffset + sizeof(uint64_t) > data_size || + !(counter_definition->CounterType & PERF_OBJECT_TIMER)) { + goto internalError; + } else { + BYTE* address = (BYTE*) object_type + object_type->DefinitionLength + + counter_definition->CounterOffset; + uint64_t value = *((uint64_t*) address); + *uptime = (double) (object_type->PerfTime.QuadPart - value) / + (double) object_type->PerfFreq.QuadPart; + free(malloced_buffer); + return uv_ok_; + } + } + + counter_definition = (PERF_COUNTER_DEFINITION*) + ((BYTE*) counter_definition + counter_definition->ByteLength); + } + + /* If we get here, the uptime value was not found. */ + free(malloced_buffer); + *uptime = 0; + return uv__new_artificial_error(UV_ENOSYS); + + internalError: + free(malloced_buffer); + *uptime = 0; + return uv__new_artificial_error(UV_EIO); } @@ -412,7 +508,7 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { *count = 0; - for (i = 0; i < system_info.dwNumberOfProcessors; i++) { + for (i = 0; i < system_info.dwNumberOfProcessors; i++) { _snprintf(key, sizeof(key), "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d", i); if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE, @@ -441,7 +537,7 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { RegCloseKey(processor_key); processor_key = NULL; - + cpu_info = &(*cpu_infos)[i]; /* $TODO: find times on windows */ @@ -569,7 +665,7 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses, } } } - + assert(name); address->name = name; diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index df840d5d26..073b9e8c0c 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4079,8 +4079,8 @@ (FACILITY_NTWIN32 << 16) | ERROR_SEVERITY_WARNING))) /* from ntifs.h */ -/* MinGW already has it */ -#if defined(_MSC_VER) || defined(__MINGW64__) +/* MinGW already has it, mingw-w64 does not. */ +#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) typedef struct _REPARSE_DATA_BUFFER { ULONG ReparseTag; USHORT ReparseDataLength; @@ -4335,7 +4335,7 @@ typedef NTSTATUS (NTAPI *sNtSetInformationFile) # define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1 #endif -#ifdef __MINGW32__ +#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) typedef struct _OVERLAPPED_ENTRY { ULONG_PTR lpCompletionKey; LPOVERLAPPED lpOverlapped; diff --git a/deps/uv/src/win/winsock.h b/deps/uv/src/win/winsock.h index 79b9e6b2c4..d070d58092 100644 --- a/deps/uv/src/win/winsock.h +++ b/deps/uv/src/win/winsock.h @@ -112,7 +112,7 @@ typedef struct _AFD_RECV_INFO { #define IOCTL_AFD_RECEIVE_DATAGRAM \ _AFD_CONTROL_CODE(AFD_RECEIVE_DATAGRAM, METHOD_NEITHER) -#if defined(__MINGW32__) && !defined(__MINGW64__) +#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) typedef struct _IP_ADAPTER_UNICAST_ADDRESS_XP { /* FIXME: __C89_NAMELESS was removed */ diff --git a/deps/uv/test/echo-server.c b/deps/uv/test/echo-server.c index 6b0d897214..d663d605c8 100644 --- a/deps/uv/test/echo-server.c +++ b/deps/uv/test/echo-server.c @@ -298,6 +298,14 @@ static int udp4_echo_start(int port) { static int pipe_echo_start(char* pipeName) { int r; +#ifndef _WIN32 + { + uv_fs_t req; + uv_fs_unlink(uv_default_loop(), &req, pipeName, NULL); + uv_fs_req_cleanup(&req); + } +#endif + server = (uv_handle_t*)&pipeServer; serverType = PIPE; diff --git a/deps/uv/test/runner-unix.c b/deps/uv/test/runner-unix.c index 3c78bb50a9..d0ebfbf073 100644 --- a/deps/uv/test/runner-unix.c +++ b/deps/uv/test/runner-unix.c @@ -100,13 +100,12 @@ typedef struct { static void* dowait(void* data) { dowait_args* args = data; - int i, status, r; + int i, r; process_info_t* p; for (i = 0; i < args->n; i++) { p = (process_info_t*)(args->vec + i * sizeof(process_info_t)); if (p->terminated) continue; - status = 0; r = waitpid(p->pid, &p->status, 0); if (r < 0) { perror("waitpid"); @@ -285,30 +284,6 @@ void rewind_cursor() { } -typedef void* (*uv_thread_cb)(void* arg); - - -uintptr_t uv_create_thread(void (*entry)(void* arg), void* arg) { - pthread_t t; - uv_thread_cb cb = (uv_thread_cb)entry; - int r = pthread_create(&t, NULL, cb, arg); - - if (r) { - return 0; - } - - return (uintptr_t)t; -} - - -/* Wait for a thread to terminate. Should return 0 if the thread ended, -1 on - * error. - */ -int uv_wait_thread(uintptr_t thread_id) { - return pthread_join((pthread_t)thread_id, NULL); -} - - /* Pause the calling thread for a number of milliseconds. */ void uv_sleep(int msec) { usleep(msec * 1000); diff --git a/deps/uv/test/runner-win.c b/deps/uv/test/runner-win.c index d2a986a714..e758dd1dd3 100644 --- a/deps/uv/test/runner-win.c +++ b/deps/uv/test/runner-win.c @@ -274,69 +274,6 @@ void rewind_cursor() { } -typedef struct { - void (*entry)(void* arg); - void* arg; -} thread_info_t; - - -static unsigned __stdcall create_thread_helper(void* info) { - /* Copy thread info locally, then free it */ - void (*entry)(void* arg) = ((thread_info_t*) info)->entry; - void* arg = ((thread_info_t*) info)->arg; - - free(info); - - /* Run the actual thread proc */ - entry(arg); - - /* Finalize */ - _endthreadex(0); - return 0; -} - - -/* Create a thread. Returns the thread identifier, or 0 on failure. */ -uintptr_t uv_create_thread(void (*entry)(void* arg), void* arg) { - uintptr_t result; - thread_info_t* info; - - info = (thread_info_t*) malloc(sizeof *info); - if (info == NULL) { - return 0; - } - - info->entry = entry; - info->arg = arg; - - result = _beginthreadex(NULL, - 0, - &create_thread_helper, - (void*) info, - 0, - NULL); - - if (result == 0) { - free(info); - return 0; - } - - return result; -} - - -/* Wait for a thread to terminate. Should return 0 if the thread ended, -1 on - * error. - */ -int uv_wait_thread(uintptr_t thread_id) { - if (WaitForSingleObject((HANDLE)thread_id, INFINITE) != WAIT_OBJECT_0) { - return -1; - } - - return 0; -} - - /* Pause the calling thread for a number of milliseconds. */ void uv_sleep(int msec) { Sleep(msec); diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index a7938e6064..04497342f7 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -103,14 +103,6 @@ typedef enum { int run_helper_##name() -/* Create a thread. Returns the thread identifier, or 0 on failure. */ -uintptr_t uv_create_thread(void (*entry)(void* arg), void* arg); - -/* Wait for a thread to terminate. Should return 0 if the thread ended, -1 on - * error. - */ -int uv_wait_thread(uintptr_t thread_id); - /* Pause the calling thread for a number of milliseconds. */ void uv_sleep(int msec); diff --git a/deps/uv/test/test-async.c b/deps/uv/test/test-async.c index 3d8415183d..7cdad0983a 100644 --- a/deps/uv/test/test-async.c +++ b/deps/uv/test/test-async.c @@ -24,192 +24,94 @@ #include #include +static uv_thread_t thread; +static uv_mutex_t mutex; -static uv_prepare_t prepare_handle; +static uv_prepare_t prepare; +static uv_async_t async; -static uv_async_t async1_handle; -/* static uv_handle_t async2_handle; */ +static volatile int async_cb_called; +static int prepare_cb_called; +static int close_cb_called; -static int prepare_cb_called = 0; -static volatile int async1_cb_called = 0; -static int async1_closed = 0; -/* static volatile int async2_cb_called = 0; */ - -static int close_cb_called = 0; - -static uintptr_t thread1_id = 0; -#if 0 -static uintptr_t thread2_id = 0; -static uintptr_t thread3_id = 0; -#endif - - -/* Thread 1 makes sure that async1_cb_called reaches 3 before exiting. */ -void thread1_entry(void *arg) { - uv_sleep(50); - - while (1) { - switch (async1_cb_called) { - case 0: - uv_async_send(&async1_handle); - break; - - case 1: - uv_async_send(&async1_handle); - break; - - case 2: - uv_async_send(&async1_handle); - break; - - default: - return; - } - } -} - -#if 0 -/* Thread 2 calls uv_async_send on async_handle_2 8 times. */ -void thread2_entry(void *arg) { - int i; - - while (1) { - switch (async1_cb_called) { - case 0: - uv_async_send(&async2_handle); - break; +void thread_cb(void *arg) { + int n; + int r; - case 1: - uv_async_send(&async2_handle); - break; + for (;;) { + uv_mutex_lock(&mutex); + n = async_cb_called; + uv_mutex_unlock(&mutex); - case 2: - uv_async_send(&async2_handle); - break; + if (n == 3) { + break; } - uv_sleep(5); - } - if (async1_cb_called == 20) { - uv_close(handle); + r = uv_async_send(&async); + ASSERT(r == 0); } } -/* Thread 3 calls uv_async_send on async_handle_2 8 times - * after waiting half a second first. - */ -void thread3_entry(void *arg) { - int i; - - for (i = 0; i < 8; i++) { - uv_async_send(&async2_handle); - } -} -#endif - - static void close_cb(uv_handle_t* handle) { ASSERT(handle != NULL); close_cb_called++; } -static void async1_cb(uv_async_t* handle, int status) { - ASSERT(handle == &async1_handle); - ASSERT(status == 0); - - async1_cb_called++; - printf("async1_cb #%d\n", async1_cb_called); - - if (async1_cb_called > 2 && !async1_closed) { - async1_closed = 1; - uv_close((uv_handle_t*)handle, close_cb); - } -} - +static void async_cb(uv_async_t* handle, int status) { + int n; -#if 0 -static void async2_cb(uv_handle_t* handle, int status) { - ASSERT(handle == &async2_handle); + ASSERT(handle == &async); ASSERT(status == 0); - async2_cb_called++; - printf("async2_cb #%d\n", async2_cb_called); + uv_mutex_lock(&mutex); + n = ++async_cb_called; + uv_mutex_unlock(&mutex); - if (async2_cb_called == 16) { - uv_close(handle); + if (n == 3) { + uv_close((uv_handle_t*)&async, close_cb); + uv_close((uv_handle_t*)&prepare, close_cb); } } -#endif static void prepare_cb(uv_prepare_t* handle, int status) { - ASSERT(handle == &prepare_handle); - ASSERT(status == 0); - - switch (prepare_cb_called) { - case 0: - thread1_id = uv_create_thread(thread1_entry, NULL); - ASSERT(thread1_id != 0); - break; - -#if 0 - case 1: - thread2_id = uv_create_thread(thread2_entry, NULL); - ASSERT(thread2_id != 0); - break; - - case 2: - thread3_id = uv_create_thread(thread3_entry, NULL); - ASSERT(thread3_id != 0); - break; -#endif + int r; - case 1: - uv_close((uv_handle_t*)handle, close_cb); - break; + ASSERT(handle == &prepare); + ASSERT(status == 0); - default: - FATAL("Should never get here"); - } + if (prepare_cb_called++) + return; - prepare_cb_called++; + r = uv_thread_create(&thread, thread_cb, NULL); + ASSERT(r == 0); + uv_mutex_unlock(&mutex); } TEST_IMPL(async) { int r; - r = uv_prepare_init(uv_default_loop(), &prepare_handle); - ASSERT(r == 0); - r = uv_prepare_start(&prepare_handle, prepare_cb); + r = uv_mutex_init(&mutex); ASSERT(r == 0); + uv_mutex_lock(&mutex); - r = uv_async_init(uv_default_loop(), &async1_handle, async1_cb); + r = uv_prepare_init(uv_default_loop(), &prepare); ASSERT(r == 0); - -#if 0 - r = uv_async_init(&async2_handle, async2_cb, close_cb, NULL); + r = uv_prepare_start(&prepare, prepare_cb); ASSERT(r == 0); -#endif - r = uv_run(uv_default_loop()); + r = uv_async_init(uv_default_loop(), &async, async_cb); ASSERT(r == 0); - r = uv_wait_thread(thread1_id); - ASSERT(r == 0); -#if 0 - r = uv_wait_thread(thread2_id); - ASSERT(r == 0); - r = uv_wait_thread(thread3_id); + r = uv_run(uv_default_loop()); ASSERT(r == 0); -#endif - ASSERT(prepare_cb_called == 2); - ASSERT(async1_cb_called > 2); - /* ASSERT(async2_cb_called = 16); */ + ASSERT(prepare_cb_called > 0); + ASSERT(async_cb_called == 3); ASSERT(close_cb_called == 2); return 0; diff --git a/deps/uv/test/test-counters-init.c b/deps/uv/test/test-counters-init.c index 29e7acdf9f..6318684246 100644 --- a/deps/uv/test/test-counters-init.c +++ b/deps/uv/test/test-counters-init.c @@ -78,7 +78,7 @@ static void create_dir(uv_loop_t* loop, const char* name) { uv_fs_t req; r = uv_fs_rmdir(loop, &req, name, NULL); r = uv_fs_mkdir(loop, &req, name, 0755, NULL); - ASSERT(r == 0); + ASSERT(r == 0 || uv_last_error(loop).code == UV_EEXIST); uv_fs_req_cleanup(&req); } @@ -208,8 +208,7 @@ TEST_IMPL(counters_init) { r = uv_fs_event_init(uv_default_loop(), &fs_event, "watch_dir", NULL, 0); ASSERT(r == 0); ASSERT(uv_default_loop()->counters.fs_event_init == ++fs_event_init_prev); - r = uv_fs_rmdir(uv_default_loop(), &fs_req, "watch_dir", NULL); - ASSERT(r == 0); + uv_fs_rmdir(uv_default_loop(), &fs_req, "watch_dir", NULL); uv_fs_req_cleanup(&fs_req); return 0; diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index 42f990f310..fe7bce2afc 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -25,6 +25,12 @@ #include #include +#ifndef HAVE_KQUEUE +# if __APPLE__ || __FreeBSD__ || __OpenBSD__ || __NetBSD__ +# define HAVE_KQUEUE 1 +# endif +#endif + static uv_fs_event_t fs_event; static uv_timer_t timer; static int timer_cb_called = 0; @@ -361,6 +367,18 @@ TEST_IMPL(fs_event_close_with_pending_event) { return 0; } +#if HAVE_KQUEUE + +/* kqueue doesn't register fs events if you don't have an active watcher. + * The file descriptor needs to be part of the kqueue set of interest and + * that's not the case until we actually enter the event loop. + */ +TEST_IMPL(fs_event_close_in_callback) { + fprintf(stderr, "Skipping test, doesn't work with kqueue.\n"); + return 0; +} + +#else /* !HAVE_KQUEUE */ static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename, int events, int status) { @@ -420,3 +438,5 @@ TEST_IMPL(fs_event_close_in_callback) { return 0; } + +#endif /* HAVE_KQUEUE */ diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 8dc7147310..a8fe0abb97 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -225,6 +225,7 @@ static void close_cb(uv_fs_t* req) { uv_fs_req_cleanup(req); if (close_cb_count == 3) { r = uv_fs_unlink(loop, &unlink_req, "test_file2", unlink_cb); + ASSERT(r == 0); } } @@ -237,6 +238,7 @@ static void ftruncate_cb(uv_fs_t* req) { ftruncate_cb_count++; uv_fs_req_cleanup(req); r = uv_fs_close(loop, &close_req, open_req1.result, close_cb); + ASSERT(r == 0); } @@ -255,6 +257,7 @@ static void read_cb(uv_fs_t* req) { ASSERT(strcmp(buf, "test-bu") == 0); r = uv_fs_close(loop, &close_req, open_req1.result, close_cb); } + ASSERT(r == 0); } @@ -274,6 +277,7 @@ static void open_cb(uv_fs_t* req) { memset(buf, 0, sizeof(buf)); r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1, read_cb); + ASSERT(r == 0); } @@ -298,6 +302,7 @@ static void fsync_cb(uv_fs_t* req) { fsync_cb_count++; uv_fs_req_cleanup(req); r = uv_fs_close(loop, &close_req, open_req1.result, close_cb); + ASSERT(r == 0); } @@ -309,6 +314,7 @@ static void fdatasync_cb(uv_fs_t* req) { fdatasync_cb_count++; uv_fs_req_cleanup(req); r = uv_fs_fsync(loop, &fsync_req, open_req1.result, fsync_cb); + ASSERT(r == 0); } @@ -320,6 +326,7 @@ static void write_cb(uv_fs_t* req) { write_cb_count++; uv_fs_req_cleanup(req); r = uv_fs_fdatasync(loop, &fdatasync_req, open_req1.result, fdatasync_cb); + ASSERT(r == 0); } @@ -332,6 +339,7 @@ static void create_cb(uv_fs_t* req) { uv_fs_req_cleanup(req); r = uv_fs_write(loop, &write_req, req->result, test_buf, sizeof(test_buf), -1, write_cb); + ASSERT(r == 0); } @@ -1665,3 +1673,59 @@ TEST_IMPL(fs_rename_to_existing_file) { return 0; } + + +TEST_IMPL(fs_read_file_eof) { + int r; + + /* Setup. */ + unlink("test_file"); + + loop = uv_default_loop(); + + r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, + S_IWRITE | S_IREAD, NULL); + ASSERT(r != -1); + ASSERT(open_req1.result != -1); + uv_fs_req_cleanup(&open_req1); + + r = uv_fs_write(loop, &write_req, open_req1.result, test_buf, + sizeof(test_buf), -1, NULL); + ASSERT(r != -1); + ASSERT(write_req.result != -1); + uv_fs_req_cleanup(&write_req); + + r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + ASSERT(r != -1); + ASSERT(close_req.result != -1); + uv_fs_req_cleanup(&close_req); + + r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, 0, NULL); + ASSERT(r != -1); + ASSERT(open_req1.result != -1); + uv_fs_req_cleanup(&open_req1); + + memset(buf, 0, sizeof(buf)); + r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1, + NULL); + ASSERT(r != -1); + ASSERT(read_req.result != -1); + ASSERT(strcmp(buf, test_buf) == 0); + uv_fs_req_cleanup(&read_req); + + r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), + read_req.result, NULL); + ASSERT(r == 0); + ASSERT(read_req.result == 0); + uv_fs_req_cleanup(&read_req); + + r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + ASSERT(r != -1); + ASSERT(close_req.result != -1); + uv_fs_req_cleanup(&close_req); + + /* Cleanup */ + unlink("test_file"); + + return 0; +} diff --git a/deps/uv/test/test-get-memory.c b/deps/uv/test/test-get-memory.c index 722bc77438..2396939bcb 100644 --- a/deps/uv/test/test-get-memory.c +++ b/deps/uv/test/test-get-memory.c @@ -26,7 +26,9 @@ TEST_IMPL(get_memory) { uint64_t free_mem = uv_get_free_memory(); uint64_t total_mem = uv_get_total_memory(); - printf("free_mem=%zu, total_mem=%zu\n", (size_t)free_mem, (size_t)total_mem); + printf("free_mem=%llu, total_mem=%llu\n", + (unsigned long long) free_mem, + (unsigned long long) total_mem); ASSERT(free_mem > 0); ASSERT(total_mem > 0); diff --git a/deps/uv/test/test-gethostbyname.c b/deps/uv/test/test-gethostbyname.c index 583622e724..e49c69c41c 100644 --- a/deps/uv/test/test-gethostbyname.c +++ b/deps/uv/test/test-gethostbyname.c @@ -26,14 +26,14 @@ #include #include /* strlen */ -ares_channel channel; -struct ares_options options; -int optmask; - -int ares_bynamecallbacks; -int bynamecallbacksig; -int ares_byaddrcallbacks; -int byaddrcallbacksig; +static ares_channel channel; +static struct ares_options options; +static int optmask; + +static int ares_bynamecallbacks; +static int bynamecallbacksig; +static int ares_byaddrcallbacks; +static int byaddrcallbacksig; static void aresbynamecallback( void *arg, int status, diff --git a/deps/uv/test/test-ipc-send-recv.c b/deps/uv/test/test-ipc-send-recv.c index 96b47f0710..970bf1effe 100644 --- a/deps/uv/test/test-ipc-send-recv.c +++ b/deps/uv/test/test-ipc-send-recv.c @@ -197,6 +197,7 @@ int ipc_send_recv_helper(void) { uv_pipe_open(&ctx.channel, 0); ASSERT(uv_is_readable((uv_stream_t*)&ctx.channel)); ASSERT(uv_is_writable((uv_stream_t*)&ctx.channel)); + ASSERT(!uv_is_closing((uv_handle_t*)&ctx.channel)); r = uv_read2_start((uv_stream_t*)&ctx.channel, alloc_cb, read2_cb); ASSERT(r == 0); diff --git a/deps/uv/test/test-ipc.c b/deps/uv/test/test-ipc.c index d70d5b23a3..1ea0e7f963 100644 --- a/deps/uv/test/test-ipc.c +++ b/deps/uv/test/test-ipc.c @@ -535,6 +535,7 @@ int ipc_helper(int listen_after_write) { ASSERT(uv_is_readable((uv_stream_t*) &channel)); ASSERT(uv_is_writable((uv_stream_t*) &channel)); + ASSERT(!uv_is_closing((uv_handle_t*) &channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); @@ -583,6 +584,7 @@ int ipc_helper_tcp_connection() { ASSERT(uv_is_readable((uv_stream_t*)&channel)); ASSERT(uv_is_writable((uv_stream_t*)&channel)); + ASSERT(!uv_is_closing((uv_handle_t*)&channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 5743243bcc..84782b2ab2 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -24,7 +24,9 @@ TEST_DECLARE (tty) TEST_DECLARE (stdio_over_pipes) TEST_DECLARE (ipc_listen_before_write) TEST_DECLARE (ipc_listen_after_write) +#ifndef _WIN32 TEST_DECLARE (ipc_send_recv_pipe) +#endif TEST_DECLARE (ipc_send_recv_tcp) TEST_DECLARE (ipc_tcp_connection) TEST_DECLARE (tcp_ping_pong) @@ -116,6 +118,8 @@ TEST_DECLARE (spawn_stdin) TEST_DECLARE (spawn_and_kill) TEST_DECLARE (spawn_and_kill_with_std) TEST_DECLARE (spawn_and_ping) +TEST_DECLARE (spawn_setuid_fails) +TEST_DECLARE (spawn_setgid_fails) TEST_DECLARE (kill) TEST_DECLARE (fs_file_noent) TEST_DECLARE (fs_file_nametoolong) @@ -140,7 +144,7 @@ TEST_DECLARE (fs_event_watch_file_current_dir) TEST_DECLARE (fs_event_no_callback_on_close) TEST_DECLARE (fs_event_immediate_close) TEST_DECLARE (fs_event_close_with_pending_event) -TEST_DECLARE (fs_event_close_in_callback); +TEST_DECLARE (fs_event_close_in_callback) TEST_DECLARE (fs_readdir_empty_dir) TEST_DECLARE (fs_readdir_file) TEST_DECLARE (fs_open_dir) @@ -162,6 +166,8 @@ TEST_DECLARE (environment_creation) TEST_DECLARE (listen_with_simultaneous_accepts) TEST_DECLARE (listen_no_simultaneous_accepts) TEST_DECLARE (fs_stat_root) +#else +TEST_DECLARE (spawn_setuid_setgid) #endif HELPER_DECLARE (tcp4_echo_server) HELPER_DECLARE (tcp6_echo_server) @@ -179,7 +185,9 @@ TASK_LIST_START TEST_ENTRY (stdio_over_pipes) TEST_ENTRY (ipc_listen_before_write) TEST_ENTRY (ipc_listen_after_write) +#ifndef _WIN32 TEST_ENTRY (ipc_send_recv_pipe) +#endif TEST_ENTRY (ipc_send_recv_tcp) TEST_ENTRY (ipc_tcp_connection) @@ -312,6 +320,8 @@ TASK_LIST_START TEST_ENTRY (spawn_and_kill) TEST_ENTRY (spawn_and_kill_with_std) TEST_ENTRY (spawn_and_ping) + TEST_ENTRY (spawn_setuid_fails) + TEST_ENTRY (spawn_setgid_fails) TEST_ENTRY (kill) #ifdef _WIN32 TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows) @@ -320,6 +330,8 @@ TASK_LIST_START TEST_ENTRY (listen_with_simultaneous_accepts) TEST_ENTRY (listen_no_simultaneous_accepts) TEST_ENTRY (fs_stat_root) +#else + TEST_ENTRY (spawn_setuid_setgid) #endif TEST_ENTRY (fs_file_noent) diff --git a/deps/uv/test/test-loop-handles.c b/deps/uv/test/test-loop-handles.c index 425dcf63ab..866445da31 100644 --- a/deps/uv/test/test-loop-handles.c +++ b/deps/uv/test/test-loop-handles.c @@ -106,14 +106,10 @@ static int idle_2_close_cb_called = 0; static int idle_2_cb_started = 0; static int idle_2_is_active = 0; -static int timer_cb_called = 0; - static void timer_cb(uv_timer_t* handle, int status) { ASSERT(handle == &timer_handle); ASSERT(status == 0); - - timer_cb_called++; } @@ -353,7 +349,5 @@ TEST_IMPL(loop_handles) { ASSERT(idle_2_close_cb_called == idle_2_cb_started); ASSERT(idle_2_is_active == 0); - ASSERT(timer_cb_called > 0); - return 0; } diff --git a/deps/uv/test/test-ping-pong.c b/deps/uv/test/test-ping-pong.c index 245a6014ec..1bdcc3bc24 100644 --- a/deps/uv/test/test-ping-pong.c +++ b/deps/uv/test/test-ping-pong.c @@ -140,6 +140,7 @@ static void pinger_on_connect(uv_connect_t *req, int status) { ASSERT(uv_is_readable(req->handle)); ASSERT(uv_is_writable(req->handle)); + ASSERT(!uv_is_closing((uv_handle_t *)req->handle)); pinger_write_ping(pinger); diff --git a/deps/uv/test/test-pipe-connect-error.c b/deps/uv/test/test-pipe-connect-error.c index 4a6c5110fa..cc06d4293a 100644 --- a/deps/uv/test/test-pipe-connect-error.c +++ b/deps/uv/test/test-pipe-connect-error.c @@ -93,4 +93,4 @@ TEST_IMPL(pipe_connect_to_file) { ASSERT(connect_cb_called == 1); return 0; -} \ No newline at end of file +} diff --git a/deps/uv/test/test-platform-output.c b/deps/uv/test/test-platform-output.c index 1e177296d8..008d14fb7d 100644 --- a/deps/uv/test/test-platform-output.c +++ b/deps/uv/test/test-platform-output.c @@ -36,38 +36,42 @@ TEST_IMPL(platform_output) { err = uv_get_process_title(buffer, sizeof(buffer)); ASSERT(UV_OK == err.code); - fprintf(stderr, "uv_get_process_title: %s\n", buffer); + printf("uv_get_process_title: %s\n", buffer); err = uv_resident_set_memory(&rss); ASSERT(UV_OK == err.code); - fprintf(stderr, "uv_resident_set_memory: %zu\n", rss); + printf("uv_resident_set_memory: %llu\n", (unsigned long long) rss); err = uv_uptime(&uptime); ASSERT(UV_OK == err.code); - fprintf(stderr, "uv_uptime: %f\n", uptime); + ASSERT(uptime > 0); + printf("uv_uptime: %f\n", uptime); err = uv_cpu_info(&cpus, &count); ASSERT(UV_OK == err.code); - fprintf(stderr, "uv_cpu_info:\n"); + printf("uv_cpu_info:\n"); for (i = 0; i < count; i++) { - fprintf(stderr, " model: %s\n", cpus[i].model); - fprintf(stderr, " speed: %d\n", cpus[i].speed); - fprintf(stderr, " times.sys: %zu\n", (size_t)cpus[i].cpu_times.sys); - fprintf(stderr, " times.user: %zu\n", (size_t)cpus[i].cpu_times.user); - fprintf(stderr, " times.idle: %zu\n", (size_t)cpus[i].cpu_times.idle); - fprintf(stderr, " times.irq: %zu\n", (size_t)cpus[i].cpu_times.irq); - fprintf(stderr, " times.nice: %zu\n", (size_t)cpus[i].cpu_times.nice); + printf(" model: %s\n", cpus[i].model); + printf(" speed: %d\n", cpus[i].speed); + printf(" times.sys: %llu\n", (unsigned long long) cpus[i].cpu_times.sys); + printf(" times.user: %llu\n", + (unsigned long long) cpus[i].cpu_times.user); + printf(" times.idle: %llu\n", + (unsigned long long) cpus[i].cpu_times.idle); + printf(" times.irq: %llu\n", (unsigned long long) cpus[i].cpu_times.irq); + printf(" times.nice: %llu\n", + (unsigned long long) cpus[i].cpu_times.nice); } uv_free_cpu_info(cpus, count); err = uv_interface_addresses(&interfaces, &count); ASSERT(UV_OK == err.code); - fprintf(stderr, "uv_interface_addresses:\n"); + printf("uv_interface_addresses:\n"); for (i = 0; i < count; i++) { - fprintf(stderr, " name: %s\n", interfaces[i].name); - fprintf(stderr, " internal: %d\n", interfaces[i].is_internal); + printf(" name: %s\n", interfaces[i].name); + printf(" internal: %d\n", interfaces[i].is_internal); if (interfaces[i].address.address4.sin_family == AF_INET) { uv_ip4_name(&interfaces[i].address.address4, buffer, sizeof(buffer)); @@ -75,7 +79,7 @@ TEST_IMPL(platform_output) { uv_ip6_name(&interfaces[i].address.address6, buffer, sizeof(buffer)); } - fprintf(stderr, " address: %s\n", buffer); + printf(" address: %s\n", buffer); } uv_free_interface_addresses(interfaces, count); diff --git a/deps/uv/test/test-shutdown-close.c b/deps/uv/test/test-shutdown-close.c index 864f7cecae..eabbefc606 100644 --- a/deps/uv/test/test-shutdown-close.c +++ b/deps/uv/test/test-shutdown-close.c @@ -57,7 +57,9 @@ static void connect_cb(uv_connect_t* req, int status) { r = uv_shutdown(&shutdown_req, req->handle, shutdown_cb); ASSERT(r == 0); + ASSERT(!uv_is_closing((uv_handle_t*) req->handle)); uv_close((uv_handle_t*) req->handle, close_cb); + ASSERT(uv_is_closing((uv_handle_t*) req->handle)); connect_cb_called++; } diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index a4d694373c..ccb9538f90 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -25,6 +25,11 @@ #include #include +#ifndef _WIN32 +#include +#endif + + static int close_cb_called; static int exit_cb_called; static uv_process_t process; @@ -55,6 +60,22 @@ static void exit_cb(uv_process_t* process, int exit_status, int term_signal) { } +static void exit_cb_failure_expected(uv_process_t* process, int exit_status, + int term_signal) { + printf("exit_cb\n"); + exit_cb_called++; + ASSERT(exit_status == 127); + ASSERT(term_signal == 0); + uv_close((uv_handle_t*)process, close_cb); +} + + +static void exit_cb_unexpected(uv_process_t* process, int exit_status, + int term_signal) { + ASSERT(0 && "should not have been called"); +} + + static void kill_cb(uv_process_t* process, int exit_status, int term_signal) { uv_err_t err; @@ -92,9 +113,8 @@ void on_read(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) { if (nread > 0) { output_used += nread; } else if (nread < 0) { - if (err.code == UV_EOF) { - uv_close((uv_handle_t*)tcp, close_cb); - } + ASSERT(err.code == UV_EOF); + uv_close((uv_handle_t*)tcp, close_cb); } } @@ -116,6 +136,7 @@ static void init_process_options(char* test, uv_exit_cb exit_cb) { options.file = exepath; options.args = args; options.exit_cb = exit_cb; + options.flags = 0; } @@ -233,19 +254,40 @@ TEST_IMPL(spawn_and_kill) { TEST_IMPL(spawn_and_kill_with_std) { int r; - uv_pipe_t out; - uv_pipe_t in; + uv_pipe_t in, out, err; + uv_write_t write; + char message[] = "Nancy's joining me because the message this evening is " + "not my message but ours."; + uv_buf_t buf; init_process_options("spawn_helper4", kill_cb); - uv_pipe_init(uv_default_loop(), &out, 0); - uv_pipe_init(uv_default_loop(), &in, 0); - options.stdout_stream = &out; + r = uv_pipe_init(uv_default_loop(), &in, 0); + ASSERT(r == 0); + + r = uv_pipe_init(uv_default_loop(), &out, 0); + ASSERT(r == 0); + + r = uv_pipe_init(uv_default_loop(), &err, 0); + ASSERT(r == 0); + options.stdin_stream = ∈ + options.stdout_stream = &out; + options.stderr_stream = &err; r = uv_spawn(uv_default_loop(), &process, options); ASSERT(r == 0); + buf = uv_buf_init(message, sizeof message); + r = uv_write(&write, (uv_stream_t*) &in, &buf, 1, write_cb); + ASSERT(r == 0); + + r = uv_read_start((uv_stream_t*) &out, on_alloc, on_read); + ASSERT(r == 0); + + r = uv_read_start((uv_stream_t*) &err, on_alloc, on_read); + ASSERT(r == 0); + r = uv_timer_init(uv_default_loop(), &timer); ASSERT(r == 0); @@ -256,7 +298,7 @@ TEST_IMPL(spawn_and_kill_with_std) { ASSERT(r == 0); ASSERT(exit_cb_called == 1); - ASSERT(close_cb_called == 2); /* Once for process and once for timer. */ + ASSERT(close_cb_called == 5); /* process x 1, timer x 1, stdio x 3. */ return 0; } @@ -485,7 +527,7 @@ TEST_IMPL(environment_creation) { ptr += GetEnvironmentVariableW(L"SYSTEMDRIVE", ptr, expected + sizeof(expected) - ptr); ++ptr; *ptr = '\0'; - + result = make_program_env(environment); for (str = result; *str; str += wcslen(str) + 1) { @@ -493,7 +535,149 @@ TEST_IMPL(environment_creation) { } ASSERT(wcscmp(expected, result) == 0); - + + return 0; +} +#endif + +#ifndef _WIN32 +TEST_IMPL(spawn_setuid_setgid) { + int r; + + /* if not root, then this will fail. */ + uv_uid_t uid = getuid(); + if (uid != 0) { + fprintf(stderr, "spawn_setuid_setgid skipped: not root\n"); + return 0; + } + + init_process_options("spawn_helper1", exit_cb); + + /* become the "nobody" user. */ + struct passwd* pw; + pw = getpwnam("nobody"); + ASSERT(pw != NULL); + options.uid = pw->pw_uid; + options.gid = pw->pw_gid; + options.flags = UV_PROCESS_SETUID | UV_PROCESS_SETGID; + + r = uv_spawn(uv_default_loop(), &process, options); + ASSERT(r == 0); + + r = uv_run(uv_default_loop()); + ASSERT(r == 0); + + ASSERT(exit_cb_called == 1); + ASSERT(close_cb_called == 1); + + return 0; +} +#endif + + +#ifndef _WIN32 +TEST_IMPL(spawn_setuid_fails) { + int r; + + /* if root, become nobody. */ + uv_uid_t uid = getuid(); + if (uid == 0) { + struct passwd* pw; + pw = getpwnam("nobody"); + ASSERT(pw != NULL); + r = setuid(pw->pw_uid); + ASSERT(r == 0); + } + + init_process_options("spawn_helper1", exit_cb_failure_expected); + + options.flags |= UV_PROCESS_SETUID; + options.uid = (uv_uid_t) -42424242; + + r = uv_spawn(uv_default_loop(), &process, options); + ASSERT(r == 0); + + r = uv_run(uv_default_loop()); + ASSERT(r == 0); + + ASSERT(exit_cb_called == 1); + ASSERT(close_cb_called == 1); + + return 0; +} + + +TEST_IMPL(spawn_setgid_fails) { + int r; + + /* if root, become nobody. */ + uv_uid_t uid = getuid(); + if (uid == 0) { + struct passwd* pw; + pw = getpwnam("nobody"); + ASSERT(pw != NULL); + r = setuid(pw->pw_uid); + ASSERT(r == 0); + } + + init_process_options("spawn_helper1", exit_cb_failure_expected); + + options.flags |= UV_PROCESS_SETGID; + options.gid = (uv_gid_t) -42424242; + + r = uv_spawn(uv_default_loop(), &process, options); + ASSERT(r == 0); + + r = uv_run(uv_default_loop()); + ASSERT(r == 0); + + ASSERT(exit_cb_called == 1); + ASSERT(close_cb_called == 1); + + return 0; +} +#endif + + +#ifdef _WIN32 +TEST_IMPL(spawn_setuid_fails) { + int r; + + init_process_options("spawn_helper1", exit_cb_unexpected); + + options.flags |= UV_PROCESS_SETUID; + options.uid = (uv_uid_t) -42424242; + + r = uv_spawn(uv_default_loop(), &process, options); + ASSERT(r == -1); + ASSERT(uv_last_error(uv_default_loop()).code == UV_ENOTSUP); + + r = uv_run(uv_default_loop()); + ASSERT(r == 0); + + ASSERT(close_cb_called == 0); + + return 0; +} + + +TEST_IMPL(spawn_setgid_fails) { + int r; + + init_process_options("spawn_helper1", exit_cb_unexpected); + + options.flags |= UV_PROCESS_SETGID; + options.gid = (uv_gid_t) -42424242; + + r = uv_spawn(uv_default_loop(), &process, options); + ASSERT(r == -1); + ASSERT(uv_last_error(uv_default_loop()).code == UV_ENOTSUP); + + r = uv_run(uv_default_loop()); + ASSERT(r == 0); + + ASSERT(close_cb_called == 0); + return 0; } #endif diff --git a/deps/uv/test/test-stdio-over-pipes.c b/deps/uv/test/test-stdio-over-pipes.c index 2116d164e3..98173fe375 100644 --- a/deps/uv/test/test-stdio-over-pipes.c +++ b/deps/uv/test/test-stdio-over-pipes.c @@ -41,12 +41,6 @@ static char output[OUTPUT_SIZE]; static int output_used; -typedef struct { - uv_write_t req; - uv_buf_t buf; -} write_req_t; - - static void close_cb(uv_handle_t* handle) { printf("close_cb\n"); close_cb_called++; @@ -78,45 +72,38 @@ static void init_process_options(char* test, uv_exit_cb exit_cb) { static uv_buf_t on_alloc(uv_handle_t* handle, size_t suggested_size) { - uv_buf_t buf; - buf.base = output + output_used; - buf.len = OUTPUT_SIZE - output_used; - return buf; + return uv_buf_init(output + output_used, OUTPUT_SIZE - output_used); } static void after_write(uv_write_t* req, int status) { - write_req_t* wr; - if (status) { uv_err_t err = uv_last_error(loop); fprintf(stderr, "uv_write error: %s\n", uv_strerror(err)); ASSERT(0); } - wr = (write_req_t*) req; - /* Free the read/write buffer and the request */ - free(wr); + free(req); after_write_cb_called++; } -static void on_read(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) { - write_req_t* write_req; +static void on_read(uv_stream_t* tcp, ssize_t nread, uv_buf_t rdbuf) { + uv_write_t* req; + uv_buf_t wrbuf; int r; - uv_err_t err = uv_last_error(uv_default_loop()); - ASSERT(nread > 0 || err.code == UV_EOF); + ASSERT(nread > 0 || uv_last_error(uv_default_loop()).code == UV_EOF); if (nread > 0) { output_used += nread; if (output_used == 12) { ASSERT(memcmp("hello world\n", output, 12) == 0); - write_req = (write_req_t*)malloc(sizeof(*write_req)); - write_req->buf = uv_buf_init(output, output_used); - r = uv_write(&write_req->req, (uv_stream_t*)&in, &write_req->buf, 1, after_write); + wrbuf = uv_buf_init(output, output_used); + req = malloc(sizeof(*req)); + r = uv_write(req, (uv_stream_t*)&in, &wrbuf, 1, after_write); ASSERT(r == 0); } } @@ -182,12 +169,8 @@ static void after_pipe_write(uv_write_t* req, int status) { } -static uv_buf_t on_read_alloc(uv_handle_t* handle, - size_t suggested_size) { - uv_buf_t buf; - buf.base = (char*)malloc(suggested_size); - buf.len = suggested_size; - return buf; +static uv_buf_t on_read_alloc(uv_handle_t* handle, size_t suggested_size) { + return uv_buf_init(malloc(suggested_size), suggested_size); } @@ -253,4 +236,4 @@ int stdio_over_pipes_helper() { ASSERT(close_cb_called == 2); return 0; -} \ No newline at end of file +} diff --git a/deps/uv/test/test-udp-options.c b/deps/uv/test/test-udp-options.c index b47457417e..34e652b711 100644 --- a/deps/uv/test/test-udp-options.c +++ b/deps/uv/test/test-udp-options.c @@ -28,6 +28,7 @@ TEST_IMPL(udp_options) { + static int invalid_ttls[] = { -1, 0, 256 }; uv_loop_t* loop; uv_udp_t h; int i, r; @@ -48,17 +49,17 @@ TEST_IMPL(udp_options) { r |= uv_udp_set_broadcast(&h, 0); ASSERT(r == 0); - /* values 0-255 should work */ - for (i = 0; i <= 255; i++) { + /* values 1-255 should work */ + for (i = 1; i <= 255; i++) { r = uv_udp_set_ttl(&h, i); ASSERT(r == 0); } - /* anything >255 should fail */ - r = uv_udp_set_ttl(&h, 256); - ASSERT(r == -1); - ASSERT(uv_last_error(loop).code == UV_EINVAL); - /* don't test ttl=-1, it's a valid value on some platforms */ + for (i = 0; i < (int) ARRAY_SIZE(invalid_ttls); i++) { + r = uv_udp_set_ttl(&h, invalid_ttls[i]); + ASSERT(r == -1); + ASSERT(uv_last_error(loop).code == UV_EINVAL); + } r = uv_udp_set_multicast_loop(&h, 1); r |= uv_udp_set_multicast_loop(&h, 1); diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 0d6e3b9a18..d03ea56898 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -180,28 +180,34 @@ 'include/uv-private/ev.h', 'include/uv-private/ngx-queue.h', 'include/uv-private/uv-unix.h', - 'src/unix/core.c', - 'src/unix/uv-eio.c', - 'src/unix/uv-eio.h', - 'src/unix/fs.c', - 'src/unix/udp.c', - 'src/unix/tcp.c', - 'src/unix/pipe.c', - 'src/unix/tty.c', - 'src/unix/stream.c', + 'src/unix/async.c', 'src/unix/cares.c', + 'src/unix/check.c', + 'src/unix/core.c', 'src/unix/dl.c', - 'src/unix/error.c', - 'src/unix/thread.c', - 'src/unix/process.c', - 'src/unix/internal.h', 'src/unix/eio/ecb.h', 'src/unix/eio/eio.c', 'src/unix/eio/xthread.h', + 'src/unix/error.c', 'src/unix/ev/ev.c', 'src/unix/ev/ev_vars.h', 'src/unix/ev/ev_wrap.h', 'src/unix/ev/event.h', + 'src/unix/fs.c', + 'src/unix/idle.c', + 'src/unix/internal.h', + 'src/unix/loop.c', + 'src/unix/pipe.c', + 'src/unix/prepare.c', + 'src/unix/process.c', + 'src/unix/stream.c', + 'src/unix/tcp.c', + 'src/unix/thread.c', + 'src/unix/timer.c', + 'src/unix/tty.c', + 'src/unix/udp.c', + 'src/unix/uv-eio.c', + 'src/unix/uv-eio.h', ], 'include_dirs': [ 'src/unix/ev', ], 'libraries': [ '-lm' ] @@ -215,6 +221,7 @@ ], }, 'defines': [ + '_DARWIN_USE_64_BIT_INODE=1', 'EV_CONFIG_H="config_darwin.h"', 'EIO_CONFIG_H="config_darwin.h"', ] @@ -224,6 +231,8 @@ 'sources': [ 'src/unix/linux/core.c', 'src/unix/linux/inotify.c', + 'src/unix/linux/syscalls.c', + 'src/unix/linux/syscalls.h', ], 'defines': [ 'EV_CONFIG_H="config_linux.h"',