uv: upgrade to 4e1f2b1
authorBen Noordhuis <info@bnoordhuis.nl>
Sun, 12 Feb 2012 15:12:04 +0000 (16:12 +0100)
committerBen Noordhuis <info@bnoordhuis.nl>
Sun, 12 Feb 2012 15:12:04 +0000 (16:12 +0100)
22 files changed:
deps/uv/AUTHORS
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/eio/config_linux.h
deps/uv/src/unix/eio/eio.c
deps/uv/src/unix/error.c
deps/uv/src/unix/stream.c
deps/uv/src/win/error.c
deps/uv/src/win/internal.h
deps/uv/src/win/pipe.c
deps/uv/src/win/stream.c
deps/uv/src/win/tcp.c
deps/uv/src/win/tty.c
deps/uv/src/win/winsock.h
deps/uv/test/run-tests.c
deps/uv/test/test-fs.c
deps/uv/test/test-ipc-threads.c [deleted file]
deps/uv/test/test-list.h
deps/uv/test/test-ping-pong.c
deps/uv/test/test-udp-multicast-ttl.c [new file with mode: 0644]
deps/uv/uv.gyp

index f1fef1c..37452ac 100644 (file)
@@ -40,3 +40,6 @@ Maciej MaƂecki <maciej.malecki@notimplemented.org>
 Yasuhiro Matsumoto <mattn.jp@gmail.com>
 Daisuke Murase <typester@cpan.org>
 Paddy Byers <paddy.byers@gmail.com>
+Dan VerWeire <dverweire@gmail.com>
+Brandon Benvie <brandon@bbenvie.com>
+Brandon Philips <brandon.philips@rackspace.com>
index 792ca84..24ef37c 100644 (file)
@@ -192,9 +192,6 @@ typedef void* uv_lib_t;
   struct termios orig_termios; \
   int mode;
 
-#define UV_STREAM_INFO_PRIVATE_FIELDS \
-  int fd;
-
 /* UV_FS_EVENT_PRIVATE_FIELDS */
 #if defined(__linux__)
 
index 626eb6d..5a6a949 100644 (file)
@@ -450,11 +450,6 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
   wchar_t* dirw;                          \
   char* buffer;
 
-#define UV_STREAM_INFO_PRIVATE_FIELDS     \
-  union {                                 \
-    WSAPROTOCOL_INFOW socket_info;        \
-  };
-
 int uv_utf16_to_utf8(const wchar_t* utf16Buffer, size_t utf16Size,
     char* utf8Buffer, size_t utf8Size);
 int uv_utf8_to_utf16(const char* utf8Buffer, wchar_t* utf16Buffer,
index ba93e07..f4ee49c 100644 (file)
@@ -41,8 +41,9 @@ extern "C" {
 #   define UV_EXTERN /* nothing */
 #   define CARES_STATICLIB 1
 # endif
+#elif __GNUC__ >= 4
+# define UV_EXTERN __attribute__((visibility("default")))
 #else
-  /* Unix. TODO: symbol hiding */
 # define UV_EXTERN /* nothing */
 #endif
 
@@ -117,7 +118,9 @@ typedef intptr_t ssize_t;
   XX( 47, EEXIST, "file already exists") \
   XX( 48, ESRCH, "no such process") \
   XX( 49, ENAMETOOLONG, "name too long") \
-  XX( 50, EPERM, "operation not permitted")
+  XX( 50, EPERM, "operation not permitted") \
+  XX( 51, ELOOP, "too many symbolic links encountered") \
+  XX( 52, EXDEV, "cross-device link not permitted")
 
 
 #define UV_ERRNO_GEN(val, name, s) UV_##name = val,
@@ -181,7 +184,6 @@ typedef struct uv_process_s uv_process_t;
 typedef struct uv_counters_s uv_counters_t;
 typedef struct uv_cpu_info_s uv_cpu_info_t;
 typedef struct uv_interface_address_s uv_interface_address_t;
-typedef struct uv_stream_info_s uv_stream_info_t;
 /* Request types */
 typedef struct uv_req_s uv_req_t;
 typedef struct uv_shutdown_s uv_shutdown_t;
@@ -237,15 +239,27 @@ UV_EXTERN int64_t uv_now(uv_loop_t*);
 
 
 /*
- * The status parameter is 0 if the request completed successfully,
- * and should be -1 if the request was cancelled or failed.
- * Error details can be obtained by calling uv_last_error().
+ * Should return a buffer that libuv can use to read data into.
  *
- * In the case of uv_read_cb the uv_buf_t returned should be freed by the
- * user.
+ * `suggested_size` is a hint. Returning a buffer that is smaller is perfectly
+ * okay as long as `buf.len > 0`.
  */
 typedef uv_buf_t (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size);
+
+/*
+ * `nread` is > 0 if there is data available, 0 if libuv is done reading for now
+ * or -1 on error.
+ *
+ * Error details can be obtained by calling uv_last_error(). UV_EOF indicates
+ * that the stream has been closed.
+ *
+ * The callee is responsible for closing the stream when an error happens.
+ * Trying to read from the stream again is undefined.
+ *
+ * The callee is responsible for freeing the buffer, libuv does not reuse it.
+ */
 typedef void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, uv_buf_t buf);
+
 /*
  * Just like the uv_read_cb except that if the pending parameter is true
  * then you can use uv_accept() to pull the new handle into the process.
@@ -253,6 +267,7 @@ typedef void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, uv_buf_t buf);
  */
 typedef void (*uv_read2_cb)(uv_pipe_t* pipe, ssize_t nread, uv_buf_t buf,
     uv_handle_type pending);
+
 typedef void (*uv_write_cb)(uv_write_t* req, int status);
 typedef void (*uv_connect_cb)(uv_connect_t* req, int status);
 typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status);
@@ -491,6 +506,13 @@ struct uv_write_s {
 };
 
 
+/*
+ * Used to determine whether a stream is readable or writable.
+ * TODO: export in v0.8.
+ */
+/* UV_EXTERN */ int uv_is_readable(uv_stream_t* handle);
+/* UV_EXTERN */ int uv_is_writable(uv_stream_t* handle);
+
 
 /*
  * uv_tcp_t is a subclass of uv_stream_t
@@ -533,28 +555,6 @@ UV_EXTERN int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name,
     int* namelen);
 
 /*
- * uv_stream_info_t is used to store exported stream (using uv_export),
- * which can be imported into a different event-loop within the same process
- * (using uv_import).
- */
-struct uv_stream_info_s {
-  uv_handle_type type;
-  UV_STREAM_INFO_PRIVATE_FIELDS
-};
-
-/*
- * Exports uv_stream_t as uv_stream_info_t value, which could
- * be used to initialize shared streams within the same process.
- */
-UV_EXTERN int uv_export(uv_stream_t* stream, uv_stream_info_t* info);
-
-/*
- * Imports uv_stream_info_t value into uv_stream_t to initialize
- * shared stream.
- */
-UV_EXTERN int uv_import(uv_stream_t* stream, uv_stream_info_t* info);
-
-/*
  * uv_tcp_connect, uv_tcp_connect6
  * These functions establish IPv4 and IPv6 TCP connections. Provide an
  * initialized TCP handle and an uninitialized uv_connect_t*. The callback
index 606301f..e7a0d6e 100644 (file)
@@ -13,8 +13,8 @@
 /* utimes(2) is available */
 #define HAVE_UTIMES 1
 
-/* futimes(2) is available */
-#define HAVE_FUTIMES 1
+/* futimes(2) is available but we make the syscall directly. */
+#undef HAVE_FUTIMES
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #define HAVE_INTTYPES_H 1
@@ -56,6 +56,9 @@
 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
 
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#define HAVE_SYS_SYSCALL_H 1
+
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
 
index 58300a6..248af9e 100644 (file)
@@ -1039,8 +1039,15 @@ eio__utimes (const char *filename, const struct timeval times[2])
 static int
 eio__futimes (int fd, const struct timeval tv[2])
 {
+#if defined(__linux) && defined(__NR_utimensat)
+  struct timespec ts[2];
+  ts[0].tv_sec = tv[0].tv_sec, ts[0].tv_nsec = tv[0].tv_usec * 1000;
+  ts[1].tv_sec = tv[1].tv_sec, ts[1].tv_nsec = tv[1].tv_usec * 1000;
+  return syscall(__NR_utimensat, fd, NULL, ts, 0);
+#else
   errno = ENOSYS;
   return -1;
+#endif
 }
 
 #endif
index b4886cf..b167f7a 100644 (file)
@@ -74,6 +74,8 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
     case EMSGSIZE: return UV_EMSGSIZE;
     case ENAMETOOLONG: return UV_ENAMETOOLONG;
     case EINVAL: return UV_EINVAL;
+    case ECONNABORTED: return UV_ECONNABORTED;
+    case ELOOP: return UV_ELOOP;
     case ECONNREFUSED: return UV_ECONNREFUSED;
     case EADDRINUSE: return UV_EADDRINUSE;
     case EADDRNOTAVAIL: return UV_EADDRNOTAVAIL;
@@ -85,6 +87,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
     case EAI_NONAME: return UV_ENOENT;
     case ESRCH: return UV_ESRCH;
     case ETIMEDOUT: return UV_ETIMEDOUT;
+    case EXDEV: return UV_EXDEV;
     default: return UV_UNKNOWN;
   }
   UNREACHABLE();
index 9e58fc5..111bbc2 100644 (file)
@@ -802,6 +802,8 @@ int uv__connect(uv_connect_t* req, uv_stream_t* stream, struct sockaddr* addr,
       /* If we get a ECONNREFUSED wait until the next tick to report the
        * error. Solaris wants to report immediately--other unixes want to
        * wait.
+       *
+       * XXX: do the same for ECONNABORTED?
        */
       case ECONNREFUSED:
         stream->delayed_error = errno;
@@ -966,40 +968,11 @@ int uv_read_stop(uv_stream_t* stream) {
 }
 
 
-int uv_export(uv_stream_t* stream, uv_stream_info_t* info) {
-  int fd;
-
-  if (stream->type != UV_TCP) {
-    uv__set_artificial_error(stream->loop, UV_EINVAL);
-    return -1;
-  }
-
-  fd = uv__dup(stream->fd);
-
-  if (fd == -1) {
-    uv__set_sys_error(stream->loop, errno);
-    return -1;
-  }
-
-  info->type = stream->type;
-  info->fd = fd;
-
-  return 0;
+int uv_is_readable(uv_stream_t* stream) {
+  return stream->flags & UV_READABLE;
 }
 
 
-int uv_import(uv_stream_t* stream, uv_stream_info_t* info) {
-  if (info->type != UV_TCP) {
-    uv__set_artificial_error(stream->loop, UV_EINVAL);
-    return -1;
-  }
-
-  if (stream->fd != -1) {
-    uv__set_artificial_error(stream->loop, UV_EALREADY);
-    return -1;
-  }
-
-  stream->fd = info->fd;
-
-  return 0;
+int uv_is_writable(uv_stream_t* stream) {
+  return stream->flags & UV_WRITABLE;
 }
index 7790610..dd0018d 100644 (file)
@@ -89,6 +89,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
     case WSAEHOSTUNREACH:                   return UV_EHOSTUNREACH;
     case ERROR_INVALID_DATA:                return UV_EINVAL;
     case WSAEINVAL:                         return UV_EINVAL;
+    case ERROR_CANT_RESOLVE_FILENAME:       return UV_ELOOP;
     case ERROR_TOO_MANY_OPEN_FILES:         return UV_EMFILE;
     case WSAEMFILE:                         return UV_EMFILE;
     case WSAEMSGSIZE:                       return UV_EMSGSIZE;
index 9435bb2..0dc551d 100644 (file)
@@ -143,14 +143,11 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
 
 void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
 
-int uv__tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info);
+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);
 
-int uv_tcp_export(uv_tcp_t* tcp, uv_stream_info_t* info);
-int uv_tcp_import(uv_tcp_t* tcp, uv_stream_info_t* info);
-
 
 /*
  * UDP
index 60f137e..ae769c1 100644 (file)
@@ -98,6 +98,62 @@ static void uv_pipe_connection_init(uv_pipe_t* handle) {
 }
 
 
+static int open_named_pipe(uv_pipe_t* handle) {
+  /* 
+   * Assume that we have a duplex pipe first, so attempt to 
+   * connect with GENERIC_READ | GENERIC_WRITE.
+   */
+  handle->handle = CreateFileW(handle->name,
+                               GENERIC_READ | GENERIC_WRITE,
+                               0,
+                               NULL,
+                               OPEN_EXISTING,
+                               FILE_FLAG_OVERLAPPED,
+                               NULL);
+
+  if (handle->handle != INVALID_HANDLE_VALUE) {
+    return 0;
+  }
+
+  /* 
+   * If the pipe is not duplex CreateFileW fails with 
+   * ERROR_ACCESS_DENIED.  In that case try to connect
+   * as a read-only or write-only.
+   */
+  if (GetLastError() == ERROR_ACCESS_DENIED) {
+    handle->handle = CreateFileW(handle->name,
+                                 GENERIC_READ | FILE_WRITE_ATTRIBUTES,
+                                 0,
+                                 NULL,
+                                 OPEN_EXISTING,
+                                 FILE_FLAG_OVERLAPPED,
+                                 NULL);
+
+    if (handle->handle != INVALID_HANDLE_VALUE) {
+      handle->flags |= UV_HANDLE_SHUT;
+      return 0;
+    }
+  }
+
+  if (GetLastError() == ERROR_ACCESS_DENIED) {
+    handle->handle = CreateFileW(handle->name,
+                                 GENERIC_WRITE | FILE_READ_ATTRIBUTES,
+                                 0,
+                                 NULL,
+                                 OPEN_EXISTING,
+                                 FILE_FLAG_OVERLAPPED,
+                                 NULL);
+
+    if (handle->handle != INVALID_HANDLE_VALUE) {
+      handle->flags |= UV_HANDLE_EOF;
+      return 0;
+    }
+  }
+
+  return -1;
+}
+
+
 int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
     char* name, size_t nameSize) {
   HANDLE pipeHandle;
@@ -437,15 +493,7 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
   /* We wait for the pipe to become available with WaitNamedPipe. */
   while (WaitNamedPipeW(handle->name, 30000)) {
     /* The pipe is now available, try to connect. */
-    pipeHandle = CreateFileW(handle->name,
-                            GENERIC_READ | GENERIC_WRITE,
-                            0,
-                            NULL,
-                            OPEN_EXISTING,
-                            FILE_FLAG_OVERLAPPED,
-                            NULL);
-
-    if (pipeHandle != INVALID_HANDLE_VALUE) {
+    if (open_named_pipe(handle) == 0) {
       break;
     }
 
@@ -471,7 +519,6 @@ 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;
-  HANDLE pipeHandle;
 
   handle->handle = INVALID_HANDLE_VALUE;
 
@@ -492,15 +539,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
     goto error;
   }
 
-  pipeHandle = CreateFileW(handle->name,
-                          GENERIC_READ | GENERIC_WRITE,
-                          0,
-                          NULL,
-                          OPEN_EXISTING,
-                          FILE_FLAG_OVERLAPPED,
-                          NULL);
-
-  if (pipeHandle == INVALID_HANDLE_VALUE) {
+  if (open_named_pipe(handle) != 0) {
     if (GetLastError() == ERROR_PIPE_BUSY) {
       /* Wait for the server to make a pipe instance available. */
       if (!QueueUserWorkItem(&pipe_connect_thread_proc,
@@ -519,13 +558,13 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
     goto error;
   }
 
-  if (uv_set_pipe_handle(loop, (uv_pipe_t*)req->handle, pipeHandle)) {
+  assert(handle->handle != INVALID_HANDLE_VALUE);
+
+  if (uv_set_pipe_handle(loop, (uv_pipe_t*)req->handle, handle->handle)) {
     errno = GetLastError();
     goto error;
   }
 
-  handle->handle = pipeHandle;
-
   SET_REQ_SUCCESS(req);
   uv_insert_pending_req(loop, (uv_req_t*) req);
   handle->reqs_pending++;
@@ -537,8 +576,9 @@ error:
     handle->name = NULL;
   }
 
-  if (pipeHandle != INVALID_HANDLE_VALUE) {
-    CloseHandle(pipeHandle);
+  if (handle->handle != INVALID_HANDLE_VALUE) {
+    CloseHandle(handle->handle);
+    handle->handle = INVALID_HANDLE_VALUE;
   }
 
   /* Make this req pending reporting an error. */
@@ -649,7 +689,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
       return -1;
     }
 
-    return uv__tcp_import((uv_tcp_t*)client, server->pending_socket_info);
+    return uv_tcp_import((uv_tcp_t*)client, server->pending_socket_info);
   } else {
     pipe_client = (uv_pipe_t*)client;
 
index 7faa0a2..ea7363e 100644 (file)
@@ -188,25 +188,11 @@ size_t uv_count_bufs(uv_buf_t bufs[], int count) {
 }
 
 
-int uv_export(uv_stream_t* stream, uv_stream_info_t* info) {
-  switch (stream->type) {
-    case UV_TCP:
-      return uv_tcp_export((uv_tcp_t*)stream, info);
-    default:
-      assert(0);
-      uv__set_sys_error(stream->loop, WSAEINVAL);
-      return -1;
-  }
+int uv_is_readable(uv_stream_t* handle) {
+  return !(handle->flags & UV_HANDLE_EOF);
 }
 
 
-int uv_import(uv_stream_t* stream, uv_stream_info_t* info) {
-  switch (stream->type) {
-    case UV_TCP:
-      return uv_tcp_import((uv_tcp_t*)stream, info);
-    default:
-      assert(0);
-      uv__set_sys_error(stream->loop, WSAEINVAL);
-      return -1;
-  }
-}
\ No newline at end of file
+int uv_is_writable(uv_stream_t* handle) {
+  return !(handle->flags & UV_HANDLE_SHUT);
+}
index 590d079..f810913 100644 (file)
@@ -1019,7 +1019,7 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
 }
 
 
-int uv__tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info) {
+int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info) {
   SOCKET socket = WSASocketW(AF_INET,
                              SOCK_STREAM,
                              IPPROTO_IP,
@@ -1140,25 +1140,4 @@ int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
   }
 
   return 0;
-}
-
-
-int uv_tcp_export(uv_tcp_t* tcp, uv_stream_info_t* info) {
-  if (uv_tcp_duplicate_socket(tcp, GetCurrentProcessId(),
-      &info->socket_info) == -1) {
-    return -1;
-  }
-
-  info->type = UV_TCP;
-  return 0;
-}
-
-
-int uv_tcp_import(uv_tcp_t* tcp, uv_stream_info_t* info) {
-  if (info->type != UV_TCP) {
-    uv__set_sys_error(tcp->loop, WSAEINVAL);
-    return -1;
-  }
-
-  return uv__tcp_import(tcp, &info->socket_info);
-}
+}
\ No newline at end of file
index 6a4d39d..dd2fdbc 100644 (file)
@@ -1096,6 +1096,7 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) {
     } else if (arg == 39) {
       /* Default text color */
       fg_color = 7;
+      fg_bright = 0;
 
     } else if (arg >= 40 && arg <= 47) {
       /* Set background color */
index 3eb8e43..79b9e6b 100644 (file)
   #define IPV6_V6ONLY 27
 #endif
 
+#ifndef IPV6_HOPLIMIT
+  #define IPV6_HOPLIMIT 21
+#endif
+
 /*
  * TDI defines that are only in the DDK.
  * We only need receive flags so far.
index ebbd16e..a101305 100644 (file)
@@ -131,6 +131,9 @@ static int ipc_helper(int listen_after_write) {
 
   uv_pipe_open(&channel, 0);
 
+  ASSERT(uv_is_readable(&channel));
+  ASSERT(uv_is_writable(&channel));
+
   r = uv_tcp_init(uv_default_loop(), &tcp_server);
   ASSERT(r == 0);
 
index 109ae01..0069688 100644 (file)
@@ -432,6 +432,14 @@ static void open_nametoolong_cb(uv_fs_t* req) {
   uv_fs_req_cleanup(req);
 }
 
+static void open_loop_cb(uv_fs_t* req) {
+  ASSERT(req->fs_type == UV_FS_OPEN);
+  ASSERT(req->errorno == UV_ELOOP);
+  ASSERT(req->result == -1);
+  open_cb_count++;
+  uv_fs_req_cleanup(req);
+}
+
 
 TEST_IMPL(fs_file_noent) {
   uv_fs_t req;
@@ -483,6 +491,34 @@ TEST_IMPL(fs_file_nametoolong) {
   return 0;
 }
 
+TEST_IMPL(fs_file_loop) {
+  uv_fs_t req;
+  int r;
+
+  loop = uv_default_loop();
+
+  unlink("test_symlink");
+  uv_fs_symlink(loop, &req, "test_symlink", "test_symlink", 0, NULL);
+  uv_fs_req_cleanup(&req);
+
+  r = uv_fs_open(loop, &req, "test_symlink", O_RDONLY, 0, NULL);
+  ASSERT(r == -1);
+  ASSERT(req.result == -1);
+  ASSERT(uv_last_error(loop).code == UV_ELOOP);
+  uv_fs_req_cleanup(&req);
+
+  r = uv_fs_open(loop, &req, "test_symlink", O_RDONLY, 0, open_loop_cb);
+  ASSERT(r == 0);
+
+  ASSERT(open_cb_count == 0);
+  uv_run(loop);
+  ASSERT(open_cb_count == 1);
+
+  unlink("test_symlink");
+
+  return 0;
+}
+
 static void check_utime(const char* path, double atime, double mtime) {
   struct stat* s;
   uv_fs_t req;
diff --git a/deps/uv/test/test-ipc-threads.c b/deps/uv/test/test-ipc-threads.c
deleted file mode 100644 (file)
index 1821f6a..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/* 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 "runner.h"
-#include "task.h"
-
-#include <stdio.h>
-#include <string.h>
-
-typedef struct {
-  uv_loop_t* loop;
-  uv_thread_t thread;
-  uv_async_t* recv_channel;
-  uv_async_t* send_channel;
-  uv_tcp_t server;
-  uv_tcp_t conn;
-  int connection_accepted;
-  int close_cb_called;
-} worker_t;
-
-static uv_async_t send_channel;
-static uv_async_t recv_channel;
-static worker_t parent;
-static worker_t child;
-
-static volatile uv_stream_info_t dup_stream;
-
-typedef struct {
-  uv_connect_t conn_req;
-  uv_tcp_t conn;
-} tcp_conn;
-
-#define CONN_COUNT 100
-
-static void close_cb(uv_handle_t* handle) {
-  worker_t* worker = (worker_t*)handle->data;
-  ASSERT(worker);
-  worker->close_cb_called++;
-}
-
-
-static void on_connection(uv_stream_t* server, int status) {
-  int r;
-  worker_t* worker = container_of(server, worker_t, server);
-
-  if (!worker->connection_accepted) {
-    /*
-     * Accept the connection and close it.
-     */
-    ASSERT(status == 0);
-
-    r = uv_tcp_init(server->loop, &worker->conn);
-    ASSERT(r == 0);
-
-    worker->conn.data = worker;
-
-    r = uv_accept(server, (uv_stream_t*)&worker->conn);
-    ASSERT(r == 0);
-
-    worker->connection_accepted = 1;
-
-    uv_close((uv_handle_t*)worker->recv_channel, close_cb);
-    uv_close((uv_handle_t*)&worker->conn, close_cb);
-    uv_close((uv_handle_t*)server, close_cb);
-  }
-}
-
-
-static void close_client_conn_cb(uv_handle_t* handle) {
-  tcp_conn* p = (tcp_conn*)handle->data;
-  free(p);
-}
-
-
-static void connect_cb(uv_connect_t* req, int status) {
-  uv_close((uv_handle_t*)req->handle, close_client_conn_cb);
-}
-
-
-static void make_many_connections() {
-  tcp_conn* conn;
-  struct sockaddr_in addr;
-  int r, i;
-
-  for (i = 0; i < CONN_COUNT; i++) {
-    conn = malloc(sizeof(*conn));
-    ASSERT(conn);
-
-    r = uv_tcp_init(uv_default_loop(), &conn->conn);
-    ASSERT(r == 0);
-
-    addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
-
-    r = uv_tcp_connect(&conn->conn_req, (uv_tcp_t*)&conn->conn, addr, connect_cb);
-    ASSERT(r == 0);
-
-    conn->conn.data = conn;
-  }
-}
-
-
-void on_parent_msg(uv_async_t* handle, int status) {
-  int r;
-
-  ASSERT(dup_stream.type == UV_TCP);
-
-  /* Import the shared TCP server, and start listening on it. */
-  r = uv_tcp_init(parent.loop, &parent.server);
-  ASSERT(r == 0);
-
-  parent.server.data = &parent;
-
-  r = uv_import((uv_stream_t*)&parent.server,
-    (uv_stream_info_t*)&dup_stream);
-  ASSERT(r == 0);
-
-  r = uv_listen((uv_stream_t*)&parent.server, 12, on_connection);
-  ASSERT(r == 0);
-
-  /* Create a bunch of connections to get both servers to accept. */
-  make_many_connections();
-}
-
-
-void on_child_msg(uv_async_t* handle, int status) {
-  ASSERT(!"no");
-}
-
-
-static void child_thread_entry(void* arg) {
-  int r;
-  int listen_after_write = *(int*) arg;
-
-  r = uv_tcp_init(child.loop, &child.server);
-  ASSERT(r == 0);
-
-  child.server.data = &child;
-
-  r = uv_tcp_bind(&child.server, uv_ip4_addr("0.0.0.0", TEST_PORT));
-  ASSERT(r == 0);
-
-  if (!listen_after_write) {
-    r = uv_listen((uv_stream_t*)&child.server, 12, on_connection);
-    ASSERT(r == 0);
-  }
-
-  r = uv_export((uv_stream_t*)&child.server,
-    (uv_stream_info_t*)&dup_stream);
-  ASSERT(r == 0);
-
-  r = uv_async_send(child.send_channel);
-  ASSERT(r == 0);
-
-  if (listen_after_write) {
-    r = uv_listen((uv_stream_t*)&child.server, 12, on_connection);
-    ASSERT(r == 0);
-  }
-
-  r = uv_run(child.loop);
-  ASSERT(r == 0);
-
-  ASSERT(child.connection_accepted == 1);
-  ASSERT(child.close_cb_called == 3);
-}
-
-
-static void run_ipc_threads_test(int listen_after_write) {
-  int r;
-
-  parent.send_channel = &send_channel;
-  parent.recv_channel = &recv_channel;
-  child.send_channel = &recv_channel;
-  child.recv_channel = &send_channel;
-
-  parent.loop = uv_default_loop();
-  child.loop = uv_loop_new();
-  ASSERT(child.loop);
-
-  r = uv_async_init(parent.loop, parent.recv_channel, on_parent_msg);
-  ASSERT(r == 0);
-  parent.recv_channel->data = &parent;
-
-  r = uv_async_init(child.loop, child.recv_channel, on_child_msg);
-  ASSERT(r == 0);
-  child.recv_channel->data = &child;
-
-  r = uv_thread_create(&child.thread, child_thread_entry, &listen_after_write);
-  ASSERT(r == 0);
-
-  r = uv_run(parent.loop);
-  ASSERT(r == 0);
-
-  ASSERT(parent.connection_accepted == 1);
-  ASSERT(parent.close_cb_called == 3);
-
-  r = uv_thread_join(&child.thread);
-  ASSERT(r == 0);
-
-  /* Satisfy valgrind. Maybe we should delete the default loop from the
-   * test runner.
-   */
-  uv_loop_delete(child.loop);
-  uv_loop_delete(uv_default_loop());
-}
-
-
-TEST_IMPL(ipc_threads_listen_after_write) {
-  run_ipc_threads_test(1);
-  return 0;
-}
-
-
-TEST_IMPL(ipc_threads_listen_before_write) {
-  run_ipc_threads_test(0);
-  return 0;
-}
index 63c1000..99932da 100644 (file)
@@ -24,8 +24,6 @@ TEST_DECLARE   (tty)
 TEST_DECLARE   (stdio_over_pipes)
 TEST_DECLARE   (ipc_listen_before_write)
 TEST_DECLARE   (ipc_listen_after_write)
-TEST_DECLARE   (ipc_threads_listen_after_write)
-TEST_DECLARE   (ipc_threads_listen_before_write)
 TEST_DECLARE   (tcp_ping_pong)
 TEST_DECLARE   (tcp_ping_pong_v6)
 TEST_DECLARE   (pipe_ping_pong)
@@ -50,6 +48,7 @@ TEST_DECLARE   (tcp_bind6_error_inval)
 TEST_DECLARE   (tcp_bind6_localhost_ok)
 TEST_DECLARE   (udp_send_and_recv)
 TEST_DECLARE   (udp_multicast_join)
+TEST_DECLARE   (udp_multicast_ttl)
 TEST_DECLARE   (udp_dgram_too_big)
 TEST_DECLARE   (udp_dual_stack)
 TEST_DECLARE   (udp_ipv6_only)
@@ -110,6 +109,7 @@ TEST_DECLARE   (spawn_and_ping)
 TEST_DECLARE   (kill)
 TEST_DECLARE   (fs_file_noent)
 TEST_DECLARE   (fs_file_nametoolong)
+TEST_DECLARE   (fs_file_loop)
 TEST_DECLARE   (fs_file_async)
 TEST_DECLARE   (fs_file_sync)
 TEST_DECLARE   (fs_async_dir)
@@ -164,8 +164,6 @@ TASK_LIST_START
   TEST_ENTRY  (stdio_over_pipes)
   TEST_ENTRY  (ipc_listen_before_write)
   TEST_ENTRY  (ipc_listen_after_write)
-  TEST_ENTRY  (ipc_threads_listen_after_write)
-  TEST_ENTRY  (ipc_threads_listen_before_write)
 
   TEST_ENTRY  (tcp_ping_pong)
   TEST_HELPER (tcp_ping_pong, tcp4_echo_server)
@@ -206,6 +204,7 @@ TASK_LIST_START
   TEST_ENTRY  (udp_ipv6_only)
   TEST_ENTRY  (udp_options)
   TEST_ENTRY  (udp_multicast_join)
+  TEST_ENTRY  (udp_multicast_ttl)
 
   TEST_ENTRY  (pipe_bind_error_addrinuse)
   TEST_ENTRY  (pipe_bind_error_addrnotavail)
@@ -294,6 +293,7 @@ TASK_LIST_START
 
   TEST_ENTRY  (fs_file_noent)
   TEST_ENTRY  (fs_file_nametoolong)
+  TEST_ENTRY  (fs_file_loop)
   TEST_ENTRY  (fs_file_async)
   TEST_ENTRY  (fs_file_sync)
   TEST_ENTRY  (fs_async_dir)
index 5c3de3b..245a601 100644 (file)
@@ -138,6 +138,9 @@ static void pinger_on_connect(uv_connect_t *req, int status) {
 
   ASSERT(status == 0);
 
+  ASSERT(uv_is_readable(req->handle));
+  ASSERT(uv_is_writable(req->handle));
+
   pinger_write_ping(pinger);
 
   uv_read_start((uv_stream_t*)(req->handle), alloc_cb, pinger_read_cb);
diff --git a/deps/uv/test/test-udp-multicast-ttl.c b/deps/uv/test/test-udp-multicast-ttl.c
new file mode 100644 (file)
index 0000000..e54583c
--- /dev/null
@@ -0,0 +1,89 @@
+/* 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"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CHECK_HANDLE(handle) \
+  ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client)
+
+static uv_udp_t server;
+static uv_udp_t client;
+
+static int cl_recv_cb_called;
+
+static int sv_send_cb_called;
+
+static int close_cb_called;
+
+
+static void close_cb(uv_handle_t* handle) {
+  CHECK_HANDLE(handle);
+  close_cb_called++;
+}
+
+
+static void sv_send_cb(uv_udp_send_t* req, int status) {
+  ASSERT(req != NULL);
+  ASSERT(status == 0);
+  CHECK_HANDLE(req->handle);
+
+  sv_send_cb_called++;
+
+  uv_close((uv_handle_t*) req->handle, close_cb);
+}
+
+
+TEST_IMPL(udp_multicast_ttl) {
+  int r;
+  uv_udp_send_t req;
+  uv_buf_t buf;
+  struct sockaddr_in addr = uv_ip4_addr("239.255.0.1", TEST_PORT);
+
+  r = uv_udp_init(uv_default_loop(), &server);
+  ASSERT(r == 0);
+
+  r = uv_udp_bind(&server, uv_ip4_addr("0.0.0.0", 0), 0);
+  ASSERT(r == 0);
+
+  r = uv_udp_set_multicast_ttl(&server, 32);
+  ASSERT(r == 0);
+
+  /* server sends "PING" */
+  buf = uv_buf_init("PING", 4);
+  r = uv_udp_send(&req, &server, &buf, 1, addr, sv_send_cb);
+  ASSERT(r == 0);
+
+  ASSERT(close_cb_called == 0);
+  ASSERT(sv_send_cb_called == 0);
+
+  /* run the loop till all events are processed */
+  uv_run(uv_default_loop());
+
+  ASSERT(sv_send_cb_called == 1);
+  ASSERT(close_cb_called == 1);
+
+  return 0;
+}
index 4c8caa4..75f3634 100644 (file)
             'src/ares/config_win32'
           ],
           'defines': [
-            '_WIN32_WINNT=0x0502',
+            '_WIN32_WINNT=0x0600',
             'EIO_STACKSIZE=262144',
             '_GNU_SOURCE',
           ],
         'test/test-hrtime.c',
         'test/test-idle.c',
         'test/test-ipc.c',
-        'test/test-ipc-threads.c',
         'test/test-list.h',
         'test/test-loop-handles.c',
         'test/test-multiple-listen.c',
         'test/test-udp-send-and-recv.c',
         'test/test-udp-multicast-join.c',
         'test/test-counters-init.c',
+        'test/test-udp-multicast-ttl.c',
       ],
       'conditions': [
         [ 'OS=="win"', {