@@ -0,0 +1,80 @@
/* 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"

static int check_cb_called;
static int timer_cb_called;
static int close_cb_called;

static uv_check_t check_handle;
static uv_timer_t timer_handle1;
static uv_timer_t timer_handle2;


static void close_cb(uv_handle_t* handle) {
ASSERT(handle != NULL);
close_cb_called++;
}


/* check_cb should run before any close_cb */
static void check_cb(uv_check_t* handle, int status) {
ASSERT(check_cb_called == 0);
ASSERT(timer_cb_called == 1);
ASSERT(close_cb_called == 0);
uv_close((uv_handle_t*) handle, close_cb);
uv_close((uv_handle_t*) &timer_handle2, close_cb);
check_cb_called++;
}


static void timer_cb(uv_timer_t* handle, int status) {
uv_close((uv_handle_t*) handle, close_cb);
timer_cb_called++;
}


TEST_IMPL(close_order) {
uv_loop_t* loop;
loop = uv_default_loop();

uv_check_init(loop, &check_handle);
uv_check_start(&check_handle, check_cb);
uv_timer_init(loop, &timer_handle1);
uv_timer_start(&timer_handle1, timer_cb, 0, 0);
uv_timer_init(loop, &timer_handle2);
uv_timer_start(&timer_handle2, timer_cb, 100000, 0);

ASSERT(check_cb_called == 0);
ASSERT(close_cb_called == 0);
ASSERT(timer_cb_called == 0);

uv_run(loop, UV_RUN_DEFAULT);

ASSERT(check_cb_called == 1);
ASSERT(close_cb_called == 3);
ASSERT(timer_cb_called == 1);

MAKE_VALGRIND_HAPPY();
return 0;
}
@@ -103,6 +103,7 @@ static void fs_event_cb_dir(uv_fs_event_t* handle, const char* filename,
ASSERT(status == 0);
ASSERT(events == UV_RENAME);
ASSERT(filename == NULL || strcmp(filename, "file1") == 0);
ASSERT(0 == uv_fs_event_stop(handle));
uv_close((uv_handle_t*)handle, close_cb);
}

@@ -113,6 +114,7 @@ static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename,
ASSERT(status == 0);
ASSERT(events == UV_CHANGE);
ASSERT(filename == NULL || strcmp(filename, "file2") == 0);
ASSERT(0 == uv_fs_event_stop(handle));
uv_close((uv_handle_t*)handle, close_cb);
}

@@ -187,7 +189,9 @@ TEST_IMPL(fs_event_watch_dir) {
remove("watch_dir/");
create_dir(loop, "watch_dir");

r = uv_fs_event_init(loop, &fs_event, "watch_dir", fs_event_cb_dir, 0);
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event, fs_event_cb_dir, "watch_dir", 0);
ASSERT(r == 0);
r = uv_timer_init(loop, &timer);
ASSERT(r == 0);
@@ -221,7 +225,9 @@ TEST_IMPL(fs_event_watch_file) {
create_file(loop, "watch_dir/file1");
create_file(loop, "watch_dir/file2");

r = uv_fs_event_init(loop, &fs_event, "watch_dir/file2", fs_event_cb_file, 0);
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event, fs_event_cb_file, "watch_dir/file2", 0);
ASSERT(r == 0);
r = uv_timer_init(loop, &timer);
ASSERT(r == 0);
@@ -252,8 +258,10 @@ TEST_IMPL(fs_event_watch_file_twice) {
loop = uv_default_loop();
timer.data = watchers;

ASSERT(0 == uv_fs_event_init(loop, watchers + 0, path, fail_cb, 0));
ASSERT(0 == uv_fs_event_init(loop, watchers + 1, path, fail_cb, 0));
ASSERT(0 == uv_fs_event_init(loop, watchers + 0));
ASSERT(0 == uv_fs_event_start(watchers + 0, fail_cb, path, 0));
ASSERT(0 == uv_fs_event_init(loop, watchers + 1));
ASSERT(0 == uv_fs_event_start(watchers + 1, fail_cb, path, 0));
ASSERT(0 == uv_timer_init(loop, &timer));
ASSERT(0 == uv_timer_start(&timer, timer_cb_watch_twice, 10, 0));
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
@@ -273,10 +281,15 @@ TEST_IMPL(fs_event_watch_file_current_dir) {
remove("watch_file");
create_file(loop, "watch_file");

r = uv_fs_event_init(loop, &fs_event, "watch_file",
fs_event_cb_file_current_dir, 0);
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event,
fs_event_cb_file_current_dir,
"watch_file",
0);
ASSERT(r == 0);


r = uv_timer_init(loop, &timer);
ASSERT(r == 0);

@@ -310,13 +323,15 @@ TEST_IMPL(fs_event_no_callback_after_close) {
create_dir(loop, "watch_dir");
create_file(loop, "watch_dir/file1");

r = uv_fs_event_init(loop,
&fs_event,
"watch_dir/file1",
fs_event_cb_file,
0);
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event,
fs_event_cb_file,
"watch_dir/file1",
0);
ASSERT(r == 0);


uv_close((uv_handle_t*)&fs_event, close_cb);
touch_file(loop, "watch_dir/file1");
uv_run(loop, UV_RUN_DEFAULT);
@@ -342,11 +357,12 @@ TEST_IMPL(fs_event_no_callback_on_close) {
create_dir(loop, "watch_dir");
create_file(loop, "watch_dir/file1");

r = uv_fs_event_init(loop,
&fs_event,
"watch_dir/file1",
fs_event_cb_file,
0);
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event,
fs_event_cb_file,
"watch_dir/file1",
0);
ASSERT(r == 0);

uv_close((uv_handle_t*)&fs_event, close_cb);
@@ -376,7 +392,9 @@ static void timer_cb(uv_timer_t* handle, int status) {

ASSERT(status == 0);

r = uv_fs_event_init(handle->loop, &fs_event, ".", fs_event_fail, 0);
r = uv_fs_event_init(handle->loop, &fs_event);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event, fs_event_fail, ".", 0);
ASSERT(r == 0);

uv_close((uv_handle_t*)&fs_event, close_cb);
@@ -415,7 +433,9 @@ TEST_IMPL(fs_event_close_with_pending_event) {
create_dir(loop, "watch_dir");
create_file(loop, "watch_dir/file");

r = uv_fs_event_init(loop, &fs_event, "watch_dir", fs_event_fail, 0);
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir", 0);
ASSERT(r == 0);

/* Generate an fs event. */
@@ -474,7 +494,9 @@ TEST_IMPL(fs_event_close_in_callback) {
create_file(loop, "watch_dir/file4");
create_file(loop, "watch_dir/file5");

r = uv_fs_event_init(loop, &fs_event, "watch_dir", fs_event_cb_close, 0);
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event, fs_event_cb_close, "watch_dir", 0);
ASSERT(r == 0);

/* Generate a couple of fs events. */
@@ -502,3 +524,35 @@ TEST_IMPL(fs_event_close_in_callback) {
}

#endif /* HAVE_KQUEUE */

TEST_IMPL(fs_event_start_and_close) {
uv_loop_t* loop;
uv_fs_event_t fs_event1;
uv_fs_event_t fs_event2;
int r;

loop = uv_default_loop();

create_dir(loop, "watch_dir");

r = uv_fs_event_init(loop, &fs_event1);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event1, fs_event_cb_dir, "watch_dir", 0);
ASSERT(r == 0);

r = uv_fs_event_init(loop, &fs_event2);
ASSERT(r == 0);
r = uv_fs_event_start(&fs_event2, fs_event_cb_dir, "watch_dir", 0);
ASSERT(r == 0);

uv_close((uv_handle_t*) &fs_event2, close_cb);
uv_close((uv_handle_t*) &fs_event1, close_cb);

uv_run(loop, UV_RUN_DEFAULT);

ASSERT(close_cb_called == 2);

remove("watch_dir/");
MAKE_VALGRIND_HAPPY();
return 0;
}
@@ -81,7 +81,7 @@ static void poll_cb(uv_fs_poll_t* handle,
memset(&zero_statbuf, 0, sizeof(zero_statbuf));

ASSERT(handle == &poll_handle);
ASSERT(uv_is_active((uv_handle_t*)handle));
ASSERT(1 == uv_is_active((uv_handle_t*) handle));
ASSERT(prev != NULL);
ASSERT(curr != NULL);

@@ -1333,7 +1333,12 @@ TEST_IMPL(fs_symlink) {

close(link);

r = uv_fs_symlink(loop, &req, "test_file_symlink", "test_file_symlink_symlink", 0, NULL);
r = uv_fs_symlink(loop,
&req,
"test_file_symlink",
"test_file_symlink_symlink",
0,
NULL);
ASSERT(r == 0);
uv_fs_req_cleanup(&req);

@@ -1343,7 +1348,12 @@ TEST_IMPL(fs_symlink) {
uv_fs_req_cleanup(&req);

/* async link */
r = uv_fs_symlink(loop, &req, "test_file", "test_file_symlink2", 0, symlink_cb);
r = uv_fs_symlink(loop,
&req,
"test_file",
"test_file_symlink2",
0,
symlink_cb);
ASSERT(r == 0);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(symlink_cb_count == 1);
@@ -1362,7 +1372,12 @@ TEST_IMPL(fs_symlink) {

close(link);

r = uv_fs_symlink(loop, &req, "test_file_symlink2", "test_file_symlink2_symlink", 0, NULL);
r = uv_fs_symlink(loop,
&req,
"test_file_symlink2",
"test_file_symlink2_symlink",
0,
NULL);
ASSERT(r == 0);
uv_fs_req_cleanup(&req);

@@ -47,7 +47,9 @@ TEST_IMPL(get_currentexe) {
}

match = strstr(buffer, path);
/* Verify that the path returned from uv_exepath is a subdirectory of executable_path */
/* Verify that the path returned from uv_exepath is a subdirectory of
* executable_path.
*/
ASSERT(match && !strcmp(match, path));
ASSERT(size == strlen(buffer));

@@ -211,9 +211,9 @@ int ipc_send_recv_helper(void) {
ASSERT(r == 0);

uv_pipe_open(&ctx.channel, 0);
ASSERT(uv_is_readable((uv_stream_t*)&ctx.channel));
ASSERT(uv_is_writable((uv_stream_t*)&ctx.channel));
ASSERT(!uv_is_closing((uv_handle_t*)&ctx.channel));
ASSERT(1 == uv_is_readable((uv_stream_t*)&ctx.channel));
ASSERT(1 == uv_is_writable((uv_stream_t*)&ctx.channel));
ASSERT(0 == uv_is_closing((uv_handle_t*)&ctx.channel));

r = uv_read2_start((uv_stream_t*)&ctx.channel, alloc_cb, read2_cb);
ASSERT(r == 0);
@@ -559,9 +559,9 @@ int ipc_helper(int listen_after_write) {

uv_pipe_open(&channel, 0);

ASSERT(uv_is_readable((uv_stream_t*) &channel));
ASSERT(uv_is_writable((uv_stream_t*) &channel));
ASSERT(!uv_is_closing((uv_handle_t*) &channel));
ASSERT(1 == uv_is_readable((uv_stream_t*) &channel));
ASSERT(1 == uv_is_writable((uv_stream_t*) &channel));
ASSERT(0 == uv_is_closing((uv_handle_t*) &channel));

r = uv_tcp_init(uv_default_loop(), &tcp_server);
ASSERT(r == 0);
@@ -609,9 +609,9 @@ int ipc_helper_tcp_connection(void) {

uv_pipe_open(&channel, 0);

ASSERT(uv_is_readable((uv_stream_t*)&channel));
ASSERT(uv_is_writable((uv_stream_t*)&channel));
ASSERT(!uv_is_closing((uv_handle_t*)&channel));
ASSERT(1 == uv_is_readable((uv_stream_t*) &channel));
ASSERT(1 == uv_is_writable((uv_stream_t*) &channel));
ASSERT(0 == uv_is_closing((uv_handle_t*) &channel));

r = uv_tcp_init(uv_default_loop(), &tcp_server);
ASSERT(r == 0);
@@ -21,6 +21,7 @@

TEST_DECLARE (platform_output)
TEST_DECLARE (callback_order)
TEST_DECLARE (close_order)
TEST_DECLARE (run_once)
TEST_DECLARE (run_nowait)
TEST_DECLARE (loop_stop)
@@ -192,6 +193,7 @@ TEST_DECLARE (fs_event_no_callback_on_close)
TEST_DECLARE (fs_event_immediate_close)
TEST_DECLARE (fs_event_close_with_pending_event)
TEST_DECLARE (fs_event_close_in_callback)
TEST_DECLARE (fs_event_start_and_close)
TEST_DECLARE (fs_readdir_empty_dir)
TEST_DECLARE (fs_readdir_file)
TEST_DECLARE (fs_open_dir)
@@ -242,6 +244,7 @@ TASK_LIST_START
#if 0
TEST_ENTRY (callback_order)
#endif
TEST_ENTRY (close_order)
TEST_ENTRY (run_once)
TEST_ENTRY (run_nowait)
TEST_ENTRY (loop_stop)
@@ -486,6 +489,7 @@ TASK_LIST_START
TEST_ENTRY (fs_event_immediate_close)
TEST_ENTRY (fs_event_close_with_pending_event)
TEST_ENTRY (fs_event_close_in_callback)
TEST_ENTRY (fs_event_start_and_close)
TEST_ENTRY (fs_readdir_empty_dir)
TEST_ENTRY (fs_readdir_file)
TEST_ENTRY (fs_open_dir)
@@ -62,7 +62,7 @@ TEST_IMPL(loop_stop) {

r = uv_run(uv_default_loop(), UV_RUN_NOWAIT);
ASSERT(r != 0);
ASSERT(prepare_called == 3);
ASSERT(prepare_called > 1);

r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(r == 0);
@@ -78,7 +78,11 @@ static void pinger_write_ping(pinger_t* pinger) {
buf = uv_buf_init(PING, sizeof(PING) - 1);

req = malloc(sizeof(*req));
if (uv_write(req, (uv_stream_t*)&pinger->stream.tcp, &buf, 1, pinger_after_write)) {
if (uv_write(req,
(uv_stream_t*) &pinger->stream.tcp,
&buf,
1,
pinger_after_write)) {
FATAL("uv_write failed");
}

@@ -135,9 +139,9 @@ static void pinger_on_connect(uv_connect_t *req, int status) {

ASSERT(status == 0);

ASSERT(uv_is_readable(req->handle));
ASSERT(uv_is_writable(req->handle));
ASSERT(!uv_is_closing((uv_handle_t *)req->handle));
ASSERT(1 == uv_is_readable(req->handle));
ASSERT(1 == uv_is_writable(req->handle));
ASSERT(0 == uv_is_closing((uv_handle_t *) req->handle));

pinger_write_ping(pinger);

@@ -406,9 +406,9 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {

/* Assert that uv_is_active works correctly for poll handles. */
if (context->events != 0) {
ASSERT(uv_is_active((uv_handle_t*) handle));
ASSERT(1 == uv_is_active((uv_handle_t*) handle));
} else {
ASSERT(!uv_is_active((uv_handle_t*) handle));
ASSERT(0 == uv_is_active((uv_handle_t*) handle));
}
}

@@ -418,7 +418,7 @@ static void delay_timer_cb(uv_timer_t* timer, int status) {
int r;

/* Timer should auto stop. */
ASSERT(!uv_is_active((uv_handle_t*) timer));
ASSERT(0 == uv_is_active((uv_handle_t*) timer));

/* Add the requested events to the poll mask. */
ASSERT(context->delayed_events != 0);
@@ -196,7 +196,8 @@ TEST_IMPL(timer_ref2) {

TEST_IMPL(fs_event_ref) {
uv_fs_event_t h;
uv_fs_event_init(uv_default_loop(), &h, ".", (uv_fs_event_cb)fail_cb, 0);
uv_fs_event_init(uv_default_loop(), &h);
uv_fs_event_start(&h, (uv_fs_event_cb)fail_cb, ".", 0);
uv_unref((uv_handle_t*)&h);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
do_close(&h);
@@ -56,9 +56,9 @@ static void connect_cb(uv_connect_t* req, int status) {

r = uv_shutdown(&shutdown_req, req->handle, shutdown_cb);
ASSERT(r == 0);
ASSERT(!uv_is_closing((uv_handle_t*) req->handle));
ASSERT(0 == uv_is_closing((uv_handle_t*) req->handle));
uv_close((uv_handle_t*) req->handle, close_cb);
ASSERT(uv_is_closing((uv_handle_t*) req->handle));
ASSERT(1 == uv_is_closing((uv_handle_t*) req->handle));

connect_cb_called++;
}
@@ -34,10 +34,20 @@
#include <string.h>
#include <unistd.h>


#define NUM_SIGNAL_HANDLING_THREADS 25
/* The value of NUM_SIGNAL_HANDLING_THREADS is not arbitrary; it needs to be a
* multiple of three for reasons that will become clear when you scroll down.
* We're basically creating three different thread groups. The total needs
* to be divisible by three in order for the numbers in the final check to
* match up.
*/
#define NUM_SIGNAL_HANDLING_THREADS 24
#define NUM_LOOP_CREATING_THREADS 10

enum signal_action {
ONLY_SIGUSR1,
ONLY_SIGUSR2,
SIGUSR1_AND_SIGUSR2
};

static uv_sem_t sem;
static uv_mutex_t counter_lock;
@@ -70,18 +80,20 @@ static void signal2_cb(uv_signal_t* handle, int signum) {


static void signal_handling_worker(void* context) {
uintptr_t mask = (uintptr_t) context;
uv_loop_t* loop;
enum signal_action action;
uv_signal_t signal1a;
uv_signal_t signal1b;
uv_signal_t signal2;
uv_loop_t* loop;
int r;

action = (enum signal_action) (uintptr_t) context;

loop = uv_loop_new();
ASSERT(loop != NULL);

/* Setup the signal watchers and start them. */
if (mask & SIGUSR1) {
if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) {
r = uv_signal_init(loop, &signal1a);
ASSERT(r == 0);
r = uv_signal_start(&signal1a, signal1_cb, SIGUSR1);
@@ -91,7 +103,8 @@ static void signal_handling_worker(void* context) {
r = uv_signal_start(&signal1b, signal1_cb, SIGUSR1);
ASSERT(r == 0);
}
if (mask & SIGUSR2) {

if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) {
r = uv_signal_init(loop, &signal2);
ASSERT(r == 0);
r = uv_signal_start(&signal2, signal2_cb, SIGUSR2);
@@ -108,13 +121,14 @@ static void signal_handling_worker(void* context) {
ASSERT(r == 0);

/* Restart the signal watchers. */
if (mask & SIGUSR1) {
if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) {
r = uv_signal_start(&signal1a, signal1_cb, SIGUSR1);
ASSERT(r == 0);
r = uv_signal_start(&signal1b, signal1_cb, SIGUSR1);
ASSERT(r == 0);
}
if (mask & SIGUSR2) {

if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) {
r = uv_signal_start(&signal2, signal2_cb, SIGUSR2);
ASSERT(r == 0);
}
@@ -126,11 +140,12 @@ static void signal_handling_worker(void* context) {
ASSERT(r == 0);

/* Close the watchers. */
if (mask & SIGUSR1) {
if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) {
uv_close((uv_handle_t*) &signal1a, NULL);
uv_close((uv_handle_t*) &signal1b, NULL);
}
if (mask & SIGUSR2) {

if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) {
uv_close((uv_handle_t*) &signal2, NULL);
}

@@ -177,10 +192,12 @@ static void loop_creating_worker(void* context) {


TEST_IMPL(signal_multiple_loops) {
int i, r;
uv_thread_t loop_creating_threads[NUM_LOOP_CREATING_THREADS];
uv_thread_t signal_handling_threads[NUM_SIGNAL_HANDLING_THREADS];
enum signal_action action;
sigset_t sigset;
int i;
int r;

r = uv_sem_init(&sem, 0);
ASSERT(r == 0);
@@ -198,17 +215,15 @@ TEST_IMPL(signal_multiple_loops) {

/* Create a couple of threads that actually handle signals. */
for (i = 0; i < NUM_SIGNAL_HANDLING_THREADS; i++) {
uintptr_t mask;

switch (i % 3) {
case 0: mask = SIGUSR1; break;
case 1: mask = SIGUSR2; break;
case 2: mask = SIGUSR1 | SIGUSR2; break;
case 0: action = ONLY_SIGUSR1; break;
case 1: action = ONLY_SIGUSR2; break;
case 2: action = SIGUSR1_AND_SIGUSR2; break;
}

r = uv_thread_create(&signal_handling_threads[i],
signal_handling_worker,
(void*) mask);
(void*) (uintptr_t) action);
ASSERT(r == 0);
}

@@ -256,8 +271,12 @@ TEST_IMPL(signal_multiple_loops) {
printf("signal2_cb calls: %d\n", signal2_cb_counter);
printf("loops created and destroyed: %d\n", loop_creation_counter);

ASSERT(signal1_cb_counter == 4 * NUM_SIGNAL_HANDLING_THREADS);
ASSERT(signal2_cb_counter == 2 * NUM_SIGNAL_HANDLING_THREADS);
/* The division by three reflects the fact that we spawn three different
* thread groups of (NUM_SIGNAL_HANDLING_THREADS / 3) threads each.
*/
ASSERT(signal1_cb_counter == 8 * (NUM_SIGNAL_HANDLING_THREADS / 3));
ASSERT(signal2_cb_counter == 4 * (NUM_SIGNAL_HANDLING_THREADS / 3));

/* We don't know exactly how much loops will be created and destroyed, but at
* least there should be 1 for every loop creating thread.
*/
@@ -113,7 +113,9 @@ static void kill_cb(uv_process_t* process,
ASSERT(err == UV_ESRCH);
}

static void detach_failure_cb(uv_process_t* process, int64_t exit_status, int term_signal) {
static void detach_failure_cb(uv_process_t* process,
int64_t exit_status,
int term_signal) {
printf("detach_cb\n");
exit_cb_called++;
}
@@ -167,7 +169,7 @@ TEST_IMPL(spawn_fails) {
init_process_options("", exit_cb_expect_enoent);
options.file = options.args[0] = "program-that-had-better-not-exist";
ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
ASSERT(0 != uv_is_active((uv_handle_t*)&process));
ASSERT(1 == uv_is_active((uv_handle_t*) &process));
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
ASSERT(1 == exit_cb_called);

@@ -630,7 +632,11 @@ TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) {
options.stdio_count = 2;

/* Create a pipe that'll cause a collision. */
_snprintf(name, sizeof(name), "\\\\.\\pipe\\uv\\%p-%d", &out, GetCurrentProcessId());
_snprintf(name,
sizeof(name),
"\\\\.\\pipe\\uv\\%p-%d",
&out,
GetCurrentProcessId());
pipe_handle = CreateNamedPipeA(name,
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
@@ -729,8 +735,12 @@ TEST_IMPL(argument_escaping) {
wprintf(L" verbatim_output: %s\n", verbatim_output);
wprintf(L"non_verbatim_output: %s\n", non_verbatim_output);

ASSERT(wcscmp(verbatim_output, L"cmd.exe /c c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\"") == 0);
ASSERT(wcscmp(non_verbatim_output, L"cmd.exe /c \"c:\\path\\to\\node.exe --eval \\\"require('c:\\\\path\\\\to\\\\test.js')\\\"\"") == 0);
ASSERT(wcscmp(verbatim_output,
L"cmd.exe /c c:\\path\\to\\node.exe --eval "
L"\"require('c:\\\\path\\\\to\\\\test.js')\"") == 0);
ASSERT(wcscmp(non_verbatim_output,
L"cmd.exe /c \"c:\\path\\to\\node.exe --eval "
L"\\\"require('c:\\\\path\\\\to\\\\test.js')\\\"\"") == 0);

free(verbatim_output);
free(non_verbatim_output);
@@ -758,17 +768,23 @@ TEST_IMPL(environment_creation) {
WCHAR* env;

for (i = 0; i < sizeof(environment) / sizeof(environment[0]) - 1; i++) {
ptr += uv_utf8_to_utf16(environment[i], ptr, expected + sizeof(expected) - ptr);
ptr += uv_utf8_to_utf16(environment[i],
ptr,
expected + sizeof(expected) - ptr);
}

memcpy(ptr, L"SYSTEMROOT=", sizeof(L"SYSTEMROOT="));
ptr += sizeof(L"SYSTEMROOT=")/sizeof(WCHAR) - 1;
ptr += GetEnvironmentVariableW(L"SYSTEMROOT", ptr, expected + sizeof(expected) - ptr);
ptr += GetEnvironmentVariableW(L"SYSTEMROOT",
ptr,
expected + sizeof(expected) - ptr);
++ptr;

memcpy(ptr, L"SYSTEMDRIVE=", sizeof(L"SYSTEMDRIVE="));
ptr += sizeof(L"SYSTEMDRIVE=")/sizeof(WCHAR) - 1;
ptr += GetEnvironmentVariableW(L"SYSTEMDRIVE", ptr, expected + sizeof(expected) - ptr);
ptr += GetEnvironmentVariableW(L"SYSTEMDRIVE",
ptr,
expected + sizeof(expected) - ptr);
++ptr;
*ptr = '\0';

@@ -946,7 +962,7 @@ TEST_IMPL(spawn_auto_unref) {
ASSERT(0 == uv_is_closing((uv_handle_t*) &process));
uv_close((uv_handle_t*) &process, NULL);
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
ASSERT(0 != uv_is_closing((uv_handle_t*) &process));
ASSERT(1 == uv_is_closing((uv_handle_t*) &process));
MAKE_VALGRIND_HAPPY();
return 0;
}
@@ -43,7 +43,6 @@ static int output_used;


static void close_cb(uv_handle_t* handle) {
printf("close_cb\n");
close_cb_called++;
}

@@ -116,7 +116,8 @@ TEST_IMPL(tcp_bind_error_addrnotavail_2) {


TEST_IMPL(tcp_bind_error_fault) {
char garbage[] = "blah blah blah blah blah blah blah blah blah blah blah blah";
char garbage[] =
"blah blah blah blah blah blah blah blah blah blah blah blah";
struct sockaddr_in* garbage_addr;
uv_tcp_t server;
int r;
@@ -92,7 +92,8 @@ TEST_IMPL(tcp_bind6_error_addrnotavail) {


TEST_IMPL(tcp_bind6_error_fault) {
char garbage[] = "blah blah blah blah blah blah blah blah blah blah blah blah";
char garbage[] =
"blah blah blah blah blah blah blah blah blah blah blah blah";
struct sockaddr_in6* garbage_addr;
uv_tcp_t server;
int r;
@@ -57,7 +57,7 @@ static void repeat_1_cb(uv_timer_t* handle, int status) {
r = uv_timer_again(&repeat_2);
ASSERT(r == 0);

if (uv_now(uv_default_loop()) >= start_time + 500) {
if (repeat_1_cb_called == 10) {
uv_close((uv_handle_t*)handle, close_cb);
/* We're not calling uv_timer_again on repeat_2 any more, so after this */
/* timer_2_cb is expected. */
@@ -78,7 +78,7 @@ static void repeat_2_cb(uv_timer_t* handle, int status) {
repeat_2_cb_called++;

if (uv_timer_get_repeat(&repeat_2) == 0) {
ASSERT(!uv_is_active((uv_handle_t*)handle));
ASSERT(0 == uv_is_active((uv_handle_t*) handle));
uv_close((uv_handle_t*)handle, close_cb);
return;
}
@@ -134,7 +134,6 @@ TEST_IMPL(timer_again) {

LOGF("Test took %ld ms (expected ~700 ms)\n",
(long int)(uv_now(uv_default_loop()) - start_time));
ASSERT(700 <= uv_now(uv_default_loop()) - start_time);

MAKE_VALGRIND_HAPPY();
return 0;
@@ -38,7 +38,7 @@ static void once_close_cb(uv_handle_t* handle) {
printf("ONCE_CLOSE_CB\n");

ASSERT(handle != NULL);
ASSERT(!uv_is_active(handle));
ASSERT(0 == uv_is_active(handle));

once_close_cb_called++;
}
@@ -49,7 +49,7 @@ static void once_cb(uv_timer_t* handle, int status) {

ASSERT(handle != NULL);
ASSERT(status == 0);
ASSERT(!uv_is_active((uv_handle_t*)handle));
ASSERT(0 == uv_is_active((uv_handle_t*) handle));

once_cb_called++;

@@ -74,7 +74,7 @@ static void repeat_cb(uv_timer_t* handle, int status) {

ASSERT(handle != NULL);
ASSERT(status == 0);
ASSERT(uv_is_active((uv_handle_t*)handle));
ASSERT(1 == uv_is_active((uv_handle_t*) handle));

repeat_cb_called++;

@@ -163,7 +163,7 @@ TEST_IMPL(timer_init) {

ASSERT(0 == uv_timer_init(uv_default_loop(), &handle));
ASSERT(0 == uv_timer_get_repeat(&handle));
ASSERT(!uv_is_active((uv_handle_t*)&handle));
ASSERT(0 == uv_is_active((uv_handle_t*) &handle));

MAKE_VALGRIND_HAPPY();
return 0;
@@ -65,12 +65,16 @@ TEST_IMPL(tty) {

#else /* unix */
ttyin_fd = open("/dev/tty", O_RDONLY, 0);
if (ttyin_fd < 0)
if (ttyin_fd < 0) {
LOGF("Cannot open /dev/tty as read-only: %s\n", strerror(errno));
return TEST_SKIP;
}

ttyout_fd = open("/dev/tty", O_WRONLY, 0);
if (ttyout_fd < 0)
if (ttyout_fd < 0) {
LOGF("Cannot open /dev/tty as write-only: %s\n", strerror(errno));
return TEST_SKIP;
}
#endif

ASSERT(ttyin_fd >= 0);
@@ -54,7 +54,7 @@ static void alloc_cb(uv_handle_t* handle,

static void close_cb(uv_handle_t* handle) {
CHECK_HANDLE(handle);
ASSERT(uv_is_closing(handle));
ASSERT(1 == uv_is_closing(handle));
close_cb_called++;
}

@@ -134,6 +134,7 @@
'include/uv-darwin.h',
'include/uv-bsd.h',
'src/unix/async.c',
'src/unix/atomic-ops.h',
'src/unix/core.c',
'src/unix/dl.c',
'src/unix/fs.c',
@@ -145,6 +146,7 @@
'src/unix/poll.c',
'src/unix/process.c',
'src/unix/signal.c',
'src/unix/spinlock.h',
'src/unix/stream.c',
'src/unix/tcp.c',
'src/unix/thread.c',
@@ -297,6 +299,7 @@
'test/test-async-null-cb.c',
'test/test-callback-stack.c',
'test/test-callback-order.c',
'test/test-close-order.c',
'test/test-connection-fail.c',
'test/test-cwd-and-chdir.c',
'test/test-delayed-accept.c',
@@ -108,17 +108,21 @@ void FSEventWrap::Start(const FunctionCallbackInfo<Value>& args) {

String::Utf8Value path(args[0]);

int err = uv_fs_event_init(wrap->env()->event_loop(),
&wrap->handle_,
*path,
OnEvent,
0);
int err = uv_fs_event_init(wrap->env()->event_loop(), &wrap->handle_);

if (err == 0) {
// Check for persistent argument
if (!args[1]->IsTrue()) {
uv_unref(reinterpret_cast<uv_handle_t*>(&wrap->handle_));
}
wrap->initialized_ = true;

err = uv_fs_event_start(&wrap->handle_, OnEvent, *path, 0);

if (err == 0) {
// Check for persistent argument
if (!args[1]->IsTrue()) {
uv_unref(reinterpret_cast<uv_handle_t*>(&wrap->handle_));
}
} else {
FSEventWrap::Close(args);
}
}

args.GetReturnValue().Set(err);