uv: upgrade to e2cae340a6
authorBert Belder <bertbelder@gmail.com>
Sat, 28 Apr 2012 22:22:01 +0000 (00:22 +0200)
committerBert Belder <bertbelder@gmail.com>
Sat, 28 Apr 2012 22:22:01 +0000 (00:22 +0200)
67 files changed:
deps/uv/config-unix.mk
deps/uv/gyp_uv
deps/uv/include/uv-private/tree.h
deps/uv/include/uv-private/uv-unix.h
deps/uv/include/uv-private/uv-win.h
deps/uv/include/uv.h
deps/uv/src/unix/async.c [new file with mode: 0644]
deps/uv/src/unix/cares.c
deps/uv/src/unix/check.c [new file with mode: 0644]
deps/uv/src/unix/core.c
deps/uv/src/unix/cygwin.c
deps/uv/src/unix/darwin.c
deps/uv/src/unix/error.c
deps/uv/src/unix/fs.c
deps/uv/src/unix/idle.c [new file with mode: 0644]
deps/uv/src/unix/internal.h
deps/uv/src/unix/kqueue.c
deps/uv/src/unix/linux/inotify.c
deps/uv/src/unix/linux/syscalls.c [new file with mode: 0644]
deps/uv/src/unix/linux/syscalls.h [new file with mode: 0644]
deps/uv/src/unix/loop.c [new file with mode: 0644]
deps/uv/src/unix/pipe.c
deps/uv/src/unix/prepare.c [new file with mode: 0644]
deps/uv/src/unix/process.c
deps/uv/src/unix/stream.c
deps/uv/src/unix/sunos.c
deps/uv/src/unix/timer.c [new file with mode: 0644]
deps/uv/src/unix/udp.c
deps/uv/src/uv-common.c
deps/uv/src/uv-common.h
deps/uv/src/win/async.c
deps/uv/src/win/core.c
deps/uv/src/win/dl.c
deps/uv/src/win/error.c
deps/uv/src/win/fs.c
deps/uv/src/win/handle.c
deps/uv/src/win/internal.h
deps/uv/src/win/pipe.c
deps/uv/src/win/process.c
deps/uv/src/win/stream.c
deps/uv/src/win/tcp.c
deps/uv/src/win/udp.c
deps/uv/src/win/util.c
deps/uv/src/win/winapi.h
deps/uv/src/win/winsock.h
deps/uv/test/echo-server.c
deps/uv/test/runner-unix.c
deps/uv/test/runner-win.c
deps/uv/test/task.h
deps/uv/test/test-async.c
deps/uv/test/test-counters-init.c
deps/uv/test/test-fs-event.c
deps/uv/test/test-fs.c
deps/uv/test/test-get-memory.c
deps/uv/test/test-gethostbyname.c
deps/uv/test/test-ipc-send-recv.c
deps/uv/test/test-ipc.c
deps/uv/test/test-list.h
deps/uv/test/test-loop-handles.c
deps/uv/test/test-ping-pong.c
deps/uv/test/test-pipe-connect-error.c
deps/uv/test/test-platform-output.c
deps/uv/test/test-shutdown-close.c
deps/uv/test/test-spawn.c
deps/uv/test/test-stdio-over-pipes.c
deps/uv/test/test-udp-options.c
deps/uv/uv.gyp

index 6450183..cdcf5ea 100644 (file)
@@ -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
index 225c976..14a3cae 100755 (executable)
@@ -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.
index eb05cdc..f936416 100644 (file)
 #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)                   \
index bb8e5d6..e190b85 100644 (file)
@@ -33,6 +33,7 @@
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
 #include <netdb.h>
+#include <pwd.h>
 #include <termios.h>
 #include <pthread.h>
 
@@ -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; \
index 812b274..c55802c 100644 (file)
@@ -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;                       \
     };                                    \
   };
 
index 1609884..97d419d 100644 (file)
@@ -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;
 
 
@@ -374,10 +387,22 @@ struct uv_handle_s {
 };
 
 /*
+ * 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.
@@ -1087,6 +1128,30 @@ typedef struct uv_process_options_s {
 } 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
  */
 struct uv_process_s {
@@ -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 (file)
index 0000000..638774c
--- /dev/null
@@ -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);
+}
index 18cdefe..03667fd 100644 (file)
  * 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 (file)
index 0000000..a975210
--- /dev/null
@@ -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);
+}
index e4d481a..9602b64 100644 (file)
 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;
 
index aef8d76..31b069f 100644 (file)
@@ -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");
 }
index 6b3705f..e6deb30 100644 (file)
@@ -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;
   }
 
index 7ba2c89..aaeaf76 100644 (file)
@@ -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();
index 6615516..3417fa6 100644 (file)
@@ -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 (file)
index 0000000..5b4cf57
--- /dev/null
@@ -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);
+}
index bd2ee0f..e8701a3 100644 (file)
 #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 <linux/version.h>
-# include <sys/syscall.h>
-# include <features.h>
-# include <unistd.h>
-
-# 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_ */
index ec3ba32..4046323 100644 (file)
@@ -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);
index 9819f55..24ddbcb 100644 (file)
@@ -21,6 +21,7 @@
 #include "uv.h"
 #include "tree.h"
 #include "../internal.h"
+#include "syscalls.h"
 
 #include <stdint.h>
 #include <stdio.h>
 
 #include <sys/types.h>
 #include <unistd.h>
-#include <fcntl.h>
-
-#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 (file)
index 0000000..bdf90cf
--- /dev/null
@@ -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 <unistd.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#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 (file)
index 0000000..5d42044
--- /dev/null
@@ -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 <sys/types.h>
+#include <sys/socket.h>
+#include <linux/types.h>
+
+#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 (file)
index 0000000..5580aba
--- /dev/null
@@ -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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+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
+}
index 3573a57..7d0b2ec 100644 (file)
@@ -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 (file)
index 0000000..6c18fbd
--- /dev/null
@@ -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);
+}
index ffe0145..10872cc 100644 (file)
@@ -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);
+}
index fd24caa..b71f9bd 100644 (file)
@@ -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));
+}
index 37fdd89..0057e68 100644 (file)
@@ -37,6 +37,7 @@
 #include <sys/time.h>
 #include <unistd.h>
 #include <kstat.h>
+#include <fcntl.h>
 
 #if HAVE_PORTS_FS
 # include <sys/port.h>
@@ -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 (file)
index 0000000..6a00229
--- /dev/null
@@ -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 <assert.h>
+
+
+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);
+}
index e1c7621..105bdc0 100644 (file)
@@ -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;
 }
index 2e424a9..c8192bd 100644 (file)
 #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;
index e1f16b6..e82f584 100644 (file)
 
 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;
 };
 
index ee5faea..b68a868 100644 (file)
@@ -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);
   }
 }
index 1983361..1358cb2 100644 (file)
@@ -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);
 }
 
 
index a7d4ced..08374d3 100644 (file)
@@ -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);
index 7bdc3cd..499abe3 100644 (file)
@@ -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;
index 507336e..3cbb66f 100644 (file)
@@ -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
 
     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);
   }
index 2e053b0..797b071 100644 (file)
@@ -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;
index 470aed1..7cc469d 100644 (file)
@@ -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);
 
index 43aff62..35da85e 100644 (file)
@@ -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);
index 7474486..aacb061 100644 (file)
@@ -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) {
index d36bc68..4275bce 100644 (file)
@@ -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);
 }
index 21409ed..51ef604 100644 (file)
@@ -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;
index 1964401..42069af 100644 (file)
@@ -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
index 9f731ec..f4d5fdb 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
+#include <wchar.h>
 
 #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;
 
index df840d5..073b9e8 100644 (file)
         (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;
index 79b9e6b..d070d58 100644 (file)
@@ -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 */
index 6b0d897..d663d60 100644 (file)
@@ -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;
 
index 3c78bb5..d0ebfbf 100644 (file)
@@ -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);
index d2a986a..e758dd1 100644 (file)
@@ -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);
index a7938e6..0449734 100644 (file)
@@ -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);
 
index 3d84151..7cdad09 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 
+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;
index 29e7acd..6318684 100644 (file)
@@ -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;
index 42f990f..fe7bce2 100644 (file)
 #include <string.h>
 #include <fcntl.h>
 
+#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 */
index 8dc7147..a8fe0ab 100644 (file)
@@ -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;
+}
index 722bc77..2396939 100644 (file)
@@ -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);
index 583622e..e49c69c 100644 (file)
 #include <stdio.h>
 #include <string.h> /* 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,
index 96b47f0..970bf1e 100644 (file)
@@ -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);
index d70d5b2..1ea0e7f 100644 (file)
@@ -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);
index 5743243..84782b2 100644 (file)
@@ -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)
index 425dcf6..866445d 100644 (file)
@@ -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;
 }
index 245a601..1bdcc3b 100644 (file)
@@ -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);
 
index 4a6c511..cc06d42 100644 (file)
@@ -93,4 +93,4 @@ TEST_IMPL(pipe_connect_to_file) {
   ASSERT(connect_cb_called == 1);
 
   return 0;
-}
\ No newline at end of file
+}
index 1e17729..008d14f 100644 (file)
@@ -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);
 
index 864f7ce..eabbefc 100644 (file)
@@ -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++;
 }
index a4d6943..ccb9538 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+#ifndef _WIN32
+#include <unistd.h>
+#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 = &in;
+  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
index 2116d16..98173fe 100644 (file)
@@ -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
+}
index b474574..34e652b 100644 (file)
@@ -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);
index 0d6e3b9..d03ea56 100644 (file)
             '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' ]
             ],
           },
           'defines': [
+            '_DARWIN_USE_64_BIT_INODE=1',
             'EV_CONFIG_H="config_darwin.h"',
             'EIO_CONFIG_H="config_darwin.h"',
           ]
           '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"',