diff --git a/Makefile b/Makefile index f8dbeaffd4b..c23b33878c1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ BUILDTYPE ?= Release all: out/Makefile - tools/gyp_node -f make $(MAKE) -C out BUILDTYPE=$(BUILDTYPE) -ln -fs out/Release/node node -ln -fs out/Debug/node node_g @@ -14,7 +13,8 @@ clean: rm -rf out distclean: - rm -rf out + -rm -rf out + -rm options.gypi test: all python tools/test.py --mode=release simple message diff --git a/common.gypi b/common.gypi index 0a4183b1c9f..c133a2e096b 100644 --- a/common.gypi +++ b/common.gypi @@ -114,6 +114,9 @@ 'cflags': [ '-Wall', '-pthread', ], 'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ], 'ldflags': [ '-pthread', ], + 'defines': [ + 'V8_SHARED=1', + ], 'conditions': [ [ 'target_arch=="ia32"', { 'cflags': [ '-m32' ], @@ -155,6 +158,9 @@ '-Wno-unused-parameter', ], }, + 'defines': [ + 'V8_SHARED=1', + ], 'target_conditions': [ ['_type!="static_library"', { 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']}, diff --git a/configure b/configure index 36ffb6bcf76..80da127905c 100755 --- a/configure +++ b/configure @@ -89,6 +89,11 @@ parser.add_option("--with-dtrace", dest="with_dtrace", help="Build with DTrace (experimental)") +parser.add_option("--isolate", + action="store_true", + dest="isolate", + help="Build with Isolate support") + # CHECKME does this still work with recent releases of V8? parser.add_option("--gdb", action="store_true", @@ -151,6 +156,7 @@ def configure_node(o): o['variables']['node_use_dtrace'] = 'true' if options.with_dtrace else 'false' o['variables']['host_arch'] = host_arch() o['variables']['target_arch'] = target_arch() + o['variables']['node_isolate'] = 'true' if options.isolate else 'false' # TODO move to node.gyp if sys.platform == 'sunos5': @@ -246,4 +252,6 @@ json.dump(output, f, indent=2, skipkeys=True) f.write("\n") f.close() -subprocess.call('tools/gyp_node') +gyp_target = 'xcode' if sys.platform == 'darwin' else 'make' + +subprocess.call(['tools/gyp_node','-f', gyp_target]) diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk index 8fe7254cfdd..c8220c56f27 100644 --- a/deps/uv/config-unix.mk +++ b/deps/uv/config-unix.mk @@ -33,6 +33,7 @@ OBJS += src/unix/fs.o OBJS += src/unix/cares.o OBJS += src/unix/udp.o OBJS += src/unix/error.o +OBJS += src/unix/thread.o OBJS += src/unix/process.o OBJS += src/unix/tcp.o OBJS += src/unix/pipe.o diff --git a/deps/uv/include/uv-private/uv-unix.h b/deps/uv/include/uv-private/uv-unix.h index 3d3b3e5f526..f157f475d8c 100644 --- a/deps/uv/include/uv-private/uv-unix.h +++ b/deps/uv/include/uv-private/uv-unix.h @@ -35,6 +35,7 @@ #include #include #include +#include /* Note: May be cast to struct iovec. See writev(2). */ typedef struct { @@ -44,6 +45,9 @@ typedef struct { typedef int uv_file; +typedef pthread_mutex_t uv_mutex_t; +typedef pthread_rwlock_t uv_rwlock_t; + /* Platform-specific definitions for uv_dlopen support. */ typedef void* uv_lib_t; #define UV_DYNAMIC /* empty */ diff --git a/deps/uv/include/uv-private/uv-win.h b/deps/uv/include/uv-private/uv-win.h index 5d461090f15..e5afd321c86 100644 --- a/deps/uv/include/uv-private/uv-win.h +++ b/deps/uv/include/uv-private/uv-win.h @@ -137,6 +137,17 @@ typedef struct uv_buf_t { typedef int uv_file; +typedef CRITICAL_SECTION uv_mutex_t; + +typedef union { + SRWLOCK srwlock_; + struct { + uv_mutex_t read_mutex_; + uv_mutex_t write_mutex_; + unsigned int num_readers_; + } fallback_; +} uv_rwlock_t; + /* Platform-specific definitions for uv_dlopen support. */ typedef HMODULE uv_lib_t; #define UV_DYNAMIC FAR WINAPI diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 0d8c67df62f..b219b0c0771 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -1297,6 +1297,20 @@ UV_EXTERN uv_err_t uv_dlclose(uv_lib_t library); */ UV_EXTERN uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr); +UV_EXTERN int uv_mutex_init(uv_mutex_t* handle); +UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle); +UV_EXTERN void uv_mutex_lock(uv_mutex_t* handle); +UV_EXTERN int uv_mutex_trylock(uv_mutex_t* handle); +UV_EXTERN void uv_mutex_unlock(uv_mutex_t* handle); + +UV_EXTERN int uv_rwlock_init(uv_rwlock_t* rwlock); +UV_EXTERN void uv_rwlock_destroy(uv_rwlock_t* rwlock); +UV_EXTERN void uv_rwlock_rdlock(uv_rwlock_t* rwlock); +UV_EXTERN int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock); +UV_EXTERN void uv_rwlock_rdunlock(uv_rwlock_t* rwlock); +UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t* rwlock); +UV_EXTERN int uv_rwlock_trywrlock(uv_rwlock_t* rwlock); +UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t* rwlock); /* the presence of these unions force similar struct layout */ union uv_any_handle { diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 7b39c1f7aed..8afef91a9de 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -739,8 +739,8 @@ int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t slen) { assert(sockfd >= 0); while (1) { -#if HAVE_ACCEPT4 - peerfd = accept4(sockfd, saddr, &slen, SOCK_NONBLOCK | SOCK_CLOEXEC); +#if HAVE_SYS_ACCEPT4 + peerfd = sys_accept4(sockfd, saddr, &slen, SOCK_NONBLOCK | SOCK_CLOEXEC); if (peerfd != -1) break; diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 1f713b7cb31..b4d91ff6b88 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -28,31 +28,70 @@ #include /* offsetof */ #undef HAVE_FUTIMES -#undef HAVE_PIPE2 -#undef HAVE_ACCEPT4 #undef HAVE_KQUEUE #undef HAVE_PORTS_FS #if defined(ANDROID) #elif defined(__linux__) -#include -#include +# undef HAVE_SYS_UTIMESAT +# undef HAVE_SYS_PIPE2 +# undef HAVE_SYS_ACCEPT4 -/* futimes() requires linux >= 2.6.22 and glib >= 2.6 */ -#if LINUX_VERSION_CODE >= 0x20616 && __GLIBC_PREREQ(2, 6) -#define HAVE_FUTIMES 1 -#endif +# undef _GNU_SOURCE +# define _GNU_SOURCE -/* pipe2() requires linux >= 2.6.27 and glibc >= 2.9 */ -#if LINUX_VERSION_CODE >= 0x2061B && __GLIBC_PREREQ(2, 9) -#define HAVE_PIPE2 1 -#endif +# include +# include +# include +# include -/* accept4() requires linux >= 2.6.28 and glib >= 2.10 */ -#if LINUX_VERSION_CODE >= 0x2061C && __GLIBC_PREREQ(2, 10) -#define HAVE_ACCEPT4 1 -#endif +# if __NR_utimensat +# define HAVE_SYS_UTIMESAT 1 +# endif +# if __NR_pipe2 +# define HAVE_SYS_PIPE2 1 +# endif +# if __NR_accept4 +# define HAVE_SYS_ACCEPT4 1 +# endif + +# if HAVE_SYS_UTIMESAT +inline static int sys_utimesat(int dirfd, + const char* path, + const struct timespec times[2], + int flags) +{ + return syscall(__NR_utimensat, dirfd, path, times, flags); +} +inline static int sys_futimes(int fd, const struct timeval times[2]) +{ + struct timespec ts[2]; + ts[0].tv_sec = times[0].tv_sec, ts[0].tv_nsec = times[0].tv_usec * 1000; + ts[1].tv_sec = times[1].tv_sec, ts[1].tv_nsec = times[1].tv_usec * 1000; + return sys_utimesat(fd, NULL, ts, 0); +} +# undef HAVE_FUTIMES +# define HAVE_FUTIMES 1 +# define futimes(fd, times) sys_futimes(fd, times) +# endif /* HAVE_SYS_FUTIMESAT */ + +# if HAVE_SYS_PIPE2 +inline static int sys_pipe2(int pipefd[2], int flags) +{ + return syscall(__NR_pipe2, pipefd, flags); +} +# endif /* HAVE_SYS_PIPE2 */ + +# if HAVE_SYS_ACCEPT4 +inline static int sys_accept4(int fd, + struct sockaddr* addr, + socklen_t* addrlen, + int flags) +{ + return syscall(__NR_accept4, fd, addr, addrlen, flags); +} +# endif /* HAVE_SYS_ACCEPT4 */ #endif /* __linux__ */ diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index 00180cd41d3..ad80a26fbb0 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -116,6 +116,7 @@ int uv_fs_event_init(uv_loop_t* loop, void uv__fs_event_destroy(uv_fs_event_t* handle) { + uv__fs_event_stop(handle); free(handle->filename); uv__close(handle->fd); handle->fd = -1; diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index c646c7fa7cf..b8dcc7bf158 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -105,7 +105,7 @@ static int uv__make_socketpair(int fds[2], int flags) { static int uv__make_pipe(int fds[2], int flags) { -#if HAVE_PIPE2 +#if HAVE_SYS_PIPE2 int fl; fl = O_CLOEXEC; @@ -113,7 +113,7 @@ static int uv__make_pipe(int fds[2], int flags) { if (flags & UV__F_NONBLOCK) fl |= O_NONBLOCK; - if (pipe2(fds, fl) == 0) + if (sys_pipe2(fds, fl) == 0) return 0; if (errno != ENOSYS) diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 25737814e58..3cdeaa8cf7b 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -145,7 +145,7 @@ void uv__stream_destroy(uv_stream_t* stream) { req = ngx_queue_data(q, uv_write_t, queue); if (req->cb) { - uv__set_sys_error(stream->loop, req->error); + uv__set_artificial_error(stream->loop, req->error); req->cb(req, req->error ? -1 : 0); } } @@ -490,7 +490,7 @@ static void uv__write_callbacks(uv_stream_t* stream) { /* NOTE: call callback AFTER freeing the request data. */ if (req->cb) { - uv__set_sys_error(stream->loop, req->error); + uv__set_artificial_error(stream->loop, req->error); req->cb(req, req->error ? -1 : 0); } diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c new file mode 100644 index 00000000000..b5c0f19839e --- /dev/null +++ b/deps/uv/src/unix/thread.c @@ -0,0 +1,141 @@ +/* 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 "internal.h" + +#include +#include + + +#ifdef NDEBUG +# define CHECK(r) ((void) (r)) +#else +# include +# include +# define CHECK(r) \ + do { \ + int __r = (r); \ + if (__r) errno = __r, perror(#r), abort(); \ + } \ + while (0) +#endif + + +int uv_mutex_init(uv_mutex_t* mutex) { + if (pthread_mutex_init(mutex, NULL)) + return -1; + else + return 0; +} + + +void uv_mutex_destroy(uv_mutex_t* mutex) { + CHECK(pthread_mutex_destroy(mutex)); +} + + +void uv_mutex_lock(uv_mutex_t* mutex) { + CHECK(pthread_mutex_lock(mutex)); +} + + +int uv_mutex_trylock(uv_mutex_t* mutex) { + int r; + + r = pthread_mutex_trylock(mutex); + + if (r && r != EAGAIN) + CHECK(r); + + if (r) + return -1; + else + return 0; +} + + +void uv_mutex_unlock(uv_mutex_t* mutex) { + CHECK(pthread_mutex_unlock(mutex)); +} + + +int uv_rwlock_init(uv_rwlock_t* rwlock) { + if (pthread_rwlock_init(rwlock, NULL)) + return -1; + else + return 0; +} + + +void uv_rwlock_destroy(uv_rwlock_t* rwlock) { + CHECK(pthread_rwlock_destroy(rwlock)); +} + + +void uv_rwlock_rdlock(uv_rwlock_t* rwlock) { + CHECK(pthread_rwlock_rdlock(rwlock)); +} + + +int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) { + int r; + + r = pthread_rwlock_tryrdlock(rwlock); + + if (r && r != EAGAIN) + CHECK(r); + + if (r) + return -1; + else + return 0; +} + + +void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) { + CHECK(pthread_rwlock_unlock(rwlock)); +} + + +void uv_rwlock_wrlock(uv_rwlock_t* rwlock) { + CHECK(pthread_rwlock_wrlock(rwlock)); +} + + +int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) { + int r; + + r = pthread_rwlock_trywrlock(rwlock); + + if (r && r != EAGAIN) + CHECK(r); + + if (r) + return -1; + else + return 0; +} + + +void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) { + CHECK(pthread_rwlock_unlock(rwlock)); +} diff --git a/deps/uv/src/win/handle.c b/deps/uv/src/win/handle.c index b67139cbc6a..ba0af755fe7 100644 --- a/deps/uv/src/win/handle.c +++ b/deps/uv/src/win/handle.c @@ -35,7 +35,7 @@ uv_handle_type uv_guess_handle(uv_file file) { if (GetConsoleMode(handle, &mode)) { return UV_TTY; } else { - return UV_UNKNOWN_HANDLE; + return UV_FILE; } case FILE_TYPE_PIPE: diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c new file mode 100644 index 00000000000..1ee1a10c3ea --- /dev/null +++ b/deps/uv/src/win/thread.c @@ -0,0 +1,320 @@ +/* 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 "../uv-common.h" +#include "internal.h" +#include + +#define HAVE_SRWLOCK_API() (pTryAcquireSRWLockShared != NULL) + +#ifdef _MSC_VER /* msvc */ +# define inline __inline +# define NOINLINE __declspec (noinline) +#else /* gcc */ +# define inline inline +# define NOINLINE __attribute__ ((noinline)) +#endif + + +inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock); +inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock); +inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock); +inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock); +inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock); +inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock); +inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock); +inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock); + +inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock); +inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock); +inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock); +inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock); +inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock); +inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock); +inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock); +inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock); + + +static NOINLINE void uv__once_inner(uv_once_t* guard, + void (*callback)(void)) { + DWORD result; + HANDLE existing_event, created_event; + HANDLE* event_ptr; + + /* Fetch and align event_ptr */ + event_ptr = (HANDLE*) (((uintptr_t) &guard->event + (sizeof(HANDLE) - 1)) & + ~(sizeof(HANDLE) - 1)); + + created_event = CreateEvent(NULL, 1, 0, NULL); + if (created_event == 0) { + /* Could fail in a low-memory situation? */ + uv_fatal_error(GetLastError(), "CreateEvent"); + } + + existing_event = InterlockedCompareExchangePointer(event_ptr, + created_event, + NULL); + + if (existing_event == NULL) { + /* We won the race */ + callback(); + + result = SetEvent(created_event); + assert(result); + guard->ran = 1; + + } else { + /* We lost the race. Destroy the event we created and wait for the */ + /* existing one to become signaled. */ + CloseHandle(created_event); + result = WaitForSingleObject(existing_event, INFINITE); + assert(result == WAIT_OBJECT_0); + } +} + + +void uv_once(uv_once_t* guard, void (*callback)(void)) { + /* Fast case - avoid WaitForSingleObject. */ + if (guard->ran) { + return; + } + + uv__once_inner(guard, callback); +} + +int uv_mutex_init(uv_mutex_t* mutex) { + InitializeCriticalSection(mutex); + return 0; +} + + +void uv_mutex_destroy(uv_mutex_t* mutex) { + DeleteCriticalSection(mutex); +} + + +void uv_mutex_lock(uv_mutex_t* mutex) { + EnterCriticalSection(mutex); +} + + +int uv_mutex_trylock(uv_mutex_t* mutex) { + if (TryEnterCriticalSection(mutex)) + return 0; + else + return -1; +} + + +void uv_mutex_unlock(uv_mutex_t* mutex) { + LeaveCriticalSection(mutex); +} + + +int uv_rwlock_init(uv_rwlock_t* rwlock) { + if (HAVE_SRWLOCK_API()) + return uv__rwlock_srwlock_init(rwlock); + else + return uv__rwlock_fallback_init(rwlock); +} + + +void uv_rwlock_destroy(uv_rwlock_t* rwlock) { + if (HAVE_SRWLOCK_API()) + uv__rwlock_srwlock_destroy(rwlock); + else + uv__rwlock_fallback_destroy(rwlock); +} + + +void uv_rwlock_rdlock(uv_rwlock_t* rwlock) { + if (HAVE_SRWLOCK_API()) + uv__rwlock_srwlock_rdlock(rwlock); + else + uv__rwlock_fallback_rdlock(rwlock); +} + + +int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) { + if (HAVE_SRWLOCK_API()) + return uv__rwlock_srwlock_tryrdlock(rwlock); + else + return uv__rwlock_fallback_tryrdlock(rwlock); +} + + +void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) { + if (HAVE_SRWLOCK_API()) + uv__rwlock_srwlock_rdunlock(rwlock); + else + uv__rwlock_fallback_rdunlock(rwlock); +} + + +void uv_rwlock_wrlock(uv_rwlock_t* rwlock) { + if (HAVE_SRWLOCK_API()) + uv__rwlock_srwlock_wrlock(rwlock); + else + uv__rwlock_fallback_wrlock(rwlock); +} + + +int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) { + if (HAVE_SRWLOCK_API()) + return uv__rwlock_srwlock_trywrlock(rwlock); + else + return uv__rwlock_fallback_trywrlock(rwlock); +} + + +void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) { + if (HAVE_SRWLOCK_API()) + uv__rwlock_srwlock_wrunlock(rwlock); + else + uv__rwlock_fallback_wrunlock(rwlock); +} + + +inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock) { + pInitializeSRWLock(&rwlock->srwlock_); + return 0; +} + + +inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock) { + (void) rwlock; +} + + +inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock) { + pAcquireSRWLockShared(&rwlock->srwlock_); +} + + +inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) { + if (pTryAcquireSRWLockShared(&rwlock->srwlock_)) + return 0; + else + return -1; +} + + +inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock) { + pReleaseSRWLockShared(&rwlock->srwlock_); +} + + +inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock) { + pAcquireSRWLockExclusive(&rwlock->srwlock_); +} + + +inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) { + if (pTryAcquireSRWLockExclusive(&rwlock->srwlock_)) + return 0; + else + return -1; +} + + +inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock) { + pReleaseSRWLockExclusive(&rwlock->srwlock_); +} + + +inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) { + if (uv_mutex_init(&rwlock->fallback_.read_mutex_)) + return -1; + + if (uv_mutex_init(&rwlock->fallback_.write_mutex_)) { + uv_mutex_destroy(&rwlock->fallback_.read_mutex_); + return -1; + } + + rwlock->fallback_.num_readers_ = 0; + + return 0; +} + + +inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock) { + uv_mutex_destroy(&rwlock->fallback_.read_mutex_); + uv_mutex_destroy(&rwlock->fallback_.write_mutex_); +} + + +inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock) { + uv_mutex_lock(&rwlock->fallback_.read_mutex_); + + if (++rwlock->fallback_.num_readers_ == 1) + uv_mutex_lock(&rwlock->fallback_.write_mutex_); + + uv_mutex_unlock(&rwlock->fallback_.read_mutex_); +} + + +inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) { + int ret; + + ret = -1; + + if (uv_mutex_trylock(&rwlock->fallback_.read_mutex_)) + goto out; + + if (rwlock->fallback_.num_readers_ == 0) + ret = uv_mutex_trylock(&rwlock->fallback_.write_mutex_); + else + ret = 0; + + if (ret == 0) + rwlock->fallback_.num_readers_++; + + uv_mutex_unlock(&rwlock->fallback_.read_mutex_); + +out: + return ret; +} + + +inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) { + uv_mutex_lock(&rwlock->fallback_.read_mutex_); + + if (--rwlock->fallback_.num_readers_ == 0) + uv_mutex_unlock(&rwlock->fallback_.write_mutex_); + + uv_mutex_unlock(&rwlock->fallback_.read_mutex_); +} + + +inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock) { + uv_mutex_lock(&rwlock->fallback_.write_mutex_); +} + + +inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock) { + return uv_mutex_trylock(&rwlock->fallback_.write_mutex_); +} + + +inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) { + uv_mutex_unlock(&rwlock->fallback_.write_mutex_); +} diff --git a/deps/uv/src/win/threads.c b/deps/uv/src/win/threads.c deleted file mode 100644 index 1fc6b73f870..00000000000 --- a/deps/uv/src/win/threads.c +++ /dev/null @@ -1,81 +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 - -#include "uv.h" -#include "../uv-common.h" -#include "internal.h" - - -#ifdef _MSC_VER /* msvc */ -# define NOINLINE __declspec (noinline) -#else /* gcc */ -# define NOINLINE __attribute__ ((noinline)) -#endif - - -static NOINLINE void uv__once_inner(uv_once_t* guard, - void (*callback)(void)) { - DWORD result; - HANDLE existing_event, created_event; - HANDLE* event_ptr; - - /* Fetch and align event_ptr */ - event_ptr = (HANDLE*) (((uintptr_t) &guard->event + (sizeof(HANDLE) - 1)) & - ~(sizeof(HANDLE) - 1)); - - created_event = CreateEvent(NULL, 1, 0, NULL); - if (created_event == 0) { - /* Could fail in a low-memory situation? */ - uv_fatal_error(GetLastError(), "CreateEvent"); - } - - existing_event = InterlockedCompareExchangePointer(event_ptr, - created_event, - NULL); - - if (existing_event == NULL) { - /* We won the race */ - callback(); - - result = SetEvent(created_event); - assert(result); - guard->ran = 1; - - } else { - /* We lost the race. Destroy the event we created and wait for the */ - /* existing one to become signaled. */ - CloseHandle(created_event); - result = WaitForSingleObject(existing_event, INFINITE); - assert(result == WAIT_OBJECT_0); - } -} - - -void uv_once(uv_once_t* guard, void (*callback)(void)) { - /* Fast case - avoid WaitForSingleObject. */ - if (guard->ran) { - return; - } - - uv__once_inner(guard, callback); -} diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c index cc21361bc70..ff6912d0e8e 100644 --- a/deps/uv/src/win/winapi.c +++ b/deps/uv/src/win/winapi.c @@ -33,6 +33,13 @@ sNtSetInformationFile pNtSetInformationFile; sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; sCreateSymbolicLinkW pCreateSymbolicLinkW; +sInitializeSRWLock pInitializeSRWLock; +sAcquireSRWLockShared pAcquireSRWLockShared; +sAcquireSRWLockExclusive pAcquireSRWLockExclusive; +sTryAcquireSRWLockShared pTryAcquireSRWLockShared; +sTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive; +sReleaseSRWLockShared pReleaseSRWLockShared; +sReleaseSRWLockExclusive pReleaseSRWLockExclusive; void uv_winapi_init() { @@ -86,4 +93,25 @@ void uv_winapi_init() { pCreateSymbolicLinkW = (sCreateSymbolicLinkW) GetProcAddress(kernel32_module, "CreateSymbolicLinkW"); + + pInitializeSRWLock = (sInitializeSRWLock) + GetProcAddress(kernel32_module, "InitializeSRWLock"); + + pAcquireSRWLockShared = (sAcquireSRWLockShared) + GetProcAddress(kernel32_module, "AcquireSRWLockShared"); + + pAcquireSRWLockExclusive = (sAcquireSRWLockExclusive) + GetProcAddress(kernel32_module, "AcquireSRWLockExclusive"); + + pTryAcquireSRWLockShared = (sTryAcquireSRWLockShared) + GetProcAddress(kernel32_module, "TryAcquireSRWLockShared"); + + pTryAcquireSRWLockExclusive = (sTryAcquireSRWLockExclusive) + GetProcAddress(kernel32_module, "TryAcquireSRWLockExclusive"); + + pReleaseSRWLockShared = (sReleaseSRWLockShared) + GetProcAddress(kernel32_module, "ReleaseSRWLockShared"); + + pReleaseSRWLockExclusive = (sReleaseSRWLockExclusive) + GetProcAddress(kernel32_module, "ReleaseSRWLockExclusive"); } diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index e0038f14aca..8144939940c 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4350,6 +4350,26 @@ typedef BOOLEAN (WINAPI* sCreateSymbolicLinkW) LPCWSTR lpTargetFileName, DWORD dwFlags); +typedef VOID (WINAPI* sInitializeSRWLock) + (PSRWLOCK SRWLock); + +typedef VOID (WINAPI* sAcquireSRWLockShared) + (PSRWLOCK SRWLock); + +typedef VOID (WINAPI* sAcquireSRWLockExclusive) + (PSRWLOCK SRWLock); + +typedef BOOL (WINAPI* sTryAcquireSRWLockShared) + (PSRWLOCK SRWLock); + +typedef BOOL (WINAPI* sTryAcquireSRWLockExclusive) + (PSRWLOCK SRWLock); + +typedef VOID (WINAPI* sReleaseSRWLockShared) + (PSRWLOCK SRWLock); + +typedef VOID (WINAPI* sReleaseSRWLockExclusive) + (PSRWLOCK SRWLock); /* Ntapi function pointers */ extern sRtlNtStatusToDosError pRtlNtStatusToDosError; @@ -4362,5 +4382,12 @@ extern sNtSetInformationFile pNtSetInformationFile; extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; extern sCreateSymbolicLinkW pCreateSymbolicLinkW; +extern sInitializeSRWLock pInitializeSRWLock; +extern sAcquireSRWLockShared pAcquireSRWLockShared; +extern sAcquireSRWLockExclusive pAcquireSRWLockExclusive; +extern sTryAcquireSRWLockShared pTryAcquireSRWLockShared; +extern sTryAcquireSRWLockExclusive pTryAcquireSRWLockExclusive; +extern sReleaseSRWLockShared pReleaseSRWLockShared; +extern sReleaseSRWLockExclusive pReleaseSRWLockExclusive; #endif /* UV_WIN_WINAPI_H_ */ diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index c1f23fe996a..59bdebc0320 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -267,4 +267,44 @@ TEST_IMPL(fs_event_no_callback_on_close) { r = uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL); return 0; -} \ No newline at end of file +} + + +static void fs_event_fail(uv_fs_event_t* handle, const char* filename, + int events, int status) { + ASSERT(0 && "should never be called"); +} + + +static void timer_cb(uv_timer_t* handle, int status) { + int r; + + ASSERT(status == 0); + + r = uv_fs_event_init(handle->loop, &fs_event, ".", fs_event_fail, 0); + ASSERT(r != -1); + + uv_close((uv_handle_t*)&fs_event, close_cb); + uv_close((uv_handle_t*)handle, close_cb); +} + + +TEST_IMPL(fs_event_immediate_close) { + uv_timer_t timer; + uv_loop_t* loop; + int r; + + loop = uv_default_loop(); + + r = uv_timer_init(loop, &timer); + ASSERT(r == 0); + + r = uv_timer_start(&timer, timer_cb, 1, 0); + ASSERT(r == 0); + + uv_run(loop); + + ASSERT(close_cb_called == 2); + + return 0; +} diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 9051fdb35ce..7240157badb 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -110,10 +110,13 @@ TEST_DECLARE (fs_event_watch_dir) TEST_DECLARE (fs_event_watch_file) TEST_DECLARE (fs_event_watch_file_current_dir) TEST_DECLARE (fs_event_no_callback_on_close) +TEST_DECLARE (fs_event_immediate_close) TEST_DECLARE (fs_readdir_empty_dir) TEST_DECLARE (fs_readdir_file) TEST_DECLARE (fs_open_dir) TEST_DECLARE (threadpool_queue_work_simple) +TEST_DECLARE (thread_mutex) +TEST_DECLARE (thread_rwlock) #ifdef _WIN32 TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) TEST_DECLARE (argument_escaping) @@ -261,10 +264,13 @@ TASK_LIST_START TEST_ENTRY (fs_event_watch_file) TEST_ENTRY (fs_event_watch_file_current_dir) TEST_ENTRY (fs_event_no_callback_on_close) + TEST_ENTRY (fs_event_immediate_close) TEST_ENTRY (fs_readdir_empty_dir) TEST_ENTRY (fs_readdir_file) TEST_ENTRY (fs_open_dir) TEST_ENTRY (threadpool_queue_work_simple) + TEST_ENTRY (thread_mutex) + TEST_ENTRY (thread_rwlock) #if 0 /* These are for testing the test runner. */ diff --git a/deps/uv/test/test-mutexes.c b/deps/uv/test/test-mutexes.c new file mode 100644 index 00000000000..896f46bbed0 --- /dev/null +++ b/deps/uv/test/test-mutexes.c @@ -0,0 +1,63 @@ +/* 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 +#include + + +/* The mutex and rwlock tests are really poor. + * They're very basic sanity checks and nothing more. + * Apologies if that rhymes. + */ + +TEST_IMPL(thread_mutex) { + uv_mutex_t mutex; + int r; + + r = uv_mutex_init(&mutex); + ASSERT(r == 0); + + uv_mutex_lock(&mutex); + uv_mutex_unlock(&mutex); + uv_mutex_destroy(&mutex); + + return 0; +} + + +TEST_IMPL(thread_rwlock) { + uv_rwlock_t rwlock; + int r; + + r = uv_rwlock_init(&rwlock); + ASSERT(r == 0); + + uv_rwlock_rdlock(&rwlock); + uv_rwlock_rdunlock(&rwlock); + uv_rwlock_wrlock(&rwlock); + uv_rwlock_wrunlock(&rwlock); + uv_rwlock_destroy(&rwlock); + + return 0; +} diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 83129b5c956..ae652320159 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -139,13 +139,13 @@ 'src/win/internal.h', 'src/win/loop-watcher.c', 'src/win/pipe.c', + 'src/win/thread.c', 'src/win/process.c', 'src/win/req.c', 'src/win/stream.c', 'src/win/tcp.c', 'src/win/tty.c', 'src/win/threadpool.c', - 'src/win/threads.c', 'src/win/timer.c', 'src/win/udp.c', 'src/win/util.c', @@ -185,6 +185,7 @@ 'src/unix/cares.c', 'src/unix/dl.c', 'src/unix/error.c', + 'src/unix/thread.c', 'src/unix/process.c', 'src/unix/internal.h', 'src/unix/eio/ecb.h', @@ -311,6 +312,7 @@ 'test/test-tcp-write-to-half-open-connection.c', 'test/test-tcp-writealot.c', 'test/test-threadpool.c', + 'test/test-mutexes.c', 'test/test-timer-again.c', 'test/test-timer.c', 'test/test-tty.c', diff --git a/deps/v8/build/common.gypi b/deps/v8/build/common.gypi index 4e896e019a8..34508913fed 100644 --- a/deps/v8/build/common.gypi +++ b/deps/v8/build/common.gypi @@ -184,6 +184,9 @@ }], ], }], + ['OS=="solaris"', { + 'defines': [ '__C99FEATURES__=1' ], # isinf() etc. + }], ], 'configurations': { 'Debug': { diff --git a/deps/v8/tools/gyp/v8-node.gyp b/deps/v8/tools/gyp/v8-node.gyp deleted file mode 100644 index 3b067a5f560..00000000000 --- a/deps/v8/tools/gyp/v8-node.gyp +++ /dev/null @@ -1,6 +0,0 @@ -{ - 'includes': [ - '../../build/common.gypi', - 'v8.gyp' - ], -} diff --git a/deps/v8/tools/gyp/v8.gyp b/deps/v8/tools/gyp/v8.gyp index 50144172a04..92d1e5c96a6 100644 --- a/deps/v8/tools/gyp/v8.gyp +++ b/deps/v8/tools/gyp/v8.gyp @@ -641,6 +641,13 @@ ], } ], + ['OS=="solaris"', { + 'sources': [ + '../../src/platform-solaris.cc', + '../../src/platform-posix.cc' + ], + } + ], ['OS=="mac"', { 'sources': [ '../../src/platform-macos.cc', diff --git a/doc/api/addons.markdown b/doc/api/addons.markdown index 3234e7a6082..3e815d4d44e 100644 --- a/doc/api/addons.markdown +++ b/doc/api/addons.markdown @@ -22,8 +22,8 @@ Node statically compiles all its dependencies into the executable. When compiling your module, you don't need to worry about linking to any of these libraries. -To get started let's make a small Addon which does the following except in -C++: +To get started let's make a small Addon which is the C++ equivalent of +the following Javascript code: exports.hello = function() { return 'world'; }; @@ -40,11 +40,18 @@ To get started we create a file `hello.cc`: } void init(Handle target) { - NODE_SET_METHOD(target, "method", Method); + NODE_SET_METHOD(target, "hello", Method); } NODE_MODULE(hello, init) -This source code needs to be built into `hello.node`, the binary Addon. To +Note that all Node addons must export an initialization function: + + void Initialize (Handle target); + NODE_MODULE(module_name, Initialize) + +There is no semi-colon after `NODE_MODULE` as it's not a function (see `node.h`). + +The source code needs to be built into `hello.node`, the binary Addon. To do this we create a file called `wscript` which is python code and looks like this: @@ -70,10 +77,12 @@ Running `node-waf configure build` will create a file `node-waf` is just [WAF](http://code.google.com/p/waf), the python-based build system. `node-waf` is provided for the ease of users. -All Node addons must export an initialization function: +You can now use the binary addon in a Node project `hello.js` by pointing `require` to +the recently built module: - void Initialize (Handle target); - NODE_MODULE(hello, Initialize) + var addon = require('./build/Release/hello'); + + console.log(addon.hello()); // 'world' For the moment, that is all the documentation on addons. Please see for a real example. diff --git a/lib/util.js b/lib/util.js index 639c04f9e7a..aafc0edf325 100644 --- a/lib/util.js +++ b/lib/util.js @@ -19,9 +19,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -var events = require('events'); - - var formatRegExp = /%[sdj%]/g; exports.format = function(f) { if (typeof f !== 'string') { diff --git a/node.gyp b/node.gyp index abc83c51b37..0677cfefcde 100644 --- a/node.gyp +++ b/node.gyp @@ -8,6 +8,7 @@ 'node_use_dtrace': 'false', 'node_use_openssl%': 'true', 'node_use_system_openssl%': 'false', + 'node_isolate': 'true', 'library_files': [ 'src/node.js', 'lib/_debugger.js', @@ -50,12 +51,12 @@ 'targets': [ { - 'target_name': 'node', - 'type': 'executable', + 'target_name': 'libnode', + 'type': 'shared_library', 'dependencies': [ 'deps/http_parser/http_parser.gyp:http_parser', - 'deps/v8/tools/gyp/v8-node.gyp:v8', + 'deps/v8/tools/gyp/v8.gyp:v8', 'deps/uv/uv.gyp:uv', 'deps/zlib/zlib.gyp:zlib', 'node_js2c#host', @@ -78,7 +79,6 @@ 'src/node_file.cc', 'src/node_http_parser.cc', 'src/node_javascript.cc', - 'src/node_main.cc', 'src/node_os.cc', 'src/node_script.cc', 'src/node_string.cc', @@ -139,6 +139,13 @@ }, { 'defines': [ 'HAVE_OPENSSL=0' ] }], + + [ 'node_isolate=="true"', { + 'defines': [ + 'NODE_FORK_ISOLATE', + 'NODE_LIBRARY' + ], + }], [ 'node_use_dtrace=="true"', { 'sources': [ @@ -203,6 +210,36 @@ }, }, + { + 'target_name': 'node', + 'type': 'executable', + + 'dependencies': [ + 'libnode', + ], + + 'include_dirs': [ + 'src', + 'deps/v8/include', + 'deps/uv/include', + ], + + 'sources': [ + 'src/node_main.cc', + # node.gyp is added to the project by default. + 'common.gypi', + ], + + 'defines': [ + 'ARCH="<(target_arch)"', + 'PLATFORM="<(OS)"', + '_LARGEFILE_SOURCE', + '_FILE_OFFSET_BITS=64', + ], + + 'conditions': [], + }, + { 'target_name': 'node_js2c', 'type': 'none', diff --git a/src/node.h b/src/node.h index 0c77d91b672..f61d3ba329e 100644 --- a/src/node.h +++ b/src/node.h @@ -29,7 +29,11 @@ # define NODE_EXTERN __declspec(dllimport) # endif #else -# define NODE_EXTERN /* nothing */ +# ifndef BUILDING_NODE_EXTENSION +# define NODE_EXTERN __attribute__((visibility("default"))) +# else +# define NODE_EXTERN /* nothing */ +# endif #endif #ifdef BUILDING_NODE_EXTENSION @@ -62,6 +66,7 @@ #include #include /* struct stat */ #include +#include #include #include @@ -122,14 +127,14 @@ class NodeOptions { class Isolate { public: - static Isolate* GetDefault(); - static Isolate* GetCurrent(); + NODE_EXTERN static Isolate* GetDefault(); + NODE_EXTERN static Isolate* GetCurrent(); static uv_loop_t* GetCurrentLoop(); int Start(uv_thread_shared_t *options); - int Start(int argc, char *argv[]); - int Stop(int signum); - static Isolate* New(); - void Dispose(); + NODE_EXTERN int Start(int argc, char *argv[]); + NODE_EXTERN int Stop(int signum); + NODE_EXTERN static Isolate* New(); + NODE_EXTERN void Dispose(); v8::Local ErrnoException(int errorno, const char *syscall = NULL, const char *msg = "", @@ -242,9 +247,9 @@ class Isolate { }; -int Start(int argc, char *argv[]); -int Initialize(int argc, char *argv[]); -void Dispose(); +NODE_EXTERN int Start(int argc, char *argv[]); +NODE_EXTERN int Initialize(int argc, char *argv[]); +NODE_EXTERN void Dispose(); #define NODE_PSYMBOL(s) \ v8::Persistent::New(v8::String::NewSymbol(s)) diff --git a/src/node_crypto.cc b/src/node_crypto.cc index fe85c1b6d8e..a23cc53d442 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -86,67 +86,47 @@ class CryptoStatics : public ModuleStatics { Persistent secure_context_constructor; }; -#ifdef _WIN32 - -static HANDLE* locks; - - -static void crypto_lock_init(void) { - int i, n; - - n = CRYPTO_num_locks(); - locks = new HANDLE[n]; - - for (i = 0; i < n; i++) - if (!(locks[i] = CreateMutex(NULL, FALSE, NULL))) - abort(); -} - - -static void crypto_lock_cb(int mode, int n, const char* file, int line) { - if (mode & CRYPTO_LOCK) - WaitForSingleObject(locks[n], INFINITE); - else - ReleaseMutex(locks[n]); -} - - static unsigned long crypto_id_cb(void) { +#ifdef _WIN32 return (unsigned long) GetCurrentThreadId(); -} - #else /* !_WIN32 */ + return (unsigned long) pthread_self(); +#endif /* !_WIN32 */ +} -static pthread_rwlock_t* locks; +static uv_rwlock_t* locks; static void crypto_lock_init(void) { int i, n; n = CRYPTO_num_locks(); - locks = new pthread_rwlock_t[n]; + locks = new uv_rwlock_t[n]; for (i = 0; i < n; i++) - if (pthread_rwlock_init(locks + i, NULL)) + if (uv_rwlock_init(locks + i)) abort(); } static void crypto_lock_cb(int mode, int n, const char* file, int line) { + assert((mode & CRYPTO_LOCK) || (mode & CRYPTO_UNLOCK)); + assert((mode & CRYPTO_READ) || (mode & CRYPTO_WRITE)); + if (mode & CRYPTO_LOCK) { - if (mode & CRYPTO_READ) pthread_rwlock_rdlock(locks + n); - if (mode & CRYPTO_WRITE) pthread_rwlock_wrlock(locks + n); + if (mode & CRYPTO_READ) + uv_rwlock_rdlock(locks + n); + else + uv_rwlock_wrlock(locks + n); } else { - pthread_rwlock_unlock(locks + n); + if (mode & CRYPTO_READ) + uv_rwlock_rdunlock(locks + n); + else + uv_rwlock_wrunlock(locks + n); } } -static unsigned long crypto_id_cb(void) { - return (unsigned long) pthread_self(); -} - -#endif /* !_WIN32 */ void SecureContext::Initialize(Handle target) { @@ -3490,7 +3470,7 @@ class Verify : public ObjectWrap { delete [] kbuf; delete [] hbuf; - return scope.Close(Integer::New(r)); + return Boolean::New(r && r != -1); } Verify () : ObjectWrap () { diff --git a/src/node_object_wrap.h b/src/node_object_wrap.h index d76dd594ab8..0ead639b645 100644 --- a/src/node_object_wrap.h +++ b/src/node_object_wrap.h @@ -22,6 +22,7 @@ #ifndef object_wrap_h #define object_wrap_h +#include #include #include diff --git a/test/simple/test-crypto.js b/test/simple/test-crypto.js index 583eec75519..6b1c6ca0204 100644 --- a/test/simple/test-crypto.js +++ b/test/simple/test-crypto.js @@ -286,7 +286,7 @@ var verified = crypto.createVerify('RSA-SHA1') .update('Test') .update('123') .verify(certPem, s1, 'base64'); -assert.ok(verified, 'sign and verify (base 64)'); +assert.strictEqual(verified, true, 'sign and verify (base 64)'); var s2 = crypto.createSign('RSA-SHA256') .update('Test123') @@ -295,7 +295,7 @@ var verified = crypto.createVerify('RSA-SHA256') .update('Test') .update('123') .verify(certPem, s2); // binary -assert.ok(verified, 'sign and verify (binary)'); +assert.strictEqual(verified, true, 'sign and verify (binary)'); // Test encryption and decryption var plaintext = 'Keep this a secret? No! Tell everyone about node.js!'; @@ -392,7 +392,7 @@ var rsaSignature = rsaSign.sign(rsaKeyPem, 'hex'); assert.equal(rsaSignature, '5c50e3145c4e2497aadb0eabc83b342d0b0021ece0d4c4a064b7c8f020d7e2688b122bfb54c724ac9ee169f83f66d2fe90abeb95e8e1290e7e177152a4de3d944cf7d4883114a20ed0f78e70e25ef0f60f06b858e6af42a2f276ede95bbc6bc9a9bbdda15bd663186a6f40819a7af19e577bb2efa5e579a1f5ce8a0d4ca8b8f6'); rsaVerify.update(rsaPubPem); -assert.equal(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), 1); +assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true); // Test PBKDF2 with RFC 6070 test vectors (except #4) diff --git a/test/simple/test-http-parser.js b/test/simple/test-http-parser.js index 086d53bf448..2382726a4ac 100644 --- a/test/simple/test-http-parser.js +++ b/test/simple/test-http-parser.js @@ -149,6 +149,29 @@ function expectBody(expected) { })(); +// +// Response with no headers. +// +(function() { + var request = Buffer( + 'HTTP/1.0 200 Connection established' + CRLF + + CRLF + ); + + var parser = newParser(RESPONSE); + + parser.onHeadersComplete = mustCall(function(info) { + assert.equal(info.method, undefined); + assert.equal(info.versionMajor, 1); + assert.equal(info.versionMinor, 0); + assert.equal(info.statusCode, 200); + assert.deepEqual(info.headers || parser.headers, []); + }); + + parser.execute(request, 0, request.length); +})(); + + // // Trailing headers. // @@ -481,7 +504,7 @@ function expectBody(expected) { // -// +// Test parser reinit sequence. // (function() { var req1 = Buffer( diff --git a/test/simple/test-http-response-no-headers.js b/test/simple/test-http-response-no-headers.js new file mode 100644 index 00000000000..aa5c37b7897 --- /dev/null +++ b/test/simple/test-http-response-no-headers.js @@ -0,0 +1,75 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +var common = require('../common'); +var assert = require('assert'); +var http = require('http'); +var net = require('net'); + +var expected = 'I AM THE WALRUS'; + +var gotExpected = false; + +function test(httpVersion, callback) { + process.on('exit', function() { + assert(gotExpected); + }); + + var server = net.createServer(function(conn) { + var reply = 'HTTP/' + httpVersion + ' 200 OK\r\n\r\n' + expected; + + conn.write(reply, function() { + conn.destroy(); + }) + }); + + server.listen(common.PORT, '127.0.0.1', function() { + var options = { + host: '127.0.0.1', + port: common.PORT + }; + + var req = http.get(options, function(res) { + var body = ''; + + res.on('data', function(data) { + body += data; + }); + + res.on('end', function() { + assert.equal(body, expected); + gotExpected = true; + server.close(); + if (callback) process.nextTick(callback); + }); + }); + + req.on('error', function(err) { + throw err; + }); + }); +} + +test('0.9', function() { + test('1.0', function() { + test('1.1'); + }); +}); diff --git a/test/simple/test-stdin-resume-pause.js b/test/simple/test-stdin-resume-pause.js new file mode 100644 index 00000000000..2d2af2fc66d --- /dev/null +++ b/test/simple/test-stdin-resume-pause.js @@ -0,0 +1,23 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +process.stdin.resume(); +process.stdin.pause(); diff --git a/tools/gyp/pylib/gyp/generator/xcode.py b/tools/gyp/pylib/gyp/generator/xcode.py index 066bb9f02f8..f905efdd896 100644 --- a/tools/gyp/pylib/gyp/generator/xcode.py +++ b/tools/gyp/pylib/gyp/generator/xcode.py @@ -1161,7 +1161,7 @@ def GenerateOutput(target_list, target_dicts, data, params): if support_xct: support_xct.AddDependency(xcode_targets[dependency]) - if 'libraries' in spec: + if spec['type'] != 'none' and 'libraries' in spec: for library in spec['libraries']: xct.FrameworksPhase().AddFile(library) # Add the library's directory to LIBRARY_SEARCH_PATHS if necessary.