Commit 328cd30c authored by Jérémy Lal's avatar Jérémy Lal

Imported Upstream version 0.10.7~dfsg1

parent 19d00453
......@@ -447,3 +447,5 @@ Kevin Locke <kevin@kevinlocke.name>
Daniel Moore <polaris@northhorizon.net>
Robert Kowalski <rok@kowalski.gd>
Benoit Vallée <github@benoitvallee.net>
Ryuichi Okumura <okuryu@okuryu.com>
Brandon Frohs <bfrohs@gmail.com>
2013.05.14, Version 0.10.6 (Stable)
2013.05.17, Version 0.10.7 (Stable)
* uv: upgrade to v0.10.7
* npm: Upgrade to 1.2.21
* crypto: Don't ignore verify encoding argument (isaacs)
* buffer, crypto: fix default encoding regression (Ben Noordhuis)
* timers: fix setInterval() assert (Ben Noordhuis)
2013.05.14, Version 0.10.6 (Stable), 5deb1672f2b5794f8be19498a425ea4dc0b0711f
* module: Deprecate require.extensions (isaacs)
......
......@@ -82,3 +82,4 @@ Brian Mazza <louseman@gmail.com>
Nils Maier <maierman@web.de>
Nicholas Vavilov <vvnicholas@gmail.com>
Miroslav Bajtoš <miro.bajtos@gmail.com>
Elliot Saba <staticfloat@gmail.com>
2013.04.24, Version 0.10.5 (Stable)
2013.05.15, Version 0.10.7 (Stable)
Changes since version 0.10.6:
* windows: kill child processes when the parent dies (Bert Belder)
2013.05.15, Version 0.10.6 (Stable), 11e6613e6260d95c8cf11bf89a2759c24649319a
Changes since version 0.10.5:
* stream: fix osx select hack (Fedor Indutny)
* stream: fix small nit in select hack, add test (Fedor Indutny)
* build: link with libkvm on openbsd (Ben Noordhuis)
* stream: use harder sync restrictions for osx-hack (Fedor Indutny)
* unix: fix EMFILE error handling (Ben Noordhuis)
* darwin: fix unnecessary include headers (Daisuke Murase)
* darwin: rename darwin-getproctitle.m (Ben Noordhuis)
* build: convert predefined $PLATFORM to lower case (Elliot Saba)
* build: set soname in shared library (Ben Noordhuis)
* build: make `make test` link against .a again (Ben Noordhuis)
* darwin: fix ios build, don't require ApplicationServices (Ben Noordhuis)
* build: only set soname on shared object builds (Timothy J. Fontaine)
2013.04.24, Version 0.10.5 (Stable), 6595a7732c52eb4f8e57c88655f72997a8567a67
Changes since version 0.10.4:
......@@ -48,7 +84,7 @@ Changes since version 0.10.3:
* build: -Wno-dollar-in-identifier-extension is clang only (Ben Noordhuis)
2013.02.04, Version 0.10.3 (Stable), 31ebe23973dd98fd8a24c042b606f37a794e99d0
2013.03.28, Version 0.10.3 (Stable), 31ebe23973dd98fd8a24c042b606f37a794e99d0
Changes since version 0.10.2:
......
......@@ -18,7 +18,11 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
ifdef PLATFORM
override PLATFORM := $(shell echo $(PLATFORM) | tr "[A-Z]" "[a-z]")
else
PLATFORM = $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
endif
CPPFLAGS += -I$(SRCDIR)/include -I$(SRCDIR)/include/uv-private
......@@ -88,6 +92,7 @@ TESTS= \
test/test-loop-stop.o \
test/test-multiple-listen.o \
test/test-mutexes.o \
test/test-osx-select.o \
test/test-pass-always.o \
test/test-ping-pong.o \
test/test-pipe-bind-error.o \
......@@ -139,10 +144,10 @@ TESTS= \
all: libuv.a
run-tests$(E): test/run-tests.o test/runner.o $(RUNNER_SRC) $(TESTS) libuv.$(SOEXT)
run-tests$(E): test/run-tests.o test/runner.o $(RUNNER_SRC) $(TESTS) libuv.a
$(CC) $(CPPFLAGS) $(RUNNER_CFLAGS) -o $@ $^ $(RUNNER_LIBS) $(RUNNER_LDFLAGS)
run-benchmarks$(E): test/run-benchmarks.o test/runner.o $(RUNNER_SRC) $(BENCHMARKS) libuv.$(SOEXT)
run-benchmarks$(E): test/run-benchmarks.o test/runner.o $(RUNNER_SRC) $(BENCHMARKS) libuv.a
$(CC) $(CPPFLAGS) $(RUNNER_CFLAGS) -o $@ $^ $(RUNNER_LIBS) $(RUNNER_LDFLAGS)
test/echo.o: test/echo.c test/echo.h
......
......@@ -18,8 +18,6 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
OBJC ?= $(CC)
E=
CSTDFLAG=--std=c89 -pedantic -Wall -Wextra -Wno-unused-parameter
CFLAGS += -g
......@@ -31,7 +29,7 @@ CPPFLAGS += -D_FILE_OFFSET_BITS=64
RUNNER_SRC=test/runner-unix.c
RUNNER_CFLAGS=$(CFLAGS) -I$(SRCDIR)/test
RUNNER_LDFLAGS=-L"$(CURDIR)" -luv -Xlinker -rpath -Xlinker "$(CURDIR)"
RUNNER_LDFLAGS=-L"$(CURDIR)" -luv
HAVE_DTRACE=
DTRACE_OBJS=
......@@ -66,7 +64,6 @@ HAVE_DTRACE=1
CPPFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500
LDFLAGS+=-lkstat -lnsl -lsendfile -lsocket
# Library dependencies are not transitive.
RUNNER_LDFLAGS += $(LDFLAGS)
OBJS += src/unix/sunos.o
OBJS += src/unix/dtrace.o
DTRACE_OBJS += src/unix/core.o
......@@ -89,8 +86,7 @@ endif
CPPFLAGS += -D_DARWIN_USE_64_BIT_INODE=1
LDFLAGS += -framework Foundation \
-framework CoreServices \
-framework ApplicationServices \
-dynamiclib -install_name "@rpath/libuv.dylib"
-framework ApplicationServices
SOEXT = dylib
OBJS += src/unix/darwin.o
OBJS += src/unix/kqueue.o
......@@ -153,12 +149,19 @@ CPPFLAGS += -Isrc/unix
CFLAGS += -DHAVE_DTRACE
endif
ifneq (darwin,$(PLATFORM))
# Must correspond with UV_VERSION_MAJOR and UV_VERSION_MINOR in src/version.c
SO_LDFLAGS = -Wl,-soname,libuv.so.0.10
endif
RUNNER_LDFLAGS += $(LDFLAGS)
libuv.a: $(OBJS)
$(AR) rcs $@ $^
libuv.$(SOEXT): override CFLAGS += -fPIC
libuv.$(SOEXT): $(OBJS:%.o=%.pic.o)
$(CC) -shared -o $@ $^ $(LDFLAGS)
$(CC) -shared -o $@ $^ $(LDFLAGS) $(SO_LDFLAGS)
include/uv-private/uv-unix.h: \
include/uv-private/uv-bsd.h \
......@@ -184,9 +187,6 @@ test/%.o: test/%.c include/uv.h test/.buildstamp
clean-platform:
$(RM) test/run-{tests,benchmarks}.dSYM $(OBJS) $(OBJS:%.o=%.pic.o) src/unix/uv-dtrace.h
%.pic.o %.o: %.m
$(OBJC) $(CPPFLAGS) $(CFLAGS) -c $^ -o $@
src/unix/uv-dtrace.h: src/unix/uv-dtrace.d
dtrace -h -xnolibs -s $< -o $@
......
......@@ -18,10 +18,18 @@
* IN THE SOFTWARE.
*/
#include <Cocoa/Cocoa.h>
#include <TargetConditionals.h>
#if !TARGET_OS_IPHONE
# include <CoreFoundation/CoreFoundation.h>
# include <ApplicationServices/ApplicationServices.h>
#endif
int uv__set_process_title(const char* title) {
#if TARGET_OS_IPHONE
return -1;
#else
typedef CFTypeRef (*LSGetCurrentApplicationASNType)(void);
typedef OSStatus (*LSSetApplicationInformationItemType)(int,
CFTypeRef,
......@@ -43,14 +51,14 @@ int uv__set_process_title(const char* title) {
if (launch_services_bundle == NULL)
return -1;
ls_get_current_application_asn =
ls_get_current_application_asn = (LSGetCurrentApplicationASNType)
CFBundleGetFunctionPointerForName(launch_services_bundle,
CFSTR("_LSGetCurrentApplicationASN"));
if (ls_get_current_application_asn == NULL)
return -1;
ls_set_application_information_item =
ls_set_application_information_item = (LSSetApplicationInformationItemType)
CFBundleGetFunctionPointerForName(launch_services_bundle,
CFSTR("_LSSetApplicationInformationItem"));
......@@ -75,4 +83,5 @@ int uv__set_process_title(const char* title) {
NULL);
return (err == noErr) ? 0 : -1;
#endif /* !TARGET_OS_IPHONE */
}
......@@ -46,8 +46,8 @@ typedef struct uv__stream_select_s uv__stream_select_t;
struct uv__stream_select_s {
uv_stream_t* stream;
uv_thread_t thread;
uv_sem_t sem;
uv_mutex_t mutex;
uv_sem_t close_sem;
uv_sem_t async_sem;
uv_async_t async;
int events;
int fake_fd;
......@@ -139,7 +139,7 @@ static void uv__stream_osx_select(void* arg) {
stream = arg;
s = stream->select;
fd = stream->io_watcher.fd;
fd = s->fd;
if (fd > s->int_fd)
max_fd = fd;
......@@ -148,7 +148,7 @@ static void uv__stream_osx_select(void* arg) {
while (1) {
/* Terminate on semaphore */
if (uv_sem_trywait(&s->sem) == 0)
if (uv_sem_trywait(&s->close_sem) == 0)
break;
/* Watch fd using select(2) */
......@@ -202,12 +202,16 @@ static void uv__stream_osx_select(void* arg) {
if (FD_ISSET(fd, &swrite))
events |= UV__POLLOUT;
uv_mutex_lock(&s->mutex);
s->events |= events;
uv_mutex_unlock(&s->mutex);
assert(events != 0 || FD_ISSET(s->int_fd, &sread));
if (events != 0) {
ACCESS_ONCE(int, s->events) = events;
if (events != 0)
uv_async_send(&s->async);
uv_sem_wait(&s->async_sem);
/* Should be processed at this stage */
assert((s->events == 0) || (stream->flags & UV_CLOSING));
}
}
}
......@@ -240,10 +244,9 @@ static void uv__stream_osx_select_cb(uv_async_t* handle, int status) {
stream = s->stream;
/* Get and reset stream's events */
uv_mutex_lock(&s->mutex);
events = s->events;
s->events = 0;
uv_mutex_unlock(&s->mutex);
ACCESS_ONCE(int, s->events) = 0;
uv_sem_post(&s->async_sem);
assert(events != 0);
assert(events == (events & (UV__POLLIN | UV__POLLOUT)));
......@@ -305,6 +308,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
if (s == NULL)
return uv__set_artificial_error(stream->loop, UV_ENOMEM);
s->events = 0;
s->fd = *fd;
if (uv_async_init(stream->loop, &s->async, uv__stream_osx_select_cb)) {
......@@ -315,10 +319,10 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
s->async.flags |= UV__HANDLE_INTERNAL;
uv__handle_unref(&s->async);
if (uv_sem_init(&s->sem, 0))
if (uv_sem_init(&s->close_sem, 0))
goto fatal1;
if (uv_mutex_init(&s->mutex))
if (uv_sem_init(&s->async_sem, 0))
goto fatal2;
/* Create fds for io watcher and to interrupt the select() loop. */
......@@ -343,9 +347,9 @@ fatal4:
s->fake_fd = -1;
s->int_fd = -1;
fatal3:
uv_mutex_destroy(&s->mutex);
uv_sem_destroy(&s->async_sem);
fatal2:
uv_sem_destroy(&s->sem);
uv_sem_destroy(&s->close_sem);
fatal1:
uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close);
return uv__set_sys_error(stream->loop, errno);
......@@ -437,7 +441,6 @@ void uv__stream_destroy(uv_stream_t* stream) {
*/
static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
int fd;
int r;
if (loop->emfile_fd == -1)
return -1;
......@@ -455,14 +458,8 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
if (errno == EINTR)
continue;
if (errno == EAGAIN || errno == EWOULDBLOCK)
r = 0;
else
r = -1;
loop->emfile_fd = uv__open_cloexec("/", O_RDONLY);
return r;
SAVE_ERRNO(loop->emfile_fd = uv__open_cloexec("/", O_RDONLY));
return errno;
}
}
......@@ -475,10 +472,9 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
static int use_emfile_trick = -1;
uv_stream_t* stream;
int err;
int fd;
int r;
stream = container_of(w, uv_stream_t, io_watcher);
assert(events == UV__POLLIN);
......@@ -493,50 +489,32 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
*/
while (uv__stream_fd(stream) != -1) {
assert(stream->accepted_fd == -1);
#if defined(UV_HAVE_KQUEUE)
if (w->rcount <= 0)
return;
#endif /* defined(UV_HAVE_KQUEUE) */
fd = uv__accept(uv__stream_fd(stream));
fd = uv__accept(uv__stream_fd(stream));
if (fd == -1) {
switch (errno) {
#if EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
case EAGAIN:
return; /* Not an error. */
case ECONNABORTED:
UV_DEC_BACKLOG(w)
continue; /* Ignore. */
case EMFILE:
case ENFILE:
if (use_emfile_trick == -1) {
const char* val = getenv("UV_ACCEPT_EMFILE_TRICK");
use_emfile_trick = (val == NULL || atoi(val) != 0);
}
if (use_emfile_trick) {
SAVE_ERRNO(r = uv__emfile_trick(loop, uv__stream_fd(stream)));
if (r == 0) {
UV_DEC_BACKLOG(w)
continue;
}
}
if (errno == EAGAIN || errno == EWOULDBLOCK)
return; /* Not an error. */
/* Fall through. */
if (errno == ECONNABORTED)
continue; /* Ignore. Nothing we can do about that. */
default:
uv__set_sys_error(loop, errno);
stream->connection_cb(stream, -1);
continue;
if (errno == EMFILE || errno == ENFILE) {
SAVE_ERRNO(err = uv__emfile_trick(loop, uv__stream_fd(stream)));
if (err == EAGAIN || err == EWOULDBLOCK)
break;
}
uv__set_sys_error(loop, errno);
stream->connection_cb(stream, -1);
continue;
}
UV_DEC_BACKLOG(w)
stream->accepted_fd = fd;
stream->connection_cb(stream, 0);
......@@ -1357,11 +1335,12 @@ void uv__stream_close(uv_stream_t* handle) {
s = handle->select;
uv_sem_post(&s->sem);
uv_sem_post(&s->close_sem);
uv_sem_post(&s->async_sem);
uv__stream_osx_interrupt_select(handle);
uv_thread_join(&s->thread);
uv_sem_destroy(&s->sem);
uv_mutex_destroy(&s->mutex);
uv_sem_destroy(&s->close_sem);
uv_sem_destroy(&s->async_sem);
close(s->fake_fd);
close(s->int_fd);
uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close);
......
......@@ -24,7 +24,9 @@
/*
* Versions with an even minor version (e.g. 0.6.1 or 1.0.4) are API and ABI
* stable. When the minor version is odd, the API can change between patch
* releases.
* releases. Make sure you update the -soname directives in config-unix.mk
* and uv.gyp whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but
* not UV_VERSION_PATCH.)
*/
#undef UV_VERSION_MAJOR /* TODO(bnoordhuis) Remove in v0.11. */
......@@ -32,7 +34,7 @@
#define UV_VERSION_MAJOR 0
#define UV_VERSION_MINOR 10
#define UV_VERSION_PATCH 5
#define UV_VERSION_PATCH 7
#define UV_VERSION_IS_RELEASE 1
......
......@@ -45,6 +45,36 @@ typedef struct env_var {
#define E_V(str) { str "=", L##str, sizeof(str), 0, 0 }
static HANDLE uv_global_job_handle_;
static uv_once_t uv_global_job_handle_init_guard_ = UV_ONCE_INIT;
static void uv__init_global_job_handle() {
SECURITY_ATTRIBUTES attr;
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
memset(&attr, 0, sizeof attr);
attr.bInheritHandle = FALSE;
memset(&info, 0, sizeof info);
info.BasicLimitInformation.LimitFlags =
JOB_OBJECT_LIMIT_BREAKAWAY_OK |
JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK |
JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION |
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
uv_global_job_handle_ = CreateJobObjectW(&attr, NULL);
if (uv_global_job_handle_ == NULL)
uv_fatal_error(GetLastError(), "CreateJobObjectW");
if (!SetInformationJobObject(uv_global_job_handle_,
JobObjectExtendedLimitInformation,
&info,
sizeof info))
uv_fatal_error(GetLastError(), "SetInformationJobObject");
}
static uv_err_t uv_utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) {
int ws_len, r;
WCHAR* ws;
......@@ -908,6 +938,15 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
process->process_handle = info.hProcess;
process->pid = info.dwProcessId;
/* If the process isn't spawned as detached, assign to the global job */
/* object so windows will kill it when the parent process dies. */
if (!(options.flags & UV_PROCESS_DETACHED)) {
uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);
if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess))
uv_fatal_error(GetLastError(), "AssignProcessToJobObject");
}
/* Set IPC pid to all IPC pipes. */
for (i = 0; i < options.stdio_count; i++) {
const uv_stdio_container_t* fdopt = &options.stdio[i];
......
......@@ -286,6 +286,34 @@ int process_copy_output(process_info_t *p, int fd) {
}
/* Copy the last line of the stdio output buffer to `buffer` */
int process_read_last_line(process_info_t *p,
char* buffer,
size_t buffer_len) {
char* ptr;
int r = fseek(p->stdout_file, 0, SEEK_SET);
if (r < 0) {
perror("fseek");
return -1;
}
buffer[0] = '\0';
while (fgets(buffer, buffer_len, p->stdout_file) != NULL) {
for (ptr = buffer; *ptr && *ptr != '\r' && *ptr != '\n'; ptr++);
*ptr = '\0';
}
if (ferror(p->stdout_file)) {
perror("read");
buffer[0] = '\0';
return -1;
}
return 0;
}
/* Return the name that was specified when `p` was started by process_start */
char* process_get_name(process_info_t *p) {
return p->name;
......
......@@ -248,6 +248,46 @@ int process_copy_output(process_info_t *p, int fd) {
}
int process_read_last_line(process_info_t *p,
char * buffer,
size_t buffer_len) {
DWORD size;
DWORD read;
DWORD start;
OVERLAPPED overlapped;
ASSERT(buffer_len > 0);
size = GetFileSize(p->stdio_out, NULL);
if (size == INVALID_FILE_SIZE)
return -1;
if (size == 0) {
buffer[0] = '\0';
return 1;
}
memset(&overlapped, 0, sizeof overlapped);
if (size >= buffer_len)
overlapped.Offset = size - buffer_len - 1;
if (!ReadFile(p->stdio_out, buffer, buffer_len - 1, &read, &overlapped))
return -1;
for (start = read - 1; start >= 0; start--) {
if (buffer[start] == '\n' || buffer[start] == '\r')
break;
}
if (start > 0)
memmove(buffer, buffer + start, read - start);
buffer[read - start] = '\0';
return 0;
}
char* process_get_name(process_info_t *p) {
return p->name;
}
......
......@@ -31,12 +31,25 @@ char executable_path[PATHMAX] = { '\0' };
int tap_output = 0;
static void log_progress(int total, int passed, int failed, const char* name) {
static void log_progress(int total,
int passed,
int failed,
int todos,
int skipped,
const char* name) {
int progress;
if (total == 0)
total = 1;
LOGF("[%% %3d|+ %3d|- %3d]: %s", (int) ((passed + failed) / ((double) total) * 100.0),
passed, failed, name);
progress = 100 * (passed + failed + skipped + todos) / total;
LOGF("[%% %3d|+ %3d|- %3d|T %3d|S %3d]: %s",
progress,
passed,
failed,
todos,
skipped,
name);
}
......@@ -78,7 +91,13 @@ const char* fmt(double d) {
int run_tests(int timeout, int benchmark_output) {
int total, passed, failed, current;
int total;
int passed;
int failed;
int todos;
int skipped;
int current;
int test_result;
task_entry_t* task;
/* Count the number of tests. */
......@@ -96,6 +115,8 @@ int run_tests(int timeout, int benchmark_output) {
/* Run all tests. */
passed = 0;
failed = 0;
todos = 0;
skipped = 0;
current = 1;
for (task = TASKS; task->main; task++) {
if (task->is_helper) {
......@@ -106,13 +127,15 @@ int run_tests(int timeout, int benchmark_output) {
rewind_cursor();
if (!benchmark_output && !tap_output) {
log_progress(total, passed, failed, task->task_name);
log_progress(total, passed, failed, todos, skipped, task->task_name);
}
if (run_test(task->task_name, timeout, benchmark_output, current) == 0) {
passed++;
} else {
failed++;
test_result = run_test(task->task_name, timeout, benchmark_output, current);
switch (test_result) {
case TEST_OK: passed++; break;
case TEST_TODO: todos++; break;
case TEST_SKIP: skipped++; break;
default: failed++;
}
current++;
}
......@@ -121,13 +144,50 @@ int run_tests(int timeout, int benchmark_output) {
rewind_cursor();
if (!benchmark_output && !tap_output) {
log_progress(total, passed, failed, "Done.\n");
log_progress(total, passed, failed, todos, skipped, "Done.\n");
}
return failed;
}
void log_tap_result(int test_count,
const char* test,
int status,
process_info_t* process) {
const char* result;
const char* directive;
char reason[1024];
switch (status) {
case TEST_OK:
result = "ok";
directive = "";
break;
case TEST_TODO:
result = "not ok";
directive = " # TODO ";
break;
case TEST_SKIP:
result = "ok";
directive = " # SKIP ";
break;
default:
result = "not ok";
directive = "";
}
if ((status == TEST_SKIP || status == TEST_TODO) &&
process_output_size(process) > 0) {
process_read_last_line(process, reason, sizeof reason);
} else {
reason[0] = '\0';
}
LOGF("%s %d - %s%s%s\n", result, test_count, test, directive, reason);
}
int run_test(const char* test,
int timeout,
int benchmark_output,
......@@ -231,7 +291,7 @@ int run_test(const char* test,
}
status = process_reap(main_proc);
if (status != 0) {
if (status != TEST_OK) {
snprintf(errmsg,
sizeof errmsg,
"exit code %d",
......@@ -255,17 +315,17 @@ out:
FATAL("process_wait failed");
}
if (tap_output) {
if (status == 0)