*.l[oa]
*.opensdf
*.orig
+*.pyc
*.sdf
*.suo
core
Brian White <mscdex@mscdex.net> <mscdex@gmail.com>
Frank Denis <github@pureftpd.org>
Isaac Z. Schlueter <i@izs.me>
+Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
Ryan Dahl <ryan@joyent.com> <ry@tinyclouds.org>
Ryan Emery <seebees@gmail.com>
Andrei Sedoi <bsnote@gmail.com>
Chris Bank <cbank@adobe.com>
Geert Jansen <geertj@gmail.com>
+Alex Gaynor <alex.gaynor@gmail.com>
+huxingyi <huxingyi@msn.com>
-2013.11.13, Version 0.10.19 (Stable)
+2013.12.13, Version 0.10.20 (Stable)
+
+Changes since version 0.10.19:
+
+* linux: fix up SO_REUSEPORT back-port (Ben Noordhuis)
+
+* fs-event: fix invalid memory access (huxingyi)
+
+
+2013.11.13, Version 0.10.19 (Stable), 33959f7524090b8d2c6c41e2400ca77e31755059
Changes since version 0.10.18:
test/test-delayed-accept.o \
test/test-dlerror.o \
test/test-embed.o \
+ test/test-emfile.o \
test/test-error.o \
test/test-fail-always.o \
test/test-fs.o \
if sys.platform != 'win32':
if '-f' not in args:
args.extend('-f make'.split())
- if 'ninja' not in args:
+ if 'eclipse' not in args and 'ninja' not in args:
args.extend(['-Goutput_dir=' + output_dir])
args.extend(['--generator-output', output_dir])
(major, minor), is_clang = compiler_version()
}
-void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
- struct kevent* events;
- uintptr_t i;
- uintptr_t nfds;
-
- assert(loop->watchers != NULL);
-
- events = (struct kevent*) loop->watchers[loop->nwatchers];
- nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
- if (events == NULL)
- return;
-
- /* Invalidate events with same file descriptor */
- for (i = 0; i < nfds; i++)
- if ((int) events[i].ident == fd)
- events[i].ident = -1;
-}
-
-
static void uv__cf_loop_runner(void* arg) {
uv_loop_t* loop;
*
* 1. Read errors are reported only if nsent==0, otherwise we return nsent.
* The user needs to know that some data has already been sent, to stop
- * him from sending it twice.
+ * them from sending it twice.
*
* 2. Write errors are always reported. Write errors are bad because they
* mean data loss: we've read data but now we can't write it out.
}
+void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
+ struct kevent* events;
+ uintptr_t i;
+ uintptr_t nfds;
+
+ assert(loop->watchers != NULL);
+
+ events = (struct kevent*) loop->watchers[loop->nwatchers];
+ nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
+ if (events == NULL)
+ return;
+
+ /* Invalidate events with same file descriptor */
+ for (i = 0; i < nfds; i++)
+ if ((int) events[i].ident == fd)
+ events[i].ident = -1;
+}
+
+
static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) {
uv_fs_event_t* handle;
struct kevent ev;
/* Only free when there was no error. On error, we touch up write_queue_size
* right before making the callback. The reason we don't do that right away
* is that a write_queue_size > 0 is our only way to signal to the user that
- * he should stop writing - which he should if we got an error. Something to
- * revisit in future revisions of the libuv API.
+ * they should stop writing - which they should if we got an error. Something
+ * to revisit in future revisions of the libuv API.
*/
if (req->error == 0) {
if (req->bufs != req->bufsml)
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
int saved_errno;
int status;
- int yes;
+ int err;
saved_errno = errno;
status = -1;
goto out;
}
- yes = 1;
- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1) {
- uv__set_sys_error(handle->loop, errno);
- goto out;
- }
-
- /* On the BSDs, SO_REUSEADDR lets you reuse an address that's in the TIME_WAIT
- * state (i.e. was until recently tied to a socket) while SO_REUSEPORT lets
- * multiple processes bind to the same address. Yes, it's something of a
- * misnomer but then again, SO_REUSEADDR was already taken.
- *
- * None of the above applies to Linux: SO_REUSEADDR implies SO_REUSEPORT on
- * Linux and hence it does not have SO_REUSEPORT at all.
- */
-#ifdef SO_REUSEPORT
- yes = 1;
- if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof yes) == -1) {
- uv__set_sys_error(handle->loop, errno);
+ err = uv__set_reuse(sock);
+ if (err) {
+ uv__set_sys_error(handle->loop, -err);
goto out;
}
-#endif
handle->io_watcher.fd = sock;
status = 0;
#define UV_VERSION_MAJOR 0
#define UV_VERSION_MINOR 10
-#define UV_VERSION_PATCH 19
+#define UV_VERSION_PATCH 20
#define UV_VERSION_IS_RELEASE 1
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
- _snwprintf(filenamew, size, L"%s\\%s", handle->dirw,
+ _snwprintf(filenamew, size, L"%s\\%.*s", handle->dirw,
+ file_info->FileNameLength / sizeof(WCHAR),
file_info->FileName);
filenamew[size - 1] = L'\0';
--- /dev/null
+/* 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.
+ */
+
+#if !defined(_WIN32)
+
+#include "uv.h"
+#include "task.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/resource.h>
+#include <unistd.h>
+
+static void connection_cb(uv_stream_t* server_handle, int status);
+static void connect_cb(uv_connect_t* req, int status);
+
+static const int maxfd = 31;
+static unsigned connect_cb_called;
+static uv_tcp_t server_handle;
+static uv_tcp_t client_handle;
+
+
+TEST_IMPL(emfile) {
+ struct sockaddr_in addr;
+ struct rlimit limits;
+ uv_connect_t connect_req;
+ uv_loop_t* loop;
+ int first_fd;
+
+ loop = uv_default_loop();
+ addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
+ ASSERT(0 == uv_tcp_init(loop, &server_handle));
+ ASSERT(0 == uv_tcp_init(loop, &client_handle));
+ ASSERT(0 == uv_tcp_bind(&server_handle, addr));
+ ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 8, connection_cb));
+
+ /* Lower the file descriptor limit and use up all fds save one. */
+ limits.rlim_cur = limits.rlim_max = maxfd + 1;
+ if (setrlimit(RLIMIT_NOFILE, &limits)) {
+ perror("setrlimit(RLIMIT_NOFILE)");
+ ASSERT(0);
+ }
+
+ /* Remember the first one so we can clean up afterwards. */
+ do
+ first_fd = dup(0);
+ while (first_fd == -1 && errno == EINTR);
+ ASSERT(first_fd > 0);
+
+ while (dup(0) != -1 || errno == EINTR);
+ ASSERT(errno == EMFILE);
+ close(maxfd);
+
+ /* Now connect and use up the last available file descriptor. The EMFILE
+ * handling logic in src/unix/stream.c should ensure that connect_cb() runs
+ * whereas connection_cb() should *not* run.
+ */
+ ASSERT(0 == uv_tcp_connect(&connect_req, &client_handle, addr, connect_cb));
+ ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
+ ASSERT(1 == connect_cb_called);
+
+ /* Close the dups again. Ignore errors in the unlikely event that the
+ * file descriptors were not contiguous.
+ */
+ while (first_fd < maxfd) {
+ close(first_fd);
+ first_fd += 1;
+ }
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+static void connection_cb(uv_stream_t* server_handle, int status) {
+ ASSERT(0 && "connection_cb should not be called.");
+}
+
+
+static void connect_cb(uv_connect_t* req, int status) {
+ /* |status| should equal 0 because the connection should have been accepted,
+ * it's just that the server immediately closes it again.
+ */
+ ASSERT(0 == status);
+ connect_cb_called += 1;
+ uv_close((uv_handle_t*) &server_handle, NULL);
+ uv_close((uv_handle_t*) &client_handle, NULL);
+}
+
+#endif /* !defined(_WIN32) */
TEST_DECLARE (listen_no_simultaneous_accepts)
TEST_DECLARE (fs_stat_root)
#else
+TEST_DECLARE (emfile)
TEST_DECLARE (spawn_setuid_setgid)
TEST_DECLARE (we_get_signal)
TEST_DECLARE (we_get_signals)
TEST_ENTRY (listen_no_simultaneous_accepts)
TEST_ENTRY (fs_stat_root)
#else
+ TEST_ENTRY (emfile)
TEST_ENTRY (spawn_setuid_setgid)
TEST_ENTRY (we_get_signal)
TEST_ENTRY (we_get_signals)
'test/test-delayed-accept.c',
'test/test-error.c',
'test/test-embed.c',
+ 'test/test-emfile.c',
'test/test-fail-always.c',
'test/test-fs.c',
'test/test-fs-event.c',