Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
+Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com>
Bert Belder <bertbelder@gmail.com> <info@2bs.nl>
Bert Belder <bertbelder@gmail.com> <user@ChrUbuntu.(none)>
Brandon Philips <brandon.philips@rackspace.com> <brandon@ifup.org>
Brian White <mscdex@mscdex.net>
Brian White <mscdex@mscdex.net> <mscdex@gmail.com>
+Fedor Indutny <fedor.indutny@gmail.com> <fedor@indutny.com>
Frank Denis <github@pureftpd.org>
Isaac Z. Schlueter <i@izs.me>
+Justin Venus <justin.venus@gmail.com> <justin.venus@orbitz.com>
+Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu>
+Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu>
+Maciej Małecki <maciej.malecki@notimplemented.org> <me@mmalecki.com>
Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
+Rasmus Pedersen <ruysch@outlook.com> <zerhacken@yahoo.com>
Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
Ryan Dahl <ryan@joyent.com> <ry@tinyclouds.org>
Ryan Emery <seebees@gmail.com>
+Sam Roberts <vieuxtech@gmail.com> <sam@strongloop.com>
San-Tai Hsu <vanilla@fatpipi.com>
Saúl Ibarra Corretgé <saghul@gmail.com>
Shigeki Ohtsu <ohtsu@iij.ad.jp> <ohtsu@ohtsu.org>
Trevor Norris <trev.norris@gmail.com>
Oguz Bastemur <obastemur@gmail.com>
Alexis Campailla <alexis@janeasystems.com>
+Justin Venus <justin.venus@gmail.com>
+Ben Kelly <ben@wanderview.com>
+Kristian Evensen <kristian.evensen@gmail.com>
+Sean Silva <chisophugis@gmail.com>
+Linus Mårtensson <linus.martensson@sonymobile.com>
+Navaneeth Kedaram Nambiathan <navaneethkn@gmail.com>
+Brent Cook <brent@boundary.com>
+Brian Kaisner <bkize1@gmail.com>
+Reini Urban <rurban@cpanel.net>
+Maks Naumov <maksqwe1@ukr.net>
+Sean Farrell <sean.farrell@rioki.org>
+Christoph Iserlohn <christoph.iserlohn@innoq.com>
+Steven Kabbes <stevenkabbes@gmail.com>
+Tenor Biel <tenorbiel@gmail.com>
+Andrej Manduch <AManduch@gmail.com>
+Joshua Neuheisel <joshua@neuheisel.us>
+Yorkie <yorkiefixer@gmail.com>
+Sam Roberts <vieuxtech@gmail.com>
+River Tarnell <river@loreley.flyingparchment.org.uk>
+Nathan Sweet <nathanjsweet@gmail.com>
+Dylan Cali <calid1984@gmail.com>
+Austin Foxley <austinf@cetoncorp.com>
+Geoffry Song <goffrie@gmail.com>
+Benjamin Saunders <ben.e.saunders@gmail.com>
+Rasmus Pedersen <ruysch@outlook.com>
+William Light <wrl@illest.net>
+Oleg Efimov <o.efimov@corp.badoo.com>
+Lars Gierth <larsg@systemli.org>
+StarWing <weasley.wx@gmail.com>
+thierry-FreeBSD <thierry@FreeBSD.org>
+Isaiah Norton <isaiah.norton@gmail.com>
+Raul Martins <raulms.martins@gmail.com>
+David Capello <davidcapello@gmail.com>
+Paul Tan <pyokagan@gmail.com>
+Javier Hernández <jhernandez@emergya.com>
+Tonis Tiigi <tonistiigi@gmail.com>
-2014.02.19, Version 0.10.25 (Stable)
+2014.05.02, Version 0.10.27 (Stable)
+
+Changes since version 0.10.26:
+
+* windows: fix console signal handler refcount (Saúl Ibarra Corretgé)
+
+* win: always leave crit section in get_proc_title (Fedor Indutny)
+
+
+2014.04.07, Version 0.10.26 (Stable), d864907611c25ec986c5e77d4d6d6dee88f26926
+
+Changes since version 0.10.25:
+
+* process: don't close stdio fds during spawn (Tonis Tiigi)
+
+* build, windows: do not fail on Windows SDK Prompt (Marc Schlaich)
+
+* build, windows: fix x64 configuration issue (Marc Schlaich)
+
+* win: fix buffer leak on error in pipe.c (Fedor Indutny)
+
+* kqueue: invalidate fd in uv_fs_event_t (Fedor Indutny)
+
+* linux: always deregister closing fds from epoll (Geoffry Song)
+
+* error: add ENXIO for O_NONBLOCK FIFO open() (Fedor Indutny)
+
+
+2014.02.19, Version 0.10.25 (Stable), d778dc588507588b12b9f9d2905078db542ed751
Changes since version 0.10.24:
XX( 57, ENODEV, "no such device") \
XX( 58, ESPIPE, "invalid seek") \
XX( 59, ECANCELED, "operation canceled") \
+ XX( 60, EFBIG, "file too large") \
+ XX( 61, ENOPROTOOPT, "protocol not available") \
+ XX( 62, ETXTBSY, "text file is busy") \
+ XX( 63, ERANGE, "result too large") \
+ XX( 64, ENXIO, "no such device or address") \
+ XX( 65, EMLINK, "too many links") \
#define UV_ERRNO_GEN(val, name, s) UV_##name = val,
case EROFS: return UV_EROFS;
case ENOMEM: return UV_ENOMEM;
case EDQUOT: return UV_ENOSPC;
+ case EFBIG: return UV_EFBIG;
+ case ENOPROTOOPT: return UV_ENOPROTOOPT;
+ case ETXTBSY: return UV_ETXTBSY;
+ case ERANGE: return UV_ERANGE;
+ case ENXIO: return UV_ENXIO;
+ case EMLINK: return UV_EMLINK;
default: return UV_UNKNOWN;
}
UNREACHABLE();
void uv__fs_event_close(uv_fs_event_t* handle) {
#if defined(__APPLE__)
if (uv__fsevents_close(handle))
- uv__io_stop(handle->loop, &handle->event_watcher, UV__POLLIN);
-#else
- uv__io_stop(handle->loop, &handle->event_watcher, UV__POLLIN);
#endif /* defined(__APPLE__) */
+ {
+ uv__io_close(handle->loop, &handle->event_watcher);
+ }
uv__handle_stop(handle);
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct uv__epoll_event* events;
+ struct uv__epoll_event dummy;
uintptr_t i;
uintptr_t nfds;
events = (struct uv__epoll_event*) 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].data == fd)
- events[i].data = -1;
+ if (events != NULL)
+ /* Invalidate events with same file descriptor */
+ for (i = 0; i < nfds; i++)
+ if ((int) events[i].data == fd)
+ events[i].data = -1;
+
+ /* Remove the file descriptor from the epoll.
+ * This avoids a problem where the same file description remains open
+ * in another process, causing repeated junk epoll events.
+ *
+ * We pass in a dummy epoll_event, to work around a bug in old kernels.
+ */
+ if (loop->backend_fd >= 0)
+ uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &dummy);
}
if (use_fd == -1) {
uv__write_int(error_fd, errno);
- perror("failed to open stdio");
_exit(127);
}
}
if (fd <= 2)
uv__nonblock(fd, 0);
- if (close_fd != -1)
+ if (close_fd >= stdio_count)
close(close_fd);
}
if (options.cwd && chdir(options.cwd)) {
uv__write_int(error_fd, errno);
- perror("chdir()");
_exit(127);
}
if ((options.flags & UV_PROCESS_SETGID) && setgid(options.gid)) {
uv__write_int(error_fd, errno);
- perror("setgid()");
_exit(127);
}
if ((options.flags & UV_PROCESS_SETUID) && setuid(options.uid)) {
uv__write_int(error_fd, errno);
- perror("setuid()");
_exit(127);
}
execvp(options.file, options.args);
uv__write_int(error_fd, errno);
- perror("execvp()");
_exit(127);
}
#define UV_VERSION_MAJOR 0
#define UV_VERSION_MINOR 10
-#define UV_VERSION_PATCH 25
+#define UV_VERSION_PATCH 27
#define UV_VERSION_IS_RELEASE 1
uv__set_artificial_error(loop, UV_EOF);
if (handle->read2_cb) {
- handle->read2_cb(handle, -1, uv_null_buf_, UV_UNKNOWN_HANDLE);
+ handle->read2_cb(handle, -1, buf, UV_UNKNOWN_HANDLE);
} else {
- handle->read_cb((uv_stream_t*) handle, -1, uv_null_buf_);
+ handle->read_cb((uv_stream_t*) handle, -1, buf);
}
}
break;
}
} else {
- uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_);
+ uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf);
break;
}
}
/* If the console control handler has already been hooked, just add a */
/* reference. */
- if (uv__signal_control_handler_refs > 0)
+ if (uv__signal_control_handler_refs > 0) {
+ uv__signal_control_handler_refs++;
return uv_ok_;
+ }
if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))
return uv__new_sys_error(GetLastError());
* we must query it with getConsoleTitleW
*/
if (!process_title && uv__get_process_title() == -1) {
+ LeaveCriticalSection(&process_title_lock);
return uv__new_sys_error(GetLastError());
}
TEST_DECLARE (spawn_stdout_to_file)
TEST_DECLARE (spawn_stdout_and_stderr_to_file)
TEST_DECLARE (spawn_auto_unref)
+TEST_DECLARE (spawn_closed_process_io)
TEST_DECLARE (fs_poll)
TEST_DECLARE (kill)
TEST_DECLARE (fs_file_noent)
TEST_DECLARE (we_get_signal)
TEST_DECLARE (we_get_signals)
TEST_DECLARE (signal_multiple_loops)
+TEST_DECLARE (closed_fd_events)
#endif
#ifdef __APPLE__
TEST_DECLARE (osx_select)
TEST_ENTRY (spawn_stdout_to_file)
TEST_ENTRY (spawn_stdout_and_stderr_to_file)
TEST_ENTRY (spawn_auto_unref)
+ TEST_ENTRY (spawn_closed_process_io)
TEST_ENTRY (fs_poll)
TEST_ENTRY (kill)
TEST_ENTRY (we_get_signal)
TEST_ENTRY (we_get_signals)
TEST_ENTRY (signal_multiple_loops)
+ TEST_ENTRY (closed_fd_events)
#endif
#ifdef __APPLE__
static size_t exepath_size = 1024;
static char* args[3];
static int no_term_signal;
+static int timer_counter;
#define OUTPUT_SIZE 1024
static char output[OUTPUT_SIZE];
}
+static void on_read_once(uv_stream_t* tcp, ssize_t nread, const uv_buf_t buf) {
+ uv_read_stop(tcp);
+ on_read(tcp, nread, buf);
+}
+
+
static void write_cb(uv_write_t* req, int status) {
ASSERT(status == 0);
uv_close((uv_handle_t*)req->handle, close_cb);
}
+static void timer_counter_cb(uv_timer_t* handle, int status) {
+ ++timer_counter;
+}
+
+
TEST_IMPL(spawn_fails) {
init_process_options("", exit_cb_failure_expected);
options.file = options.args[0] = "program-that-had-better-not-exist";
}
+TEST_IMPL(spawn_closed_process_io) {
+ uv_pipe_t in;
+ uv_write_t write_req;
+ uv_buf_t buf;
+ uv_stdio_container_t stdio[2];
+ static char buffer[] = "hello-from-spawn_stdin";
+
+ init_process_options("spawn_helper1", exit_cb);
+
+ uv_pipe_init(uv_default_loop(), &in, 0);
+ options.stdio = stdio;
+ options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
+ options.stdio[0].data.stream = (uv_stream_t*) ∈
+ options.stdio_count = 1;
+
+ close(0); /* Close process stdin. */
+
+ ASSERT(0 == uv_spawn(uv_default_loop(), &process, options));
+
+ buf.base = buffer;
+ buf.len = sizeof(buffer);
+ ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb));
+
+ ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
+
+ ASSERT(exit_cb_called == 1);
+ ASSERT(close_cb_called == 2); /* process, child stdin */
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
TEST_IMPL(kill) {
int r;
uv_err_t err;
MAKE_VALGRIND_HAPPY();
return 0;
}
+
+
+#ifndef _WIN32
+TEST_IMPL(closed_fd_events) {
+ uv_stdio_container_t stdio[3];
+ uv_pipe_t pipe_handle;
+ int fd[2];
+
+ /* create a pipe and share it with a child process */
+ ASSERT(0 == pipe(fd));
+ ASSERT(0 == fcntl(fd[0], F_SETFL, O_NONBLOCK));
+
+ /* spawn_helper4 blocks indefinitely. */
+ init_process_options("spawn_helper4", exit_cb);
+ options.stdio_count = 3;
+ options.stdio = stdio;
+ options.stdio[0].data.fd = fd[0];
+ options.stdio[0].flags = UV_INHERIT_FD;
+ options.stdio[1].flags = UV_IGNORE;
+ options.stdio[2].flags = UV_IGNORE;
+
+ ASSERT(0 == uv_spawn(uv_default_loop(), &process, options));
+ uv_unref((uv_handle_t*) &process);
+
+ /* read from the pipe with uv */
+ ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0));
+ ASSERT(0 == uv_pipe_open(&pipe_handle, fd[0]));
+ fd[0] = -1;
+
+ ASSERT(0 == uv_read_start((uv_stream_t*) &pipe_handle, on_alloc, on_read_once));
+
+ ASSERT(1 == write(fd[1], "", 1));
+
+ ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
+
+ /* should have received just one byte */
+ ASSERT(output_used == 1);
+
+ /* close the pipe and see if we still get events */
+ uv_close((uv_handle_t*) &pipe_handle, close_cb);
+
+ ASSERT(1 == write(fd[1], "", 1));
+
+ ASSERT(0 == uv_timer_init(uv_default_loop(), &timer));
+ ASSERT(0 == uv_timer_start(&timer, timer_counter_cb, 10, 0));
+
+ /* see if any spurious events interrupt the timer */
+ if (1 == uv_run(uv_default_loop(), UV_RUN_ONCE)) {
+ if (1 == uv_run(uv_default_loop(), UV_RUN_ONCE))
+ ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
+ }
+
+ ASSERT(timer_counter == 1);
+
+ /* cleanup */
+ ASSERT(0 == uv_process_kill(&process, /* SIGTERM */ 15));
+ ASSERT(0 == close(fd[1]));
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+#endif /* !_WIN32 */
if /i "%1"=="nobuild" set nobuild=1&goto arg-ok
if /i "%1"=="x86" set target_arch=ia32&set platform=WIN32&set vs_toolset=x86&goto arg-ok
if /i "%1"=="ia32" set target_arch=ia32&set platform=WIN32&set vs_toolset=x86&goto arg-ok
-if /i "%1"=="x64" set target_arch=x64&set platform=amd64&set vs_toolset=x64&goto arg-ok
+if /i "%1"=="x64" set target_arch=x64&set platform=x64&set vs_toolset=x64&goto arg-ok
if /i "%1"=="shared" set library=shared_library&goto arg-ok
if /i "%1"=="static" set library=static_library&goto arg-ok
:arg-ok
goto next-arg
:args-done
+if defined WindowsSDKDir goto select-target
+if defined VCINSTALLDIR goto select-target
+
+@rem Look for Visual Studio 2013
+if not defined VS120COMNTOOLS goto vc-set-2012
+if not exist "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2012
+call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" %vs_toolset%
+set GYP_MSVS_VERSION=2013
+goto select-target
+
+:vc-set-2012
@rem Look for Visual Studio 2012
if not defined VS110COMNTOOLS goto vc-set-2010
if not exist "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2010
if defined nobuild goto run
@rem Check if VS build env is available
-if not defined VCINSTALLDIR goto msbuild-not-found
-goto msbuild-found
-
-:msbuild-not-found
+if defined VCINSTALLDIR goto msbuild-found
+if defined WindowsSDKDir goto msbuild-found
echo Build skipped. To build, this file needs to run from VS cmd prompt.
goto run