unix,windows: allow NULL loop for sync fs requests

Synchronous file operations don't need an event loop.  Permit NULL as
the event loop parameter.

Fixes: https://github.com/libuv/libuv/issues/469
PR-URL: https://github.com/libuv/libuv/pull/479
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
Ben Noordhuis 2015-08-17 02:05:23 +02:00
parent 54eecf32a9
commit df62b54aa2
7 changed files with 237 additions and 243 deletions

View File

@ -58,10 +58,12 @@
# include <sys/sendfile.h>
#endif
#define INIT(type) \
#define INIT(subtype) \
do { \
uv__req_init(loop, req, UV_FS); \
req->fs_type = UV_FS_ ## type; \
req->type = UV_FS; \
if (cb != NULL) \
uv__req_init(loop, req, UV_FS); \
req->fs_type = UV_FS_ ## subtype; \
req->result = 0; \
req->ptr = NULL; \
req->loop = loop; \
@ -112,7 +114,6 @@
} \
else { \
uv__fs_work(&req->work_req); \
uv__fs_done(&req->work_req, 0); \
return req->result; \
} \
} \
@ -896,8 +897,7 @@ static void uv__fs_done(struct uv__work* w, int status) {
req->result = -ECANCELED;
}
if (req->cb != NULL)
req->cb(req);
req->cb(req);
}

View File

@ -116,8 +116,8 @@ void uv_fs_init() {
}
INLINE static int fs__capture_path(uv_loop_t* loop, uv_fs_t* req,
const char* path, const char* new_path, const int copy_path) {
INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
const char* new_path, const int copy_path) {
char* buf;
char* pos;
ssize_t buf_sz = 0, path_len, pathw_len = 0, new_pathw_len = 0;
@ -1762,8 +1762,7 @@ static void uv__fs_done(struct uv__work* w, int status) {
req->result = UV_ECANCELED;
}
if (req->cb != NULL)
req->cb(req);
req->cb(req);
}
@ -1792,7 +1791,7 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
uv_fs_req_init(loop, req, UV_FS_OPEN, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -1902,7 +1901,7 @@ int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_req_init(loop, req, UV_FS_UNLINK, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -1923,7 +1922,7 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
uv_fs_req_init(loop, req, UV_FS_MKDIR, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -1946,7 +1945,7 @@ int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl,
uv_fs_req_init(loop, req, UV_FS_MKDTEMP, cb);
err = fs__capture_path(loop, req, tpl, NULL, TRUE);
err = fs__capture_path(req, tpl, NULL, TRUE);
if (err)
return uv_translate_sys_error(err);
@ -1965,7 +1964,7 @@ int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
uv_fs_req_init(loop, req, UV_FS_RMDIR, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -1986,7 +1985,7 @@ int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
uv_fs_req_init(loop, req, UV_FS_SCANDIR, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -2009,7 +2008,7 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_req_init(loop, req, UV_FS_LINK, cb);
err = fs__capture_path(loop, req, path, new_path, cb != NULL);
err = fs__capture_path(req, path, new_path, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -2030,7 +2029,7 @@ int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_req_init(loop, req, UV_FS_SYMLINK, cb);
err = fs__capture_path(loop, req, path, new_path, cb != NULL);
err = fs__capture_path(req, path, new_path, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -2053,7 +2052,7 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_req_init(loop, req, UV_FS_READLINK, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -2074,7 +2073,7 @@ int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
uv_fs_req_init(loop, req, UV_FS_CHOWN, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -2108,7 +2107,7 @@ int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
uv_fs_req_init(loop, req, UV_FS_STAT, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -2128,7 +2127,7 @@ int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
uv_fs_req_init(loop, req, UV_FS_LSTAT, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -2163,7 +2162,7 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_req_init(loop, req, UV_FS_RENAME, cb);
err = fs__capture_path(loop, req, path, new_path, cb != NULL);
err = fs__capture_path(req, path, new_path, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -2252,7 +2251,7 @@ int uv_fs_access(uv_loop_t* loop,
uv_fs_req_init(loop, req, UV_FS_ACCESS, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err)
return uv_translate_sys_error(err);
@ -2274,7 +2273,7 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
uv_fs_req_init(loop, req, UV_FS_CHMOD, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
@ -2314,7 +2313,7 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
uv_fs_req_init(loop, req, UV_FS_UTIME, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}

View File

@ -31,7 +31,7 @@
#define sync_stat(req, path) \
do { \
uv_fs_stat(uv_default_loop(), (req), (path), NULL); \
uv_fs_stat(NULL, (req), (path), NULL); \
uv_fs_req_cleanup((req)); \
} \
while (0)

View File

@ -304,7 +304,7 @@ static int pipe_echo_start(char* pipeName) {
#ifndef _WIN32
{
uv_fs_t req;
uv_fs_unlink(uv_default_loop(), &req, pipeName, NULL);
uv_fs_unlink(NULL, &req, pipeName, NULL);
uv_fs_req_cleanup(&req);
}
#endif

View File

@ -56,46 +56,45 @@ static int timer_cb_touch_called;
static void fs_event_unlink_files(uv_timer_t* handle);
static void fs_event_unlink_files_in_subdir(uv_timer_t* handle);
static void create_dir(uv_loop_t* loop, const char* name) {
static void create_dir(const char* name) {
int r;
uv_fs_t req;
r = uv_fs_mkdir(loop, &req, name, 0755, NULL);
r = uv_fs_mkdir(NULL, &req, name, 0755, NULL);
ASSERT(r == 0 || r == UV_EEXIST);
uv_fs_req_cleanup(&req);
}
static void create_file(uv_loop_t* loop, const char* name) {
static void create_file(const char* name) {
int r;
uv_file file;
uv_fs_t req;
r = uv_fs_open(loop, &req, name, O_WRONLY | O_CREAT,
S_IWUSR | S_IRUSR, NULL);
r = uv_fs_open(NULL, &req, name, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, NULL);
ASSERT(r >= 0);
file = r;
uv_fs_req_cleanup(&req);
r = uv_fs_close(loop, &req, file, NULL);
r = uv_fs_close(NULL, &req, file, NULL);
ASSERT(r == 0);
uv_fs_req_cleanup(&req);
}
static void touch_file(uv_loop_t* loop, const char* name) {
static void touch_file(const char* name) {
int r;
uv_file file;
uv_fs_t req;
uv_buf_t buf;
r = uv_fs_open(loop, &req, name, O_RDWR, 0, NULL);
r = uv_fs_open(NULL, &req, name, O_RDWR, 0, NULL);
ASSERT(r >= 0);
file = r;
uv_fs_req_cleanup(&req);
buf = uv_buf_init("foo", 4);
r = uv_fs_write(loop, &req, file, &buf, 1, -1, NULL);
r = uv_fs_write(NULL, &req, file, &buf, 1, -1, NULL);
ASSERT(r >= 0);
uv_fs_req_cleanup(&req);
r = uv_fs_close(loop, &req, file, NULL);
r = uv_fs_close(NULL, &req, file, NULL);
ASSERT(r == 0);
uv_fs_req_cleanup(&req);
}
@ -192,7 +191,7 @@ static void fs_event_create_files(uv_timer_t* handle) {
/* Create all files */
for (i = 0; i < 16; i++, fs_event_created++)
create_file(handle->loop, fs_event_get_filename(i));
create_file(fs_event_get_filename(i));
/* And unlink them */
ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files, 50, 0));
@ -209,7 +208,7 @@ static void fs_event_create_files_in_subdir(uv_timer_t* handle) {
/* Create all files */
for (i = 0; i < 16; i++, fs_event_created++)
create_file(handle->loop, fs_event_get_filename_in_subdir(i));
create_file(fs_event_get_filename_in_subdir(i));
/* And unlink them */
ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files_in_subdir, 50, 0));
@ -295,16 +294,16 @@ static void timer_cb_file(uv_timer_t* handle) {
++timer_cb_called;
if (timer_cb_called == 1) {
touch_file(handle->loop, "watch_dir/file1");
touch_file("watch_dir/file1");
} else {
touch_file(handle->loop, "watch_dir/file2");
touch_file("watch_dir/file2");
uv_close((uv_handle_t*)handle, close_cb);
}
}
static void timer_cb_touch(uv_timer_t* timer) {
uv_close((uv_handle_t*)timer, NULL);
touch_file(timer->loop, "watch_file");
touch_file("watch_file");
timer_cb_touch_called++;
}
@ -324,7 +323,7 @@ TEST_IMPL(fs_event_watch_dir) {
remove("watch_dir/file2");
remove("watch_dir/file1");
remove("watch_dir/");
create_dir(loop, "watch_dir");
create_dir("watch_dir");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
@ -363,8 +362,8 @@ TEST_IMPL(fs_event_watch_dir_recursive) {
remove("watch_dir/file1");
remove("watch_dir/subdir");
remove("watch_dir/");
create_dir(loop, "watch_dir");
create_dir(loop, "watch_dir/subdir");
create_dir("watch_dir");
create_dir("watch_dir/subdir");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
@ -404,9 +403,9 @@ TEST_IMPL(fs_event_watch_file) {
remove("watch_dir/file2");
remove("watch_dir/file1");
remove("watch_dir/");
create_dir(loop, "watch_dir");
create_file(loop, "watch_dir/file1");
create_file(loop, "watch_dir/file2");
create_dir("watch_dir");
create_file("watch_dir/file1");
create_file("watch_dir/file2");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
@ -462,7 +461,7 @@ TEST_IMPL(fs_event_watch_file_current_dir) {
/* Setup */
remove("watch_file");
create_file(loop, "watch_file");
create_file("watch_file");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
@ -503,8 +502,8 @@ TEST_IMPL(fs_event_no_callback_after_close) {
/* Setup */
remove("watch_dir/file1");
remove("watch_dir/");
create_dir(loop, "watch_dir");
create_file(loop, "watch_dir/file1");
create_dir("watch_dir");
create_file("watch_dir/file1");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
@ -516,7 +515,7 @@ TEST_IMPL(fs_event_no_callback_after_close) {
uv_close((uv_handle_t*)&fs_event, close_cb);
touch_file(loop, "watch_dir/file1");
touch_file("watch_dir/file1");
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(fs_event_cb_called == 0);
@ -537,8 +536,8 @@ TEST_IMPL(fs_event_no_callback_on_close) {
/* Setup */
remove("watch_dir/file1");
remove("watch_dir/");
create_dir(loop, "watch_dir");
create_file(loop, "watch_dir/file1");
create_dir("watch_dir");
create_file("watch_dir/file1");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
@ -611,8 +610,8 @@ TEST_IMPL(fs_event_close_with_pending_event) {
loop = uv_default_loop();
create_dir(loop, "watch_dir");
create_file(loop, "watch_dir/file");
create_dir("watch_dir");
create_file("watch_dir/file");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
@ -620,7 +619,7 @@ TEST_IMPL(fs_event_close_with_pending_event) {
ASSERT(r == 0);
/* Generate an fs event. */
touch_file(loop, "watch_dir/file");
touch_file("watch_dir/file");
uv_close((uv_handle_t*)&fs_event, close_cb);
@ -668,12 +667,12 @@ TEST_IMPL(fs_event_close_in_callback) {
loop = uv_default_loop();
create_dir(loop, "watch_dir");
create_file(loop, "watch_dir/file1");
create_file(loop, "watch_dir/file2");
create_file(loop, "watch_dir/file3");
create_file(loop, "watch_dir/file4");
create_file(loop, "watch_dir/file5");
create_dir("watch_dir");
create_file("watch_dir/file1");
create_file("watch_dir/file2");
create_file("watch_dir/file3");
create_file("watch_dir/file4");
create_file("watch_dir/file5");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
@ -681,11 +680,11 @@ TEST_IMPL(fs_event_close_in_callback) {
ASSERT(r == 0);
/* Generate a couple of fs events. */
touch_file(loop, "watch_dir/file1");
touch_file(loop, "watch_dir/file2");
touch_file(loop, "watch_dir/file3");
touch_file(loop, "watch_dir/file4");
touch_file(loop, "watch_dir/file5");
touch_file("watch_dir/file1");
touch_file("watch_dir/file2");
touch_file("watch_dir/file3");
touch_file("watch_dir/file4");
touch_file("watch_dir/file5");
uv_run(loop, UV_RUN_DEFAULT);
@ -714,7 +713,7 @@ TEST_IMPL(fs_event_start_and_close) {
loop = uv_default_loop();
create_dir(loop, "watch_dir");
create_dir("watch_dir");
r = uv_fs_event_init(loop, &fs_event1);
ASSERT(r == 0);
@ -744,7 +743,7 @@ TEST_IMPL(fs_event_getpath) {
char buf[1024];
size_t len;
create_dir(loop, "watch_dir");
create_dir("watch_dir");
r = uv_fs_event_init(loop, &fs_event);
ASSERT(r == 0);
@ -806,7 +805,7 @@ TEST_IMPL(fs_event_error_reporting) {
TEST_FILE_LIMIT(ARRAY_SIZE(loops) * 3);
remove("watch_dir/");
create_dir(uv_default_loop(), "watch_dir");
create_dir("watch_dir");
/* Create a lot of loops, and start FSEventStream in each of them.
* Eventually, this should create enough streams to make FSEventStreamStart()

File diff suppressed because it is too large Load Diff

View File

@ -277,7 +277,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,
r = uv_fs_open(NULL, &fs_req, "stdout_file", O_CREAT | O_RDWR,
S_IRUSR | S_IWUSR, NULL);
ASSERT(r != -1);
uv_fs_req_cleanup(&fs_req);
@ -300,11 +300,11 @@ TEST_IMPL(spawn_stdout_to_file) {
ASSERT(close_cb_called == 1);
buf = uv_buf_init(output, sizeof(output));
r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL);
r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL);
ASSERT(r == 12);
uv_fs_req_cleanup(&fs_req);
r = uv_fs_close(uv_default_loop(), &fs_req, file, NULL);
r = uv_fs_close(NULL, &fs_req, file, NULL);
ASSERT(r == 0);
uv_fs_req_cleanup(&fs_req);
@ -331,7 +331,7 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file) {
init_process_options("spawn_helper6", exit_cb);
r = uv_fs_open(uv_default_loop(), &fs_req, "stdout_file", O_CREAT | O_RDWR,
r = uv_fs_open(NULL, &fs_req, "stdout_file", O_CREAT | O_RDWR,
S_IRUSR | S_IWUSR, NULL);
ASSERT(r != -1);
uv_fs_req_cleanup(&fs_req);
@ -356,11 +356,11 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file) {
ASSERT(close_cb_called == 1);
buf = uv_buf_init(output, sizeof(output));
r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL);
r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL);
ASSERT(r == 27);
uv_fs_req_cleanup(&fs_req);
r = uv_fs_close(uv_default_loop(), &fs_req, file, NULL);
r = uv_fs_close(NULL, &fs_req, file, NULL);
ASSERT(r == 0);
uv_fs_req_cleanup(&fs_req);
@ -389,7 +389,7 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file2) {
init_process_options("spawn_helper6", exit_cb);
/* Replace stderr with our file */
r = uv_fs_open(uv_default_loop(),
r = uv_fs_open(NULL,
&fs_req,
"stdout_file",
O_CREAT | O_RDWR,
@ -418,11 +418,11 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file2) {
ASSERT(close_cb_called == 1);
buf = uv_buf_init(output, sizeof(output));
r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL);
r = uv_fs_read(NULL, &fs_req, file, &buf, 1, 0, NULL);
ASSERT(r == 27);
uv_fs_req_cleanup(&fs_req);
r = uv_fs_close(uv_default_loop(), &fs_req, file, NULL);
r = uv_fs_close(NULL, &fs_req, file, NULL);
ASSERT(r == 0);
uv_fs_req_cleanup(&fs_req);
@ -456,7 +456,7 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file_swap) {
init_process_options("spawn_helper6", exit_cb);
/* open 'stdout_file' and replace STDOUT_FILENO with it */
r = uv_fs_open(uv_default_loop(),
r = uv_fs_open(NULL,
&fs_req,
"stdout_file",
O_CREAT | O_RDWR,
@ -468,7 +468,7 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file_swap) {
ASSERT(stdout_file != -1);
/* open 'stderr_file' and replace STDERR_FILENO with it */
r = uv_fs_open(uv_default_loop(), &fs_req, "stderr_file", O_CREAT | O_RDWR,
r = uv_fs_open(NULL, &fs_req, "stderr_file", O_CREAT | O_RDWR,
S_IRUSR | S_IWUSR, NULL);
ASSERT(r != -1);
uv_fs_req_cleanup(&fs_req);
@ -497,11 +497,11 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file_swap) {
buf = uv_buf_init(output, sizeof(output));
/* check the content of stdout_file */
r = uv_fs_read(uv_default_loop(), &fs_req, stdout_file, &buf, 1, 0, NULL);
r = uv_fs_read(NULL, &fs_req, stdout_file, &buf, 1, 0, NULL);
ASSERT(r >= 15);
uv_fs_req_cleanup(&fs_req);
r = uv_fs_close(uv_default_loop(), &fs_req, stdout_file, NULL);
r = uv_fs_close(NULL, &fs_req, stdout_file, NULL);
ASSERT(r == 0);
uv_fs_req_cleanup(&fs_req);
@ -509,11 +509,11 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file_swap) {
ASSERT(strncmp("hello errworld\n", output, 15) == 0);
/* check the content of stderr_file */
r = uv_fs_read(uv_default_loop(), &fs_req, stderr_file, &buf, 1, 0, NULL);
r = uv_fs_read(NULL, &fs_req, stderr_file, &buf, 1, 0, NULL);
ASSERT(r >= 12);
uv_fs_req_cleanup(&fs_req);
r = uv_fs_close(uv_default_loop(), &fs_req, stderr_file, NULL);
r = uv_fs_close(NULL, &fs_req, stderr_file, NULL);
ASSERT(r == 0);
uv_fs_req_cleanup(&fs_req);
@ -1399,7 +1399,7 @@ TEST_IMPL(spawn_fs_open) {
uv_buf_t buf;
uv_stdio_container_t stdio[1];
fd = uv_fs_open(uv_default_loop(), &fs_req, "/dev/null", O_RDWR, 0, NULL);
fd = uv_fs_open(NULL, &fs_req, "/dev/null", O_RDWR, 0, NULL);
ASSERT(fd >= 0);
uv_fs_req_cleanup(&fs_req);
@ -1418,7 +1418,7 @@ TEST_IMPL(spawn_fs_open) {
ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb));
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
ASSERT(0 == uv_fs_close(uv_default_loop(), &fs_req, fd, NULL));
ASSERT(0 == uv_fs_close(NULL, &fs_req, fd, NULL));
ASSERT(exit_cb_called == 1);
ASSERT(close_cb_called == 2); /* One for `in`, one for process */