uv: upgrade to b7e150ee
authorBert Belder <bertbelder@gmail.com>
Tue, 12 Jun 2012 17:19:26 +0000 (19:19 +0200)
committerBert Belder <bertbelder@gmail.com>
Tue, 12 Jun 2012 17:54:56 +0000 (19:54 +0200)
32 files changed:
deps/uv/include/uv-private/ngx-queue.h
deps/uv/include/uv-private/uv-unix.h
deps/uv/src/unix/async.c
deps/uv/src/unix/core.c
deps/uv/src/unix/cygwin.c
deps/uv/src/unix/dl.c
deps/uv/src/unix/freebsd.c
deps/uv/src/unix/internal.h
deps/uv/src/unix/linux/core.c
deps/uv/src/unix/linux/syscalls.c
deps/uv/src/unix/linux/syscalls.h
deps/uv/src/unix/loop.c
deps/uv/src/unix/netbsd.c
deps/uv/src/unix/openbsd.c
deps/uv/src/unix/process.c
deps/uv/src/unix/stream.c
deps/uv/src/unix/sunos.c
deps/uv/src/unix/uv-eio.c
deps/uv/src/win/process.c
deps/uv/src/win/timer.c
deps/uv/src/win/util.c
deps/uv/src/win/winapi.c
deps/uv/src/win/winapi.h
deps/uv/test/benchmark-list.h
deps/uv/test/benchmark-million-timers.c [new file with mode: 0644]
deps/uv/test/benchmark-pound.c
deps/uv/test/runner.c
deps/uv/test/test-hrtime.c
deps/uv/test/test-list.h
deps/uv/test/test-tcp-close-while-connecting.c [new file with mode: 0644]
deps/uv/test/test-tcp-shutdown-after-write.c
deps/uv/uv.gyp

index 7058ce4..6fd0071 100644 (file)
@@ -100,7 +100,9 @@ struct ngx_queue_s {
 
 
 #define ngx_queue_foreach(q, h)                                               \
-    for ((q) = ngx_queue_head(h); (q) != (h); (q) = ngx_queue_next(q))
+    for ((q) = ngx_queue_head(h);                                             \
+         (q) != ngx_queue_sentinel(h);                                        \
+         (q) = ngx_queue_next(q))
 
 
 #endif /* NGX_QUEUE_H_INCLUDED_ */
index 3b9619c..62bb0aa 100644 (file)
@@ -38,6 +38,7 @@
 
 #include <semaphore.h>
 #include <pthread.h>
+#include <signal.h>
 
 #if __sun
 # include <sys/port.h>
@@ -113,6 +114,9 @@ struct uv__io_s {
   ngx_queue_t prepare_handles;                                                \
   ngx_queue_t check_handles;                                                  \
   ngx_queue_t idle_handles;                                                   \
+  ngx_queue_t async_handles;                                                  \
+  uv__io_t async_watcher;                                                     \
+  int async_pipefd[2];                                                        \
   /* RB_HEAD(uv__timers, uv_timer_s) */                                       \
   struct uv__timers { struct uv_timer_s* rbh_root; } timer_handles;           \
   uint64_t time;                                                              \
@@ -211,9 +215,10 @@ struct uv__io_s {
 
 
 /* UV_ASYNC */
-#define UV_ASYNC_PRIVATE_FIELDS \
-  ev_async async_watcher; \
-  uv_async_cb async_cb;
+#define UV_ASYNC_PRIVATE_FIELDS                                               \
+  volatile sig_atomic_t pending;                                              \
+  uv_async_cb async_cb;                                                       \
+  ngx_queue_t queue;
 
 
 /* UV_TIMER */
index db9ce18..f782e15 100644 (file)
 #include "uv.h"
 #include "internal.h"
 
+#include <errno.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
 
-static void uv__async(EV_P_ ev_async* w, int revents) {
-  uv_async_t* async = container_of(w, uv_async_t, async_watcher);
+static int uv__async_init(uv_loop_t* loop);
+static void uv__async_io(uv_loop_t* loop, uv__io_t* handle, int events);
 
-  if (async->async_cb) {
-    async->async_cb(async, 0);
-  }
-}
 
+int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
+  if (uv__async_init(loop))
+    return uv__set_sys_error(loop, errno);
 
-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);
+  uv__handle_init(loop, (uv_handle_t*)handle, UV_ASYNC);
   loop->counters.async_init++;
 
-  ev_async_init(&async->async_watcher, uv__async);
-  async->async_cb = async_cb;
+  handle->async_cb = async_cb;
+  handle->pending = 0;
 
-  /* Note: This does not have symmetry with the other libev wrappers. */
-  ev_async_start(loop->ev, &async->async_watcher);
-  uv__handle_unref(async);
-  uv__handle_start(async);
+  ngx_queue_insert_tail(&loop->async_handles, &handle->queue);
+  uv__handle_start(handle);
 
   return 0;
 }
 
 
-int uv_async_send(uv_async_t* async) {
-  ev_async_send(async->loop->ev, &async->async_watcher);
+int uv_async_send(uv_async_t* handle) {
+  int r;
+
+  handle->pending = 1; /* XXX needs a memory barrier? */
+
+  do
+    r = write(handle->loop->async_pipefd[1], "x", 1);
+  while (r == -1 && errno == EINTR);
+
+  if (r == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
+    return uv__set_sys_error(handle->loop, errno);
+
   return 0;
 }
 
 
 void uv__async_close(uv_async_t* handle) {
-  ev_async_stop(handle->loop->ev, &handle->async_watcher);
-  uv__handle_ref(handle);
+  ngx_queue_remove(&handle->queue);
   uv__handle_stop(handle);
 }
+
+
+static int uv__async_init(uv_loop_t* loop) {
+  if (loop->async_pipefd[0] != -1)
+    return 0;
+
+  if (uv__make_pipe(loop->async_pipefd, UV__F_NONBLOCK))
+    return -1;
+
+  uv__io_init(&loop->async_watcher,
+              uv__async_io,
+              loop->async_pipefd[0],
+              UV__IO_READ);
+  uv__io_start(loop, &loop->async_watcher);
+
+  return 0;
+}
+
+
+static void uv__async_io(uv_loop_t* loop, uv__io_t* handle, int events) {
+  char buf[1024];
+  ngx_queue_t* q;
+  uv_async_t* h;
+  ssize_t r;
+
+  while (1) {
+    r = read(loop->async_pipefd[0], buf, sizeof(buf));
+
+    if (r == sizeof(buf))
+      continue;
+
+    if (r != -1)
+      break;
+
+    if (errno == EAGAIN || errno == EWOULDBLOCK)
+      break;
+
+    if (errno == EINTR)
+      continue;
+
+    abort();
+  }
+
+  ngx_queue_foreach(q, &loop->async_handles) {
+    h = ngx_queue_data(q, uv_async_t, queue);
+    if (!h->pending) continue;
+    h->pending = 0;
+    h->async_cb(h, 0);
+  }
+}
index b33a6f7..ca74fb3 100644 (file)
@@ -233,6 +233,9 @@ static unsigned int uv__poll_timeout(uv_loop_t* loop) {
   if (!ngx_queue_empty(&loop->idle_handles))
     return 0;
 
+  if (loop->closing_handles)
+    return 0;
+
   return uv__next_timeout(loop);
 }
 
index 31b069f..a99779d 100644 (file)
@@ -29,7 +29,7 @@
 #include <time.h>
 
 #undef NANOSEC
-#define NANOSEC 1000000000
+#define NANOSEC ((uint64_t) 1e9)
 
 
 uint64_t uv_hrtime() {
index 9eb6600..01796e3 100644 (file)
@@ -31,6 +31,7 @@ static int uv__dlerror(uv_lib_t* lib);
 
 
 int uv_dlopen(const char* filename, uv_lib_t* lib) {
+  dlerror(); /* Reset error status. */
   lib->errmsg = NULL;
   lib->handle = dlopen(filename, RTLD_LAZY);
   return uv__dlerror(lib);
index 1e2c1d4..d916b0b 100644 (file)
@@ -38,7 +38,7 @@
 #include <fcntl.h>
 
 #undef NANOSEC
-#define NANOSEC 1000000000
+#define NANOSEC ((uint64_t) 1e9)
 
 #ifndef CPUSTATES
 # define CPUSTATES 5U
index 8a28b2a..23f16f7 100644 (file)
@@ -168,8 +168,12 @@ 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);
 
-#define UV__F_IPC        (1 << 0)
-#define UV__F_NONBLOCK   (1 << 1)
+#ifdef UV__O_NONBLOCK
+# define UV__F_NONBLOCK UV__O_NONBLOCK
+#else
+# define UV__F_NONBLOCK 1
+#endif
+
 int uv__make_socketpair(int fds[2], int flags);
 int uv__make_pipe(int fds[2], int flags);
 
index bee7026..34f48a9 100644 (file)
@@ -46,7 +46,7 @@
 #endif
 
 #undef NANOSEC
-#define NANOSEC 1000000000
+#define NANOSEC ((uint64_t) 1e9)
 
 /* This is rather annoying: CLOCK_BOOTTIME lives in <linux/time.h> but we can't
  * include that file because it conflicts with <time.h>. We'll just have to
index bdf90cf..4a1f8bc 100644 (file)
 # endif
 #endif /* __NR_accept4 */
 
+#ifndef __NR_eventfd
+# if __x86_64__
+#  define __NR_eventfd 284
+# elif __i386__
+#  define __NR_eventfd 323
+# elif __arm__
+#  define __NR_eventfd (UV_SYSCALL_BASE + 351)
+# endif
+#endif /* __NR_eventfd */
+
+#ifndef __NR_eventfd2
+# if __x86_64__
+#  define __NR_eventfd2 290
+# elif __i386__
+#  define __NR_eventfd2 328
+# elif __arm__
+#  define __NR_eventfd2 (UV_SYSCALL_BASE + 356)
+# endif
+#endif /* __NR_eventfd2 */
+
 #ifndef __NR_inotify_init
 # if __x86_64__
 #  define __NR_inotify_init 253
@@ -147,6 +167,24 @@ int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
 }
 
 
+int uv__eventfd(unsigned int count) {
+#if __NR_eventfd
+  return syscall(__NR_eventfd, count);
+#else
+  return errno = ENOSYS, -1;
+#endif
+}
+
+
+int uv__eventfd2(unsigned int count, int flags) {
+#if __NR_eventfd2
+  return syscall(__NR_eventfd2, count, flags);
+#else
+  return errno = ENOSYS, -1;
+#endif
+}
+
+
 int uv__inotify_init(void) {
 #if __NR_inotify_init
   return syscall(__NR_inotify_init);
index 5d42044..ec70fd9 100644 (file)
 #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__EFD_CLOEXEC       UV__O_CLOEXEC
+#define UV__EFD_NONBLOCK      UV__O_NONBLOCK
 
 #define UV__IN_CLOEXEC        UV__O_CLOEXEC
 #define UV__IN_NONBLOCK       UV__O_NONBLOCK
 
+#define UV__SOCK_CLOEXEC      UV__O_CLOEXEC
+#define UV__SOCK_NONBLOCK     UV__O_NONBLOCK
+
+/* inotify flags */
 #define UV__IN_ACCESS         0x001
 #define UV__IN_MODIFY         0x002
 #define UV__IN_ATTRIB         0x004
@@ -65,6 +69,8 @@ struct uv__mmsghdr {
 };
 
 int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags);
+int uv__eventfd(unsigned int count);
+int uv__eventfd2(unsigned int count, 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);
index 08985d6..75fad43 100644 (file)
@@ -40,12 +40,15 @@ int uv__loop_init(uv_loop_t* loop, int default_loop) {
   RB_INIT(&loop->timer_handles);
   ngx_queue_init(&loop->active_reqs);
   ngx_queue_init(&loop->idle_handles);
+  ngx_queue_init(&loop->async_handles);
   ngx_queue_init(&loop->check_handles);
   ngx_queue_init(&loop->prepare_handles);
   ngx_queue_init(&loop->handle_queue);
   loop->closing_handles = NULL;
   loop->channel = NULL;
   loop->time = uv_hrtime() / 1000000;
+  loop->async_pipefd[0] = -1;
+  loop->async_pipefd[1] = -1;
   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);
index 2fedc94..a1a7091 100644 (file)
@@ -32,7 +32,7 @@
 #include <time.h>
 
 #undef NANOSEC
-#define NANOSEC 1000000000
+#define NANOSEC ((uint64_t) 1e9)
 
 
 uint64_t uv_hrtime(void) {
index ec757a4..865f8e9 100644 (file)
@@ -37,7 +37,7 @@
 #include <unistd.h>
 
 #undef NANOSEC
-#define NANOSEC 1000000000
+#define NANOSEC ((uint64_t) 1e9)
 
 
 static char *process_title;
index d3eb998..230afe9 100644 (file)
@@ -68,25 +68,15 @@ static void uv__chld(EV_P_ ev_child* watcher, int revents) {
 
 
 int uv__make_socketpair(int fds[2], int flags) {
-#ifdef SOCK_NONBLOCK
-  int fl;
-
-  fl = SOCK_CLOEXEC;
-
-  if (flags & UV__F_NONBLOCK)
-    fl |= SOCK_NONBLOCK;
-
-  if (socketpair(AF_UNIX, SOCK_STREAM|fl, 0, fds) == 0)
+#if __linux__
+  if (socketpair(AF_UNIX, SOCK_STREAM | UV__SOCK_CLOEXEC | flags, 0, fds) == 0)
     return 0;
 
+  /* Retry on EINVAL, it means SOCK_CLOEXEC is not supported.
+   * Anything else is a genuine error.
+   */
   if (errno != EINVAL)
     return -1;
-
-  /* errno == EINVAL so maybe the kernel headers lied about
-   * the availability of SOCK_NONBLOCK. This can happen if people
-   * build libuv against newer kernel headers than the kernel
-   * they actually run the software on.
-   */
 #endif
 
   if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
@@ -106,14 +96,7 @@ int uv__make_socketpair(int fds[2], int flags) {
 
 int uv__make_pipe(int fds[2], int flags) {
 #if __linux__
-  int fl;
-
-  fl = UV__O_CLOEXEC;
-
-  if (flags & UV__F_NONBLOCK)
-    fl |= UV__O_NONBLOCK;
-
-  if (uv__pipe2(fds, fl) == 0)
+  if (uv__pipe2(fds, flags | UV__O_CLOEXEC) == 0)
     return 0;
 
   if (errno != ENOSYS)
index 602e948..89790ea 100644 (file)
@@ -708,7 +708,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
       stream->flags & UV_STREAM_SHUT ||
       stream->flags & UV_CLOSED ||
       stream->flags & UV_CLOSING) {
-    uv__set_sys_error(stream->loop, EINVAL);
+    uv__set_artificial_error(stream->loop, UV_ENOTCONN);
     return -1;
   }
 
index 3cf214c..d5867ac 100644 (file)
@@ -28,9 +28,7 @@
 #include <assert.h>
 #include <errno.h>
 
-#ifdef SUNOS_HAVE_IFADDRS
-# include <ifaddrs.h>
-#endif
+#include <ifaddrs.h>
 #include <net/if.h>
 
 #include <sys/loadavg.h>
@@ -407,9 +405,7 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
 
 uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
   int* count) {
-#ifndef SUNOS_HAVE_IFADDRS
-  return uv__new_artificial_error(UV_ENOSYS);
-#else
+
   struct ifaddrs *addrs, *ent;
   char ip[INET6_ADDRSTRLEN];
   uv_interface_address_t* address;
@@ -466,7 +462,6 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
   freeifaddrs(addrs);
 
   return uv_ok_;
-#endif  /* SUNOS_HAVE_IFADDRS */
 }
 
 
index 10dc0a6..0d931b8 100644 (file)
@@ -95,11 +95,13 @@ void uv_eio_init(uv_loop_t* loop) {
                 &loop->uv_eio_want_poll_notifier,
                 uv_eio_want_poll_notifier_cb);
   loop->uv_eio_want_poll_notifier.flags |= UV__HANDLE_INTERNAL;
+  uv__handle_unref(&loop->uv_eio_want_poll_notifier);
 
   uv_async_init(loop,
                 &loop->uv_eio_done_poll_notifier,
                 uv_eio_done_poll_notifier_cb);
   loop->uv_eio_done_poll_notifier.flags |= UV__HANDLE_INTERNAL;
+  uv__handle_unref(&loop->uv_eio_done_poll_notifier);
 
   uv_once(&uv__eio_init_once_guard, uv__eio_init);
 }
index 332ef0f..a2bd33b 100644 (file)
@@ -1320,32 +1320,46 @@ done:
 
 
 static uv_err_t uv__kill(HANDLE process_handle, int signum) {
-  DWORD status;
-  uv_err_t err;
+  switch (signum) {
+    case SIGTERM:
+    case SIGKILL:
+    case SIGINT: {
+      /* Unconditionally terminate the process. On Windows, killed processes */
+      /* normally return 1. */
+      DWORD error, status;
+
+      if (TerminateProcess(process_handle, 1))
+        return uv_ok_;
+
+      /* If the process already exited before TerminateProcess was called, */
+      /* TerminateProcess will fail with ERROR_ACESS_DENIED. */
+      error = GetLastError();
+      if (error == ERROR_ACCESS_DENIED &&
+          GetExitCodeProcess(process_handle, &status) &&
+          status != STILL_ACTIVE) {
+        return uv__new_artificial_error(UV_ESRCH);
+      }
 
-  if (signum == SIGTERM || signum == SIGKILL || signum == SIGINT) {
-    /* Kill the process. On Windows, killed processes normally return 1. */
-    if (TerminateProcess(process_handle, 1)) {
-      err = uv_ok_;
-    } else {
-      err = uv__new_sys_error(GetLastError());
+      return uv__new_sys_error(error);
     }
-  } else if (signum == 0) {
-    /* Health check: is the process still alive? */
-    if (GetExitCodeProcess(process_handle, &status)) {
-      if (status == STILL_ACTIVE) {
-        err =  uv_ok_;
-      } else {
-        err = uv__new_artificial_error(UV_ESRCH);
-      }
-    } else {
-      err = uv__new_sys_error(GetLastError());
+
+    case 0: {
+      /* Health check: is the process still alive? */
+      DWORD status;
+
+      if (!GetExitCodeProcess(process_handle, &status))
+        return uv__new_sys_error(GetLastError());
+
+      if (status != STILL_ACTIVE)
+        return uv__new_artificial_error(UV_ESRCH);
+
+      return uv_ok_;
     }
-  } else {
-    err = uv__new_artificial_error(UV_ENOSYS);
-  }
 
-  return err;
+    default:
+      /* Unsupported signal. */
+      return uv__new_artificial_error(UV_ENOSYS);
+  }
 }
 
 
index 69638bc..5ddcfca 100644 (file)
@@ -90,6 +90,7 @@ void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) {
 int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, int64_t timeout,
     int64_t repeat) {
   uv_loop_t* loop = handle->loop;
+  uv_timer_t* old;
 
   if (handle->flags & UV_HANDLE_ACTIVE) {
     RB_REMOVE(uv_timer_tree_s, &loop->timers, handle);
@@ -101,9 +102,8 @@ int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, int64_t timeout,
   handle->flags |= UV_HANDLE_ACTIVE;
   uv__handle_start(handle);
 
-  if (RB_INSERT(uv_timer_tree_s, &loop->timers, handle) != NULL) {
-    uv_fatal_error(ERROR_INVALID_DATA, "RB_INSERT");
-  }
+  old = RB_INSERT(uv_timer_tree_s, &loop->timers, handle);
+  assert(old == NULL);
 
   return 0;
 }
index be43d50..4ceae04 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <assert.h>
 #include <direct.h>
+#include <limits.h>
 #include <malloc.h>
 #include <stdio.h>
 #include <string.h>
@@ -773,8 +774,13 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
   for (adapter_address = adapter_addresses;
        adapter_address != NULL;
        adapter_address = adapter_address->Next) {
+
+    if (adapter_address->OperStatus != IfOperStatusUp)
+      continue;
+
     unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*)
                       adapter_address->FirstUnicastAddress;
+
     while (unicast_address) {
       (*count)++;
       unicast_address = unicast_address->Next;
@@ -792,6 +798,10 @@ uv_err_t uv_interface_addresses(uv_interface_address_t** addresses,
   for (adapter_address = adapter_addresses;
        adapter_address != NULL;
        adapter_address = adapter_address->Next) {
+
+    if (adapter_address->OperStatus != IfOperStatusUp)
+      continue;
+
     name = NULL;
     unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*)
                       adapter_address->FirstUnicastAddress;
index 80c3e52..ab5513a 100644 (file)
 #include "internal.h"
 
 
+/* Ntdll function pointers */
 sRtlNtStatusToDosError pRtlNtStatusToDosError;
 sNtDeviceIoControlFile pNtDeviceIoControlFile;
 sNtQueryInformationFile pNtQueryInformationFile;
 sNtSetInformationFile pNtSetInformationFile;
 sNtQuerySystemInformation pNtQuerySystemInformation;
+
+
+/* Kernel32 function pointers */
 sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
 sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
 sCreateSymbolicLinkW pCreateSymbolicLinkW;
index 2f57e39..df1e822 100644 (file)
@@ -4419,7 +4419,7 @@ typedef VOID (WINAPI* sReleaseSRWLockExclusive)
 
 
 
-/* Ntapi function pointers */
+/* Ntdll function pointers */
 extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
 extern sNtDeviceIoControlFile pNtDeviceIoControlFile;
 extern sNtQueryInformationFile pNtQueryInformationFile;
index e4494f1..32cd1ba 100644 (file)
@@ -46,6 +46,7 @@ BENCHMARK_DECLARE (gethostbyname)
 BENCHMARK_DECLARE (getaddrinfo)
 BENCHMARK_DECLARE (spawn)
 BENCHMARK_DECLARE (thread_create)
+BENCHMARK_DECLARE (million_timers)
 HELPER_DECLARE    (tcp4_blackhole_server)
 HELPER_DECLARE    (tcp_pump_server)
 HELPER_DECLARE    (pipe_pump_server)
@@ -106,4 +107,5 @@ TASK_LIST_START
 
   BENCHMARK_ENTRY  (spawn)
   BENCHMARK_ENTRY  (thread_create)
+  BENCHMARK_ENTRY  (million_timers)
 TASK_LIST_END
diff --git a/deps/uv/test/benchmark-million-timers.c b/deps/uv/test/benchmark-million-timers.c
new file mode 100644 (file)
index 0000000..ae56b2b
--- /dev/null
@@ -0,0 +1,65 @@
+/* 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 "task.h"
+#include "uv.h"
+
+#define NUM_TIMERS (1000 * 1000)
+
+static int timer_cb_called;
+
+
+static void timer_cb(uv_timer_t* handle, int status) {
+  timer_cb_called++;
+}
+
+
+BENCHMARK_IMPL(million_timers) {
+  uv_timer_t* timers;
+  uv_loop_t* loop;
+  uint64_t before;
+  uint64_t after;
+  int timeout;
+  int i;
+
+  timers = malloc(NUM_TIMERS * sizeof(timers[0]));
+  ASSERT(timers != NULL);
+
+  loop = uv_default_loop();
+  timeout = 0;
+
+  for (i = 0; i < NUM_TIMERS; i++) {
+    if (i % 1000 == 0) timeout++;
+    ASSERT(0 == uv_timer_init(loop, timers + i));
+    ASSERT(0 == uv_timer_start(timers + i, timer_cb, timeout, 0));
+  }
+
+  before = uv_hrtime();
+  ASSERT(0 == uv_run(loop));
+  after = uv_hrtime();
+
+  ASSERT(timer_cb_called == NUM_TIMERS);
+  free(timers);
+
+  LOGF("%.2f seconds\n", (after - before) / 1e9);
+
+  return 0;
+}
index 1693c31..5c29a05 100644 (file)
@@ -26,7 +26,7 @@
 #define MAX_CONNS 1000
 
 #undef NANOSEC
-#define NANOSEC ((uint64_t)10e8)
+#define NANOSEC ((uint64_t) 1e9)
 
 #undef DEBUG
 #define DEBUG 0
index 1bda480..214c9a0 100644 (file)
@@ -32,7 +32,7 @@ static void log_progress(int total, int passed, int failed, const char* name) {
   if (total == 0)
     total = 1;
 
-  LOGF("[%% %3d|+ %3d|- %3d]: %s", (passed + failed) / total * 100,
+  LOGF("[%% %3d|+ %3d|- %3d]: %s", (int) ((passed + failed) / ((double) total) * 100.0),
       passed, failed, name);
 }
 
index 566e0d2..91059f0 100644 (file)
 #endif
 
 #ifndef NANOSEC
-# define NANOSEC 1000000000
+# define NANOSEC ((uint64_t) 1e9)
 #endif
 
 
 TEST_IMPL(hrtime) {
   uint64_t a, b, diff;
-
-  a = uv_hrtime();
-  uv_sleep(100);
-  b = uv_hrtime();
-
-  diff = b - a;
-
-  printf("diff = %llu\n", (unsigned long long int) diff);
-
-  /* The windows Sleep() function has only a resolution of 10-20 ms. */
-  /* Check that the difference between the two hrtime values is somewhat in */
-  /* the range we expect it to be. */
-  ASSERT(diff > (uint64_t) 80 * NANOSEC / MILLISEC);
-  ASSERT(diff < (uint64_t) 120 * NANOSEC / MILLISEC);
+  int i = 100;
+  while (i > 0) {
+    a = uv_hrtime();
+    uv_sleep(45);
+    b = uv_hrtime();
+
+    diff = b - a;
+
+    /*  printf("i= %d diff = %llu\n", i, (unsigned long long int) diff); */
+
+    /* The windows Sleep() function has only a resolution of 10-20 ms. */
+    /* Check that the difference between the two hrtime values is somewhat in */
+    /* the range we expect it to be. */
+    ASSERT(diff > (uint64_t) 25 * NANOSEC / MILLISEC);
+    ASSERT(diff < (uint64_t) 60 * NANOSEC / MILLISEC);
+    --i;
+  }
   return 0;
 }
index b9104d6..9af246d 100644 (file)
@@ -51,6 +51,7 @@ TEST_DECLARE   (tcp_bind_localhost_ok)
 TEST_DECLARE   (tcp_listen_without_bind)
 TEST_DECLARE   (tcp_connect_error_fault)
 TEST_DECLARE   (tcp_connect_timeout)
+TEST_DECLARE   (tcp_close_while_connecting)
 TEST_DECLARE   (tcp_close)
 TEST_DECLARE   (tcp_flags)
 TEST_DECLARE   (tcp_write_error)
@@ -243,6 +244,7 @@ TASK_LIST_START
   TEST_ENTRY  (tcp_listen_without_bind)
   TEST_ENTRY  (tcp_connect_error_fault)
   TEST_ENTRY  (tcp_connect_timeout)
+  TEST_ENTRY  (tcp_close_while_connecting)
   TEST_ENTRY  (tcp_close)
   TEST_ENTRY  (tcp_flags)
   TEST_ENTRY  (tcp_write_error)
diff --git a/deps/uv/test/test-tcp-close-while-connecting.c b/deps/uv/test/test-tcp-close-while-connecting.c
new file mode 100644 (file)
index 0000000..93e331d
--- /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 "task.h"
+
+static uv_timer_t timer1_handle;
+static uv_timer_t timer2_handle;
+static uv_tcp_t tcp_handle;
+
+static int connect_cb_called;
+static int timer1_cb_called;
+static int close_cb_called;
+
+
+static void close_cb(uv_handle_t* handle) {
+  close_cb_called++;
+}
+
+
+static void connect_cb(uv_connect_t* req, int status) {
+  ASSERT(status == -1);
+  ASSERT(uv_last_error(req->handle->loop).code == UV_EINTR);
+  uv_timer_stop(&timer2_handle);
+  connect_cb_called++;
+}
+
+
+static void timer1_cb(uv_timer_t* handle, int status) {
+  uv_close((uv_handle_t*)handle, close_cb);
+  uv_close((uv_handle_t*)&tcp_handle, close_cb);
+  timer1_cb_called++;
+}
+
+
+static void timer2_cb(uv_timer_t* handle, int status) {
+  ASSERT(0 && "should not be called");
+}
+
+
+TEST_IMPL(tcp_close_while_connecting) {
+  uv_connect_t connect_req;
+  struct sockaddr_in addr;
+  uv_loop_t* loop;
+
+  addr = uv_ip4_addr("1.2.3.4", TEST_PORT);
+  loop = uv_default_loop();
+
+  ASSERT(0 == uv_tcp_init(loop, &tcp_handle));
+  ASSERT(0 == uv_tcp_connect(&connect_req, &tcp_handle, addr, connect_cb));
+  ASSERT(0 == uv_timer_init(loop, &timer1_handle));
+  ASSERT(0 == uv_timer_start(&timer1_handle, timer1_cb, 50, 0));
+  ASSERT(0 == uv_timer_init(loop, &timer2_handle));
+  ASSERT(0 == uv_timer_start(&timer2_handle, timer2_cb, 86400 * 1000, 0));
+  ASSERT(0 == uv_run(loop));
+
+  ASSERT(connect_cb_called == 1);
+  ASSERT(timer1_cb_called == 1);
+  ASSERT(close_cb_called == 2);
+
+  return 0;
+}
index 8bf9123..219a3b4 100644 (file)
@@ -70,13 +70,18 @@ static void timer_cb(uv_timer_t* handle, int status) {
 }
 
 
+static void read_cb(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
+}
+
+
 static void connect_cb(uv_connect_t* req, int status) {
+  int r;
+
   ASSERT(status == 0);
   connect_cb_called++;
-}
 
-
-static void read_cb(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
+  r = uv_read_start((uv_stream_t*)&conn, alloc_cb, read_cb);
+  ASSERT(r == 0);
 }
 
 
@@ -113,9 +118,6 @@ TEST_IMPL(tcp_shutdown_after_write) {
   r = uv_tcp_connect(&connect_req, &conn, addr, connect_cb);
   ASSERT(r == 0);
 
-  r = uv_read_start((uv_stream_t*)&conn, alloc_cb, read_cb);
-  ASSERT(r == 0);
-
   r = uv_run(loop);
   ASSERT(r == 0);
 
index 964933d..5409389 100644 (file)
         'test/test-tcp-bind-error.c',
         'test/test-tcp-bind6-error.c',
         'test/test-tcp-close.c',
+        'test/test-tcp-close-while-connecting.c',
         'test/test-tcp-connect-error-after-write.c',
         'test/test-tcp-shutdown-after-write.c',
         'test/test-tcp-flags.c',
         'test/benchmark-getaddrinfo.c',
         'test/benchmark-list.h',
         'test/benchmark-loop-count.c',
+        'test/benchmark-million-timers.c',
         'test/benchmark-ping-pongs.c',
         'test/benchmark-pound.c',
         'test/benchmark-pump.c',