From 4bc024ddecf4e0daaa5d28155d3ad5977b98a68e Mon Sep 17 00:00:00 2001 From: isaacs Date: Wed, 26 Jun 2013 10:48:10 -0700 Subject: [PATCH] uv: Upgrade to v0.11.5 --- deps/uv/AUTHORS | 2 + deps/uv/ChangeLog | 78 +++++++++++++- deps/uv/LICENSE | 3 + deps/uv/README.md | 14 +++ deps/uv/android-configure | 20 ++++ deps/uv/checksparse.sh | 4 +- deps/uv/common.gypi | 5 +- deps/uv/config-unix.mk | 36 +++++-- deps/uv/gyp_uv | 1 + deps/uv/include/uv-private/pthread-fixes.h | 59 ++++++++++ deps/uv/include/uv-private/uv-unix.h | 3 + deps/uv/include/uv.h | 29 ++++- deps/uv/src/queue.h | 6 +- deps/uv/src/unix/error.c | 22 ---- deps/uv/src/unix/internal.h | 25 ++--- deps/uv/src/unix/linux-core.c | 24 +++-- deps/uv/src/unix/linux-syscalls.h | 1 + deps/uv/src/unix/pthread-fixes.c | 80 ++++++++++++++ deps/uv/src/unix/stream.c | 120 ++++++++++++++------- deps/uv/src/unix/thread.c | 12 ++- deps/uv/src/uv-common.c | 48 ++++----- deps/uv/src/version.c | 2 +- deps/uv/src/win/internal.h | 1 + deps/uv/src/win/pipe.c | 89 +++++++++++++-- deps/uv/src/win/stream.c | 10 ++ deps/uv/src/win/tcp.c | 6 +- deps/uv/src/win/util.c | 2 +- deps/uv/test/task.h | 10 ++ deps/uv/test/test-fs-event.c | 2 +- deps/uv/test/test-fs.c | 40 +++---- deps/uv/test/test-spawn.c | 2 +- deps/uv/uv.gyp | 20 +++- 32 files changed, 613 insertions(+), 163 deletions(-) create mode 100755 deps/uv/android-configure create mode 100644 deps/uv/include/uv-private/pthread-fixes.h create mode 100644 deps/uv/src/unix/pthread-fixes.c diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 4c36faeb9e..2d0f01db06 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -88,3 +88,5 @@ Miroslav Bajtoš Elliot Saba Sean Silva Wynn Wilkes +Linus Mårtensson +Andrei Sedoi diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 113d170693..53f2ed4664 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,4 +1,80 @@ -2013.05.30, Version 0.11.4 (Unstable) +2013.06.27, Version 0.11.5 (Unstable) + +Changes since version 0.11.4: + +* build: remove CSTDFLAG, use only CFLAGS (Ben Noordhuis) + +* unix: support for android builds (Linus Mårtensson) + +* unix: avoid extra read, short-circuit on POLLHUP (Ben Noordhuis) + +* uv: support android libuv standalone build (Linus Mårtensson) + +* src: make queue.h c++ compatible (Ben Noordhuis) + +* unix: s/ngx-queue.h/queue.h/ in checksparse.sh (Ben Noordhuis) + +* unix: unconditionally stop handle on close (Ben Noordhuis) + +* freebsd: don't enable dtrace if it's not available (Brian White) + +* build: make HAVE_DTRACE=0 should disable dtrace (Timothy J. Fontaine) + +* unix: remove overzealous assert (Ben Noordhuis) + +* unix: remove unused function uv_fatal_error() (Ben Noordhuis) + +* unix, windows: clean up uv_thread_create() (Ben Noordhuis) + +* queue: fix pointer truncation on LLP64 platforms (Bert Belder) + +* build: set OS=="android" for android builds (Linus Mårtensson) + +* windows: don't use uppercase in include filename (Ben Noordhuis) + +* stream: add an API to make streams do blocking writes (Henry Rawas) + +* windows: use WSAGetLastError(), not errno (Ben Noordhuis) + + +2013.06.13, Version 0.10.11 (Stable), c3b75406a66a10222a589cb173e8f469e9665c7e + +Changes since version 0.10.10: + +* unix: unconditionally stop handle on close (Ben Noordhuis) + +* freebsd: don't enable dtrace if it's not available (Brian White) + +* build: make HAVE_DTRACE=0 should disable dtrace (Timothy J. Fontaine) + +* unix: remove overzealous assert (Ben Noordhuis) + +* unix: clear UV_STREAM_SHUTTING after shutdown() (Ben Noordhuis) + +* unix: fix busy loop, write if POLLERR or POLLHUP (Ben Noordhuis) + + +2013.06.05, Version 0.10.10 (Stable), 0d95a88bd35fce93863c57a460be613aea34d2c5 + +Changes since version 0.10.9: + +* include: document uv_update_time() and uv_now() (Ben Noordhuis) + +* linux: fix cpu model parsing on newer arm kernels (Ben Noordhuis) + +* linux: fix a memory leak in uv_cpu_info() error path (Ben Noordhuis) + +* linux: don't ignore out-of-memory errors in uv_cpu_info() (Ben Noordhuis) + +* unix, windows: move uv_now() to uv-common.c (Ben Noordhuis) + +* test: fix a compilation problem in test-osx-select.c that was caused by the + use of c-style comments (Bert Belder) + +* darwin: use uv_fs_sendfile() use the sendfile api correctly (Wynn Wilkes) + + +2013.05.30, Version 0.11.4 (Unstable), e43e5b3d954a0989db5588aa110e1fe4fe6e0219 Changes since version 0.11.3: diff --git a/deps/uv/LICENSE b/deps/uv/LICENSE index 4718e345f3..8db13acf2c 100644 --- a/deps/uv/LICENSE +++ b/deps/uv/LICENSE @@ -37,3 +37,6 @@ The externally maintained libraries used by libuv are: - stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three clause BSD license. + + - pthread-fixes.h, pthread-fixes.c, copyright Google Inc. and Sony Mobile + Communications AB. Three clause BSD license. diff --git a/deps/uv/README.md b/deps/uv/README.md index e0d38c4463..f4f3ce2c86 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -70,6 +70,10 @@ Out-of-tree builds are supported: make builddir_name=/path/to/builddir +To build a shared object: + + make libuv.so # libuv.dylib on OS X + To build with Visual Studio run the vcbuild.bat file which will checkout the GYP code into build/gyp and generate the uv.sln and related files. @@ -106,6 +110,16 @@ Note for Linux users: compile your project with `-D_GNU_SOURCE` when you include `uv.h`. GYP builds take care of that automatically. If you use autotools, add a `AC_GNU_SOURCE` declaration to your `configure.ac`. +To build for android, locate your android NDK path, then run: + + source ./android-configure NDK_PATH + make + +To build for android with gyp, add "gyp" to the configuration: + + source ./android-configure NDK_PATH gyp + make -C out + ## Supported Platforms Microsoft Windows operating systems since Windows XP SP2. It can be built diff --git a/deps/uv/android-configure b/deps/uv/android-configure new file mode 100755 index 0000000000..d5c937e52a --- /dev/null +++ b/deps/uv/android-configure @@ -0,0 +1,20 @@ +#!/bin/bash + +export TOOLCHAIN=$PWD/android-toolchain +mkdir -p $TOOLCHAIN +$1/build/tools/make-standalone-toolchain.sh \ + --toolchain=arm-linux-androideabi-4.7 \ + --arch=arm \ + --install-dir=$TOOLCHAIN \ + --platform=android-9 +export PATH=$TOOLCHAIN/bin:$PATH +export AR=arm-linux-androideabi-ar +export CC=arm-linux-androideabi-gcc +export CXX=arm-linux-androideabi-g++ +export LINK=arm-linux-androideabi-g++ +export PLATFORM=android + +if [ $2 -a $2 == 'gyp' ] + then + ./gyp_uv -Dtarget_arch=arm -DOS=android +fi diff --git a/deps/uv/checksparse.sh b/deps/uv/checksparse.sh index f06b27d28f..65ff72b54b 100755 --- a/deps/uv/checksparse.sh +++ b/deps/uv/checksparse.sh @@ -27,12 +27,12 @@ SPARSE_FLAGS=${SPARSE_FLAGS:-" "} SOURCES=" -include/uv-private/ngx-queue.h include/uv-private/tree.h include/uv-private/uv-unix.h include/uv.h src/fs-poll.c src/inet.c +src/queue.h src/unix/async.c src/unix/core.c src/unix/dl.c @@ -222,7 +222,7 @@ SunOS) ;; esac -for ARCH in __i386__ __x86_64__ __arm__; do +for ARCH in __i386__ __x86_64__ __arm__ __mips__; do $SPARSE $SPARSE_FLAGS -D$ARCH=1 $SOURCES done diff --git a/deps/uv/common.gypi b/deps/uv/common.gypi index c3462821fb..7f2e8c3e4b 100644 --- a/deps/uv/common.gypi +++ b/deps/uv/common.gypi @@ -129,7 +129,7 @@ }] ] }], - [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', { + ['OS in "freebsd linux openbsd solaris android"', { 'cflags': [ '-Wall' ], 'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ], 'target_conditions': [ @@ -148,7 +148,8 @@ [ 'OS=="solaris"', { 'cflags': [ '-pthreads' ], 'ldflags': [ '-pthreads' ], - }, { + }], + [ 'OS not in "solaris android"', { 'cflags': [ '-pthread' ], 'ldflags': [ '-pthread' ], }], diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk index 67aaa140ab..7b99ac1b94 100644 --- a/deps/uv/config-unix.mk +++ b/deps/uv/config-unix.mk @@ -19,8 +19,7 @@ # IN THE SOFTWARE. E= -CSTDFLAG=--std=c89 -pedantic -Wall -Wextra -Wno-unused-parameter -CFLAGS += -g +CFLAGS += -g -Wall -Wextra -Wno-unused-parameter CPPFLAGS += -I$(SRCDIR)/src LDFLAGS=-lm @@ -31,7 +30,6 @@ RUNNER_SRC=test/runner-unix.c RUNNER_CFLAGS=$(CFLAGS) -I$(SRCDIR)/test RUNNER_LDFLAGS=-L"$(CURDIR)" -luv -HAVE_DTRACE= DTRACE_OBJS= DTRACE_HEADER= @@ -60,14 +58,16 @@ OBJS += src/inet.o OBJS += src/version.o ifeq (sunos,$(PLATFORM)) -HAVE_DTRACE=1 +HAVE_DTRACE ?= 1 CPPFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 LDFLAGS+=-lkstat -lnsl -lsendfile -lsocket # Library dependencies are not transitive. OBJS += src/unix/sunos.o +ifeq (1, $(HAVE_DTRACE)) OBJS += src/unix/dtrace.o DTRACE_OBJS += src/unix/core.o endif +endif ifeq (aix,$(PLATFORM)) CPPFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 @@ -76,7 +76,7 @@ OBJS += src/unix/aix.o endif ifeq (darwin,$(PLATFORM)) -HAVE_DTRACE=1 +HAVE_DTRACE ?= 1 # dtrace(1) probes contain dollar signs on OS X. Mute the warnings they # generate but only when CC=clang, -Wno-dollar-in-identifier-extension # is a clang extension. @@ -96,17 +96,31 @@ OBJS += src/unix/darwin-proctitle.o endif ifeq (linux,$(PLATFORM)) -CSTDFLAG += -D_GNU_SOURCE +CFLAGS += -D_GNU_SOURCE +LDFLAGS+=-ldl -lrt +RUNNER_CFLAGS += -D_GNU_SOURCE +OBJS += src/unix/linux-core.o \ + src/unix/linux-inotify.o \ + src/unix/linux-syscalls.o \ + src/unix/proctitle.o +endif + +ifeq (android,$(PLATFORM)) +CFLAGS += -D_GNU_SOURCE LDFLAGS+=-ldl -lrt RUNNER_CFLAGS += -D_GNU_SOURCE OBJS += src/unix/linux-core.o \ src/unix/linux-inotify.o \ src/unix/linux-syscalls.o \ src/unix/proctitle.o +else +CFLAGS += -std=c89 endif ifeq (freebsd,$(PLATFORM)) -HAVE_DTRACE=1 +ifeq ($(shell dtrace -l 1>&2 2>/dev/null; echo $$?),0) +HAVE_DTRACE ?= 1 +endif LDFLAGS+=-lkvm OBJS += src/unix/freebsd.o OBJS += src/unix/kqueue.o @@ -133,8 +147,10 @@ endif ifeq (sunos,$(PLATFORM)) RUNNER_LDFLAGS += -pthreads else +ifneq (android, $(PLATFORM)) RUNNER_LDFLAGS += -pthread endif +endif ifeq ($(HAVE_DTRACE), 1) DTRACE_HEADER = src/unix/uv-dtrace.h @@ -170,13 +186,13 @@ src/.buildstamp src/unix/.buildstamp test/.buildstamp: touch $@ src/unix/%.o src/unix/%.pic.o: src/unix/%.c include/uv.h include/uv-private/uv-unix.h src/unix/internal.h src/unix/.buildstamp $(DTRACE_HEADER) - $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ src/%.o src/%.pic.o: src/%.c include/uv.h include/uv-private/uv-unix.h src/.buildstamp - $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ test/%.o: test/%.c include/uv.h test/.buildstamp - $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ clean-platform: $(RM) test/run-{tests,benchmarks}.dSYM $(OBJS) $(OBJS:%.o=%.pic.o) src/unix/uv-dtrace.h diff --git a/deps/uv/gyp_uv b/deps/uv/gyp_uv index ab594515a9..651bd095f1 100755 --- a/deps/uv/gyp_uv +++ b/deps/uv/gyp_uv @@ -24,6 +24,7 @@ def host_arch(): if machine == 'i386': return 'ia32' if machine == 'x86_64': return 'x64' if machine.startswith('arm'): return 'arm' + if machine.startswith('mips'): return 'mips' return machine # Return as-is and hope for the best. diff --git a/deps/uv/include/uv-private/pthread-fixes.h b/deps/uv/include/uv-private/pthread-fixes.h new file mode 100644 index 0000000000..230ce3178d --- /dev/null +++ b/deps/uv/include/uv-private/pthread-fixes.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2013, Sony Mobile Communications AB + * Copyright (c) 2012, Google Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H +#define GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H + +#include + + +/*Android doesn't provide pthread_barrier_t for now.*/ +#ifndef PTHREAD_BARRIER_SERIAL_THREAD + +/* Anything except 0 will do here.*/ +#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345 + +typedef struct { + pthread_mutex_t mutex; + pthread_cond_t cond; + unsigned count; +} pthread_barrier_t; + +int pthread_barrier_init(pthread_barrier_t* barrier, + const void* barrier_attr, + unsigned count); + +int pthread_barrier_wait(pthread_barrier_t* barrier); +int pthread_barrier_destroy(pthread_barrier_t *barrier); +#endif /* defined(PTHREAD_BARRIER_SERIAL_THREAD) */ + +int pthread_yield(void); +#endif /* GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H */ diff --git a/deps/uv/include/uv-private/uv-unix.h b/deps/uv/include/uv-private/uv-unix.h index 385c32a313..4c05a714ac 100644 --- a/deps/uv/include/uv-private/uv-unix.h +++ b/deps/uv/include/uv-private/uv-unix.h @@ -37,6 +37,9 @@ #include #include +#ifdef __ANDROID__ +#include "pthread-fixes.h" +#endif #include #if defined(__linux__) diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index f51aea60f2..bb443e0453 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -349,6 +349,8 @@ typedef uv_buf_t (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size); * Trying to read from the stream again is undefined. * * The callee is responsible for freeing the buffer, libuv does not reuse it. + * The buffer may be a null buffer (where buf.base=NULL and buf.len=0) on EOF + * or error. */ typedef void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, uv_buf_t buf); @@ -673,6 +675,31 @@ UV_EXTERN int uv_is_readable(const uv_stream_t* handle); UV_EXTERN int uv_is_writable(const uv_stream_t* handle); +/* + * Enable or disable blocking mode for a stream. + * + * When blocking mode is enabled all writes complete synchronously. The + * interface remains unchanged otherwise, e.g. completion or failure of the + * operation will still be reported through a callback which is made + * asychronously. + * + * Relying too much on this API is not recommended. It is likely to change + * significantly in the future. + * + * On windows this currently works only for uv_pipe_t instances. On unix it + * works for tcp, pipe and tty instances. Be aware that changing the blocking + * mode on unix sets or clears the O_NONBLOCK bit. If you are sharing a handle + * with another process, the other process is affected by the change too, + * which can lead to unexpected results. + * + * Also libuv currently makes no ordering guarantee when the blocking mode + * is changed after write requests have already been submitted. Therefore it is + * recommended to set the blocking mode immediately after opening or creating + * the stream. + */ +UV_EXTERN int uv_stream_set_blocking(uv_stream_t* handle, int blocking); + + /* * Used to determine whether a stream is closing or closed. * @@ -1869,8 +1896,6 @@ UV_EXTERN extern uint64_t uv_hrtime(void); * Note that this function works on a best-effort basis: there is no guarantee * that libuv can discover all file descriptors that were inherited. In general * it does a better job on Windows than it does on unix. - * - * TODO(bb): insert snarky remark to annoy bnoordhuis and the folks at joyent. */ UV_EXTERN void uv_disable_stdio_inheritance(void); diff --git a/deps/uv/src/queue.h b/deps/uv/src/queue.h index a88ce9a47e..2f5ab61001 100644 --- a/deps/uv/src/queue.h +++ b/deps/uv/src/queue.h @@ -16,6 +16,8 @@ #ifndef QUEUE_H_ #define QUEUE_H_ +#include + typedef void *QUEUE[2]; /* Private macros. */ @@ -26,10 +28,10 @@ typedef void *QUEUE[2]; /* Public macros. */ #define QUEUE_DATA(ptr, type, field) \ - ((type *) ((char *) (ptr) - ((long) &((type *) 0)->field))) + ((type *) ((char *) (ptr) - ((uintptr_t) &((type *) 0)->field))) #define QUEUE_FOREACH(q, h) \ - for ((q) = (*(h))[0]; (q) != (h); (q) = (*(q))[0]) + for ((q) = (QUEUE *) (*(h))[0]; (q) != (h); (q) = (QUEUE *) (*(q))[0]) #define QUEUE_EMPTY(q) \ (QUEUE_NEXT(q) == (q)) diff --git a/deps/uv/src/unix/error.c b/deps/uv/src/unix/error.c index 05ab482025..74e1bac315 100644 --- a/deps/uv/src/unix/error.c +++ b/deps/uv/src/unix/error.c @@ -34,28 +34,6 @@ #include -/* TODO Expose callback to user to handle fatal error like V8 does. */ -void uv_fatal_error(const int errorno, const char* syscall) { - char* buf = NULL; - const char* errmsg; - - if (buf) { - errmsg = buf; - } else { - errmsg = "Unknown error"; - } - - if (syscall) { - fprintf(stderr, "\nlibuv fatal error. %s: (%d) %s\n", syscall, errorno, - errmsg); - } else { - fprintf(stderr, "\nlibuv fatal error. (%d) %s\n", errorno, errmsg); - } - - abort(); -} - - uv_err_code uv_translate_sys_error(int sys_errno) { switch (sys_errno) { case 0: return UV_OK; diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 2f4d526a61..9b593d9ea1 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -99,17 +99,19 @@ /* handle flags */ enum { - UV_CLOSING = 0x01, /* uv_close() called but not finished. */ - UV_CLOSED = 0x02, /* close(2) finished. */ - UV_STREAM_READING = 0x04, /* uv_read_start() called. */ - UV_STREAM_SHUTTING = 0x08, /* uv_shutdown() called but not complete. */ - UV_STREAM_SHUT = 0x10, /* Write side closed. */ - UV_STREAM_READABLE = 0x20, /* The stream is readable */ - UV_STREAM_WRITABLE = 0x40, /* The stream is writable */ - UV_STREAM_BLOCKING = 0x80, /* Synchronous writes. */ - UV_TCP_NODELAY = 0x100, /* Disable Nagle. */ - UV_TCP_KEEPALIVE = 0x200, /* Turn on keep-alive. */ - UV_TCP_SINGLE_ACCEPT = 0x400 /* Only accept() when idle. */ + UV_CLOSING = 0x01, /* uv_close() called but not finished. */ + UV_CLOSED = 0x02, /* close(2) finished. */ + UV_STREAM_READING = 0x04, /* uv_read_start() called. */ + UV_STREAM_SHUTTING = 0x08, /* uv_shutdown() called but not complete. */ + UV_STREAM_SHUT = 0x10, /* Write side closed. */ + UV_STREAM_READABLE = 0x20, /* The stream is readable */ + UV_STREAM_WRITABLE = 0x40, /* The stream is writable */ + UV_STREAM_BLOCKING = 0x80, /* Synchronous writes. */ + UV_STREAM_READ_PARTIAL = 0x100, /* read(2) read less than requested. */ + UV_STREAM_READ_EOF = 0x200, /* read(2) read EOF. */ + UV_TCP_NODELAY = 0x400, /* Disable Nagle. */ + UV_TCP_KEEPALIVE = 0x800, /* Turn on keep-alive. */ + UV_TCP_SINGLE_ACCEPT = 0x1000 /* Only accept() when idle. */ }; /* core */ @@ -142,7 +144,6 @@ void uv__run_prepare(uv_loop_t* loop); /* error */ uv_err_code uv_translate_sys_error(int sys_errno); -void uv_fatal_error(const int errorno, const char* syscall); /* stream */ void uv__stream_init(uv_loop_t* loop, uv_stream_t* stream, diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index 23af7891e1..f18da7a8c2 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -36,7 +36,10 @@ #include #include +#ifndef __ANDROID__ #define HAVE_IFADDRS_H 1 +#endif + #ifdef __UCLIBC__ # if __UCLIBC_MAJOR__ < 0 || __UCLIBC_MINOR__ < 9 || __UCLIBC_SUBLEVEL__ < 32 # undef HAVE_IFADDRS_H @@ -427,7 +430,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { char* model; FILE* fp; - /* Most are unused on non-ARM and non-x86 architectures. */ + /* Most are unused on non-ARM, non-MIPS and non-x86 architectures. */ (void) &model_marker; (void) &speed_marker; (void) &speed_idx; @@ -438,7 +441,10 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { model_idx = 0; speed_idx = 0; -#if defined(__arm__) || defined(__i386__) || defined(__x86_64__) +#if defined(__arm__) || \ + defined(__i386__) || \ + defined(__mips__) || \ + defined(__x86_64__) fp = fopen("/proc/cpuinfo", "r"); if (fp == NULL) return -1; @@ -456,10 +462,14 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { continue; } } -#if defined(__arm__) - /* Fallback for pre-3.8 kernels. */ +#if defined(__arm__) || defined(__mips__) if (model_idx < numcpus) { +#if defined(__arm__) + /* Fallback for pre-3.8 kernels. */ static const char model_marker[] = "Processor\t: "; +#else /* defined(__mips__) */ + static const char model_marker[] = "cpu model\t\t: "; +#endif if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) { model = buf + sizeof(model_marker) - 1; model = strndup(model, strlen(model) - 1); /* Strip newline. */ @@ -471,18 +481,18 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { continue; } } -#else /* !__arm____ */ +#else /* !__arm__ && !__mips__ */ if (speed_idx < numcpus) { if (strncmp(buf, speed_marker, sizeof(speed_marker) - 1) == 0) { ci[speed_idx++].speed = atoi(buf + sizeof(speed_marker) - 1); continue; } } -#endif /* __arm__ */ +#endif /* __arm__ || __mips__ */ } fclose(fp); -#endif /* __arm__ || __i386__ || __x86_64__ */ +#endif /* __arm__ || __i386__ || __mips__ || __x86_64__ */ /* Now we want to make sure that all the models contain *something* because * it's not safe to leave them as null. Copy the last entry unless there diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h index ba44974a06..1ad9518548 100644 --- a/deps/uv/src/unix/linux-syscalls.h +++ b/deps/uv/src/unix/linux-syscalls.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #if defined(__alpha__) diff --git a/deps/uv/src/unix/pthread-fixes.c b/deps/uv/src/unix/pthread-fixes.c new file mode 100644 index 0000000000..2e4c542bc2 --- /dev/null +++ b/deps/uv/src/unix/pthread-fixes.c @@ -0,0 +1,80 @@ +/* Copyright (c) 2013, Sony Mobile Communications AB + * Copyright (c) 2012, Google Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/*Android doesn't provide pthread_barrier_t for now.*/ +#ifndef PTHREAD_BARRIER_SERIAL_THREAD + +#include "pthread-fixes.h" + +int pthread_barrier_init(pthread_barrier_t* barrier, + const void* barrier_attr, + unsigned count) { + barrier->count = count; + pthread_mutex_init(&barrier->mutex, NULL); + pthread_cond_init(&barrier->cond, NULL); + return 0; +} + +int pthread_barrier_wait(pthread_barrier_t* barrier) { + /* Lock the mutex*/ + pthread_mutex_lock(&barrier->mutex); + /* Decrement the count. If this is the first thread to reach 0, wake up + waiters, unlock the mutex, then return PTHREAD_BARRIER_SERIAL_THREAD.*/ + if (--barrier->count == 0) { + /* First thread to reach the barrier */ + pthread_cond_broadcast(&barrier->cond); + pthread_mutex_unlock(&barrier->mutex); + return PTHREAD_BARRIER_SERIAL_THREAD; + } + /* Otherwise, wait for other threads until the count reaches 0, then + return 0 to indicate this is not the first thread.*/ + do { + pthread_cond_wait(&barrier->cond, &barrier->mutex); + } while (barrier->count > 0); + + pthread_mutex_unlock(&barrier->mutex); + return 0; +} + +int pthread_barrier_destroy(pthread_barrier_t *barrier) { + barrier->count = 0; + pthread_cond_destroy(&barrier->cond); + pthread_mutex_destroy(&barrier->mutex); + return 0; +} + +#endif /* defined(PTHREAD_BARRIER_SERIAL_THREAD) */ + +int pthread_yield(void) { + sched_yield(); + return 0; +} diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 7936380a2f..9688fbe520 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -613,6 +613,7 @@ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { static void uv__drain(uv_stream_t* stream) { uv_shutdown_t* req; + int status; assert(QUEUE_EMPTY(&stream->write_queue)); uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); @@ -625,21 +626,17 @@ static void uv__drain(uv_stream_t* stream) { req = stream->shutdown_req; stream->shutdown_req = NULL; + stream->flags &= ~UV_STREAM_SHUTTING; uv__req_unregister(stream->loop, req); - if (shutdown(uv__stream_fd(stream), SHUT_WR)) { - /* Error. Report it. User should call uv_close(). */ + status = shutdown(uv__stream_fd(stream), SHUT_WR); + if (status) uv__set_sys_error(stream->loop, errno); - if (req->cb) { - req->cb(req, -1); - } - } else { - uv__set_sys_error(stream->loop, 0); - ((uv_handle_t*) stream)->flags |= UV_STREAM_SHUT; - if (req->cb) { - req->cb(req, 0); - } - } + else + stream->flags |= UV_STREAM_SHUT; + + if (req->cb != NULL) + req->cb(req, status); } } @@ -696,11 +693,24 @@ static int uv__handle_fd(uv_handle_t* handle) { } } +static int uv__getiovmax() { +#if defined(IOV_MAX) + return IOV_MAX; +#elif defined(_SC_IOV_MAX) + static int iovmax = -1; + if (iovmax == -1) + iovmax = sysconf(_SC_IOV_MAX); + return iovmax; +#else + return 1024; +#endif +} static void uv__write(uv_stream_t* stream) { struct iovec* iov; QUEUE* q; uv_write_t* req; + int iovmax; int iovcnt; ssize_t n; @@ -723,9 +733,11 @@ start: iov = (struct iovec*) &(req->bufs[req->write_index]); iovcnt = req->bufcnt - req->write_index; + iovmax = uv__getiovmax(); + /* Limit iov count to avoid EINVALs from writev() */ - if (iovcnt > IOV_MAX) - iovcnt = IOV_MAX; + if (iovcnt > iovmax) + iovcnt = iovmax; /* * Now do the actual writev. Note that we've been updating the pointers @@ -915,6 +927,27 @@ static uv_handle_type uv__handle_type(int fd) { } +static void uv__stream_read_cb(uv_stream_t* stream, + int status, + uv_buf_t buf, + uv_handle_type type) { + if (stream->read_cb != NULL) + stream->read_cb(stream, status, buf); + else + stream->read2_cb((uv_pipe_t*) stream, status, buf, type); +} + + +static void uv__stream_eof(uv_stream_t* stream, uv_buf_t buf) { + stream->flags |= UV_STREAM_READ_EOF; + uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN); + if (!uv__io_active(&stream->io_watcher, UV__POLLOUT)) + uv__handle_stop(stream); + uv__set_artificial_error(stream->loop, UV_EOF); + uv__stream_read_cb(stream, -1, buf, UV_UNKNOWN_HANDLE); +} + + static void uv__read(uv_stream_t* stream) { uv_buf_t buf; ssize_t nread; @@ -923,6 +956,8 @@ static void uv__read(uv_stream_t* stream) { char cmsg_space[64]; int count; + stream->flags &= ~UV_STREAM_READ_PARTIAL; + /* Prevent loop starvation when the data comes in as fast as (or faster than) * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O. */ @@ -964,15 +999,6 @@ static void uv__read(uv_stream_t* stream) { while (nread < 0 && errno == EINTR); } -#define INVOKE_READ_CB(stream, status, buf, type) \ - do { \ - if ((stream)->read_cb != NULL) \ - (stream)->read_cb((stream), (status), (buf)); \ - else \ - (stream)->read2_cb((uv_pipe_t*) (stream), (status), (buf), (type)); \ - } \ - while (0) - if (nread < 0) { /* Error */ if (errno == EAGAIN || errno == EWOULDBLOCK) { @@ -981,22 +1007,17 @@ static void uv__read(uv_stream_t* stream) { uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN); } uv__set_sys_error(stream->loop, EAGAIN); - INVOKE_READ_CB(stream, 0, buf, UV_UNKNOWN_HANDLE); + uv__stream_read_cb(stream, 0, buf, UV_UNKNOWN_HANDLE); } else { /* Error. User should call uv_close(). */ uv__set_sys_error(stream->loop, errno); - INVOKE_READ_CB(stream, -1, buf, UV_UNKNOWN_HANDLE); + uv__stream_read_cb(stream, -1, buf, UV_UNKNOWN_HANDLE); assert(!uv__io_active(&stream->io_watcher, UV__POLLIN) && "stream->read_cb(status=-1) did not call uv_close()"); } return; } else if (nread == 0) { - /* EOF */ - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN); - if (!uv__io_active(&stream->io_watcher, UV__POLLOUT)) - uv__handle_stop(stream); - uv__set_artificial_error(stream->loop, UV_EOF); - INVOKE_READ_CB(stream, -1, buf, UV_UNKNOWN_HANDLE); + uv__stream_eof(stream, buf); return; } else { /* Successful read */ @@ -1047,6 +1068,7 @@ static void uv__read(uv_stream_t* stream) { /* Return if we didn't fill the buffer, there is no more data to read. */ if (nread < buflen) { + stream->flags |= UV_STREAM_READ_PARTIAL; return; } } @@ -1095,17 +1117,33 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { return; } - if (events & (UV__POLLIN | UV__POLLERR | UV__POLLHUP)) { - assert(uv__stream_fd(stream) >= 0); + assert(uv__stream_fd(stream) >= 0); + /* Ignore POLLHUP here. Even it it's set, there may still be data to read. */ + if (events & (UV__POLLIN | UV__POLLERR)) uv__read(stream); - if (uv__stream_fd(stream) == -1) - return; /* read_cb closed stream. */ + if (uv__stream_fd(stream) == -1) + return; /* read_cb closed stream. */ + + /* Short-circuit iff POLLHUP is set, the user is still interested in read + * events and uv__read() reported a partial read but not EOF. If the EOF + * flag is set, uv__read() called read_cb with err=UV_EOF and we don't + * have to do anything. If the partial read flag is not set, we can't + * report the EOF yet because there is still data to read. + */ + if ((events & UV__POLLHUP) && + (stream->flags & UV_STREAM_READING) && + (stream->flags & UV_STREAM_READ_PARTIAL) && + !(stream->flags & UV_STREAM_READ_EOF)) { + uv_buf_t buf = { NULL, 0 }; + uv__stream_eof(stream, buf); } - if (events & UV__POLLOUT) { - assert(uv__stream_fd(stream) >= 0); + if (uv__stream_fd(stream) == -1) + return; /* read_cb closed stream. */ + + if (events & (UV__POLLOUT | UV__POLLERR | UV__POLLHUP)) { uv__write(stream); uv__write_callbacks(stream); } @@ -1378,8 +1416,9 @@ void uv__stream_close(uv_stream_t* handle) { } #endif /* defined(__APPLE__) */ - uv_read_stop(handle); uv__io_close(handle->loop, &handle->io_watcher); + uv_read_stop(handle); + uv__handle_stop(handle); close(handle->io_watcher.fd); handle->io_watcher.fd = -1; @@ -1391,3 +1430,8 @@ void uv__stream_close(uv_stream_t* handle) { assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT)); } + + +int uv_stream_set_blocking(uv_stream_t* handle, int blocking) { + assert(0 && "implement me"); +} diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index e44a77ffce..0cf65a592f 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -26,9 +26,7 @@ #include #include -#if defined(__APPLE__) && defined(__MACH__) #include -#endif /* defined(__APPLE__) && defined(__MACH__) */ #undef NANOSEC #define NANOSEC ((uint64_t) 1e9) @@ -283,8 +281,10 @@ int uv_cond_init(uv_cond_t* cond) { if (pthread_condattr_init(&attr)) return -1; +#if !defined(__ANDROID__) if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) goto error2; +#endif if (pthread_cond_init(cond, &attr)) goto error2; @@ -336,7 +336,15 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { timeout += uv__hrtime(); ts.tv_sec = timeout / NANOSEC; ts.tv_nsec = timeout % NANOSEC; +#if defined(__ANDROID__) + /* + * The bionic pthread implementation doesn't support CLOCK_MONOTONIC, + * but has this alternative function instead. + */ + r = pthread_cond_timedwait_monotonic_np(cond, mutex, &ts); +#else r = pthread_cond_timedwait(cond, mutex, &ts); +#endif /* __ANDROID__ */ #endif diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 3956e0bc22..64a25991a8 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -301,37 +301,37 @@ int uv_udp_recv_stop(uv_udp_t* handle) { return uv__udp_recv_stop(handle); } + +struct thread_ctx { + void (*entry)(void* arg); + void* arg; +}; + + #ifdef _WIN32 -static UINT __stdcall uv__thread_start(void *ctx_v) +static UINT __stdcall uv__thread_start(void* arg) #else -static void *uv__thread_start(void *ctx_v) +static void* uv__thread_start(void *arg) #endif { - void (*entry)(void *arg); - void *arg; - - struct { - void (*entry)(void *arg); - void *arg; - } *ctx; + struct thread_ctx *ctx_p; + struct thread_ctx ctx; - ctx = ctx_v; - arg = ctx->arg; - entry = ctx->entry; - free(ctx); - entry(arg); + ctx_p = arg; + ctx = *ctx_p; + free(ctx_p); + ctx.entry(ctx.arg); return 0; } int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { - struct { - void (*entry)(void *arg); - void *arg; - } *ctx; + struct thread_ctx* ctx; + int err; - if ((ctx = malloc(sizeof *ctx)) == NULL) + ctx = malloc(sizeof(*ctx)); + if (ctx == NULL) return -1; ctx->entry = entry; @@ -339,15 +339,15 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { #ifdef _WIN32 *tid = (HANDLE) _beginthreadex(NULL, 0, uv__thread_start, ctx, 0, NULL); - if (*tid == 0) { + err = *tid ? 0 : errno; #else - if (pthread_create(tid, NULL, uv__thread_start, ctx)) { + err = pthread_create(tid, NULL, uv__thread_start, ctx); #endif + + if (err) free(ctx); - return -1; - } - return 0; + return err ? -1 : 0; } diff --git a/deps/uv/src/version.c b/deps/uv/src/version.c index 9114afb2cd..9ec64f6a45 100644 --- a/deps/uv/src/version.c +++ b/deps/uv/src/version.c @@ -31,7 +31,7 @@ #define UV_VERSION_MAJOR 0 #define UV_VERSION_MINOR 11 -#define UV_VERSION_PATCH 4 +#define UV_VERSION_PATCH 5 #define UV_VERSION_IS_RELEASE 1 diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index f0909cdf0e..525eda51b9 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -58,6 +58,7 @@ #define UV_HANDLE_SYNC_BYPASS_IOCP 0x00040000 #define UV_HANDLE_ZERO_READ 0x00080000 #define UV_HANDLE_EMULATE_IOCP 0x00100000 +#define UV_HANDLE_BLOCKING_WRITES 0x00200000 /* Only used by uv_tcp_t handles. */ #define UV_HANDLE_IPV6 0x01000000 diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index 0fb70eae32..8df2fcc124 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -1128,6 +1128,13 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req, /* Write the header or the whole frame. */ memset(&ipc_header_req->overlapped, 0, sizeof(ipc_header_req->overlapped)); + /* Using overlapped IO, but wait for completion before returning. + This write is blocking because ipc_frame is on stack. */ + ipc_header_req->overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); + if (!ipc_header_req->overlapped.hEvent) { + uv_fatal_error(GetLastError(), "CreateEvent"); + } + result = WriteFile(handle->handle, &ipc_frame, ipc_frame.header.flags & UV_IPC_TCP_SERVER ? @@ -1136,18 +1143,22 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req, &ipc_header_req->overlapped); if (!result && GetLastError() != ERROR_IO_PENDING) { uv__set_sys_error(loop, GetLastError()); + CloseHandle(ipc_header_req->overlapped.hEvent); return -1; } - if (result) { - /* Request completed immediately. */ - ipc_header_req->queued_bytes = 0; - } else { - /* Request queued by the kernel. */ - ipc_header_req->queued_bytes = ipc_frame.header.flags & UV_IPC_TCP_SERVER ? - sizeof(ipc_frame) : sizeof(ipc_frame.header); - handle->write_queue_size += ipc_header_req->queued_bytes; + if (!result) { + /* Request not completed immediately. Wait for it.*/ + if (WaitForSingleObject(ipc_header_req->overlapped.hEvent, INFINITE) != + WAIT_OBJECT_0) { + uv__set_sys_error(loop, GetLastError()); + CloseHandle(ipc_header_req->overlapped.hEvent); + return -1; + } } + ipc_header_req->queued_bytes = 0; + CloseHandle(ipc_header_req->overlapped.hEvent); + ipc_header_req->overlapped.hEvent = NULL; REGISTER_HANDLE_REQ(loop, handle, ipc_header_req); handle->reqs_pending++; @@ -1159,7 +1170,29 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req, } } - if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { + if ((handle->flags & + (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) == + (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) { + DWORD bytes; + result = WriteFile(handle->handle, + bufs[0].base, + bufs[0].len, + &bytes, + NULL); + + if (!result) { + return uv__set_sys_error(loop, GetLastError()); + } else { + /* Request completed immediately. */ + req->queued_bytes = 0; + } + + REGISTER_HANDLE_REQ(loop, handle, req); + handle->reqs_pending++; + handle->write_reqs_pending++; + POST_COMPLETION_FOR_REQ(loop, req); + return 0; + } else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { req->write_buffer = bufs[0]; uv_insert_non_overlapped_write_req(handle, req); if (handle->write_reqs_pending == 0) { @@ -1169,6 +1202,44 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req, /* Request queued by the kernel. */ req->queued_bytes = uv_count_bufs(bufs, bufcnt); handle->write_queue_size += req->queued_bytes; + } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) { + /* Using overlapped IO, but wait for completion before returning */ + req->overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); + if (!req->overlapped.hEvent) { + uv_fatal_error(GetLastError(), "CreateEvent"); + } + + result = WriteFile(handle->handle, + bufs[0].base, + bufs[0].len, + NULL, + &req->overlapped); + + if (!result && GetLastError() != ERROR_IO_PENDING) { + uv__set_sys_error(loop, GetLastError()); + CloseHandle(req->overlapped.hEvent); + return -1; + } + + if (result) { + /* Request completed immediately. */ + req->queued_bytes = 0; + } else { + /* Request queued by the kernel. */ + if (WaitForSingleObject(ipc_header_req->overlapped.hEvent, INFINITE) != + WAIT_OBJECT_0) { + uv__set_sys_error(loop, GetLastError()); + CloseHandle(ipc_header_req->overlapped.hEvent); + return -1; + } + } + CloseHandle(req->overlapped.hEvent); + + REGISTER_HANDLE_REQ(loop, handle, req); + handle->reqs_pending++; + handle->write_reqs_pending++; + POST_COMPLETION_FOR_REQ(loop, req); + return 0; } else { result = WriteFile(handle->handle, bufs[0].base, diff --git a/deps/uv/src/win/stream.c b/deps/uv/src/win/stream.c index edc5407cf5..26485851e9 100644 --- a/deps/uv/src/win/stream.c +++ b/deps/uv/src/win/stream.c @@ -196,3 +196,13 @@ int uv_is_readable(const uv_stream_t* handle) { int uv_is_writable(const uv_stream_t* handle) { return !!(handle->flags & UV_HANDLE_WRITABLE); } + + +int uv_stream_set_blocking(uv_stream_t* handle, int blocking) { + if (blocking != 0) + handle->flags |= UV_HANDLE_BLOCKING_WRITES; + else + handle->flags &= ~UV_HANDLE_BLOCKING_WRITES; + + return 0; +} diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index c3ef6533d5..59a36de01f 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -50,7 +50,7 @@ static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) { TCP_NODELAY, (const char*)&enable, sizeof enable) == -1) { - uv__set_sys_error(handle->loop, errno); + uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; } return 0; @@ -63,7 +63,7 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign SO_KEEPALIVE, (const char*)&enable, sizeof enable) == -1) { - uv__set_sys_error(handle->loop, errno); + uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; } @@ -72,7 +72,7 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign TCP_KEEPALIVE, (const char*)&delay, sizeof delay) == -1) { - uv__set_sys_error(handle->loop, errno); + uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; } diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 8eedb495d4..ed7f115718 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -31,7 +31,7 @@ #include "uv.h" #include "internal.h" -#include +#include #include #include #include diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index 308201e579..1e3f8df804 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -43,6 +43,16 @@ # define TEST_PIPENAME_2 "/tmp/uv-test-sock2" #endif +#ifdef _WIN32 +# include +# ifndef S_IRUSR +# define S_IRUSR _S_IREAD +# endif +# ifndef S_IWUSR +# define S_IWUSR _S_IWRITE +# endif +#endif + #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define container_of(ptr, type, member) \ diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index 37f9cf2e31..e989511582 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -56,7 +56,7 @@ static void create_file(uv_loop_t* loop, const char* name) { uv_fs_t req; r = uv_fs_open(loop, &req, name, O_WRONLY | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); file = r; uv_fs_req_cleanup(&req); diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 6459d125cf..1ab958f1e9 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -600,7 +600,7 @@ TEST_IMPL(fs_file_async) { loop = uv_default_loop(); r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IREAD | S_IWRITE, create_cb); + S_IRUSR | S_IWUSR, create_cb); ASSERT(r == 0); uv_run(loop, UV_RUN_DEFAULT); @@ -663,7 +663,7 @@ TEST_IMPL(fs_file_sync) { loop = uv_default_loop(); r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(open_req1.result != -1); uv_fs_req_cleanup(&open_req1); @@ -756,7 +756,7 @@ TEST_IMPL(fs_async_dir) { /* Create 2 files synchronously. */ r = uv_fs_open(loop, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); uv_fs_req_cleanup(&open_req1); r = uv_fs_close(loop, &close_req, open_req1.result, NULL); @@ -764,7 +764,7 @@ TEST_IMPL(fs_async_dir) { uv_fs_req_cleanup(&close_req); r = uv_fs_open(loop, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); uv_fs_req_cleanup(&open_req1); r = uv_fs_close(loop, &close_req, open_req1.result, NULL); @@ -840,7 +840,7 @@ TEST_IMPL(fs_async_sendfile) { unlink("test_file"); unlink("test_file2"); - f = open("test_file", O_WRONLY | O_CREAT, S_IWRITE | S_IREAD); + f = open("test_file", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR); ASSERT(f != -1); r = write(f, "begin\n", 6); @@ -862,7 +862,7 @@ TEST_IMPL(fs_async_sendfile) { uv_fs_req_cleanup(&open_req1); r = uv_fs_open(loop, &open_req2, "test_file2", O_WRONLY | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(open_req2.result != -1); uv_fs_req_cleanup(&open_req2); @@ -909,7 +909,7 @@ TEST_IMPL(fs_fstat) { loop = uv_default_loop(); r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(req.result != -1); file = req.result; @@ -1003,7 +1003,7 @@ TEST_IMPL(fs_chmod) { loop = uv_default_loop(); r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(req.result != -1); file = req.result; @@ -1100,7 +1100,7 @@ TEST_IMPL(fs_chown) { loop = uv_default_loop(); r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(req.result != -1); file = req.result; @@ -1166,7 +1166,7 @@ TEST_IMPL(fs_link) { loop = uv_default_loop(); r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(req.result != -1); file = req.result; @@ -1274,7 +1274,7 @@ TEST_IMPL(fs_symlink) { loop = uv_default_loop(); r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(req.result != -1); file = req.result; @@ -1439,7 +1439,7 @@ TEST_IMPL(fs_symlink_dir) { uv_fs_req_cleanup(&req); r = uv_fs_open(loop, &open_req1, "test_dir/file1", O_WRONLY | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); uv_fs_req_cleanup(&open_req1); r = uv_fs_close(loop, &close_req, open_req1.result, NULL); @@ -1447,7 +1447,7 @@ TEST_IMPL(fs_symlink_dir) { uv_fs_req_cleanup(&close_req); r = uv_fs_open(loop, &open_req1, "test_dir/file2", O_WRONLY | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); uv_fs_req_cleanup(&open_req1); r = uv_fs_close(loop, &close_req, open_req1.result, NULL); @@ -1504,7 +1504,7 @@ TEST_IMPL(fs_utime) { loop = uv_default_loop(); unlink(path); r = uv_fs_open(loop, &req, path, O_RDWR | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(req.result != -1); uv_fs_req_cleanup(&req); @@ -1589,7 +1589,7 @@ TEST_IMPL(fs_futime) { loop = uv_default_loop(); unlink(path); r = uv_fs_open(loop, &req, path, O_RDWR | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(req.result != -1); uv_fs_req_cleanup(&req); @@ -1747,7 +1747,7 @@ TEST_IMPL(fs_file_open_append) { loop = uv_default_loop(); r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(open_req1.result != -1); uv_fs_req_cleanup(&open_req1); @@ -1779,7 +1779,7 @@ TEST_IMPL(fs_file_open_append) { ASSERT(close_req.result != -1); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, S_IREAD, NULL); + r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, S_IRUSR, NULL); ASSERT(r != -1); ASSERT(open_req1.result != -1); uv_fs_req_cleanup(&open_req1); @@ -1817,7 +1817,7 @@ TEST_IMPL(fs_rename_to_existing_file) { loop = uv_default_loop(); r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(open_req1.result != -1); uv_fs_req_cleanup(&open_req1); @@ -1834,7 +1834,7 @@ TEST_IMPL(fs_rename_to_existing_file) { uv_fs_req_cleanup(&close_req); r = uv_fs_open(loop, &open_req1, "test_file2", O_WRONLY | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(open_req1.result != -1); uv_fs_req_cleanup(&open_req1); @@ -1885,7 +1885,7 @@ TEST_IMPL(fs_read_file_eof) { loop = uv_default_loop(); r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWRITE | S_IREAD, NULL); + S_IWUSR | S_IRUSR, NULL); ASSERT(r != -1); ASSERT(open_req1.result != -1); uv_fs_req_cleanup(&open_req1); diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index 56eca9c58c..afa8d918b3 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -222,7 +222,7 @@ TEST_IMPL(spawn_stdout_to_file) { init_process_options("spawn_helper2", exit_cb); r = uv_fs_open(uv_default_loop(), &fs_req, "stdout_file", O_CREAT | O_RDWR, - S_IREAD | S_IWRITE, NULL); + S_IRUSR | S_IWUSR, NULL); ASSERT(r != -1); uv_fs_req_cleanup(&fs_req); diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 2e228855a0..e000b18996 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -20,7 +20,8 @@ 'conditions': [ ['OS=="solaris"', { 'cflags': [ '-pthreads' ], - }, { + }], + ['OS not in "solaris android"', { 'cflags': [ '-pthread' ], }], ], @@ -159,7 +160,8 @@ 'conditions': [ ['OS=="solaris"', { 'ldflags': [ '-pthreads' ], - }, { + }], + ['OS != "solaris" and OS != "android"', { 'ldflags': [ '-pthread' ], }], ], @@ -177,7 +179,7 @@ }], ], }], - [ 'OS=="linux" or OS=="mac"', { + [ 'OS in "linux mac android"', { 'sources': [ 'src/unix/proctitle.c' ], }], [ 'OS=="mac"', { @@ -213,6 +215,18 @@ 'libraries': [ '-ldl', '-lrt' ], }, }], + [ 'OS=="android"', { + 'sources': [ + 'src/unix/linux-core.c', + 'src/unix/linux-inotify.c', + 'src/unix/linux-syscalls.c', + 'src/unix/linux-syscalls.h', + 'src/unix/pthread-fixes.c', + ], + 'link_settings': { + 'libraries': [ '-ldl' ], + }, + }], [ 'OS=="solaris"', { 'sources': [ 'src/unix/sunos.c' ], 'defines': [