Browse Source

uv: upgrade to cc91989

Ben Noordhuis 13 years ago
parent
commit
94b0481a56
  1. 5
      deps/uv/include/uv-private/uv-win.h
  2. 6
      deps/uv/src/unix/core.c
  3. 26
      deps/uv/src/unix/fs.c
  4. 133
      deps/uv/src/win/process.c
  5. 155
      deps/uv/test/test-fs.c
  6. 6
      deps/uv/test/test-list.h

5
deps/uv/include/uv-private/uv-win.h

@ -235,10 +235,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
struct uv_process_close_s { \ struct uv_process_close_s { \
UV_REQ_FIELDS \ UV_REQ_FIELDS \
} close_req; \ } close_req; \
struct uv_process_stdio_s { \ HANDLE child_stdio[3]; \
uv_pipe_t* server_pipe; \
HANDLE child_pipe; \
} stdio_pipes[3]; \
int exit_signal; \ int exit_signal; \
DWORD spawn_errno; \ DWORD spawn_errno; \
HANDLE wait_handle; \ HANDLE wait_handle; \

6
deps/uv/src/unix/core.c

@ -764,10 +764,8 @@ size_t uv__strlcpy(char* dst, const char* src, size_t size) {
} }
org = src; org = src;
while (size > 1) { while (--size && *src) {
if ((*dst++ = *src++) == '\0') { *dst++ = *src++;
return org - src;
}
} }
*dst = '\0'; *dst = '\0';

26
deps/uv/src/unix/fs.c

@ -472,10 +472,34 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
} }
#if defined(HAVE_FUTIMES)
static int _futime(const uv_file file, double atime, double mtime) {
struct timeval tv[2];
/* FIXME possible loss of precision in floating-point arithmetic? */
tv[0].tv_sec = atime;
tv[0].tv_usec = (unsigned long)(atime * 1000000) % 1000000;
tv[1].tv_sec = mtime;
tv[1].tv_usec = (unsigned long)(mtime * 1000000) % 1000000;
return futimes(file, tv);
}
#endif
int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime,
double mtime, uv_fs_cb cb) { double mtime, uv_fs_cb cb) {
assert(0 && "implement me"); const char* path = NULL;
uv_fs_req_init(loop, req, UV_FS_FUTIME, path, cb);
#if defined(HAVE_FUTIMES)
WRAP_EIO(UV_FS_FUTIME, eio_futime, _futime, ARGS3(file, atime, mtime))
#else
uv_err_new(loop, ENOSYS);
return -1; return -1;
#endif
} }

133
deps/uv/src/win/process.c

@ -61,12 +61,9 @@ static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
handle->wait_handle = INVALID_HANDLE_VALUE; handle->wait_handle = INVALID_HANDLE_VALUE;
handle->process_handle = INVALID_HANDLE_VALUE; handle->process_handle = INVALID_HANDLE_VALUE;
handle->close_handle = INVALID_HANDLE_VALUE; handle->close_handle = INVALID_HANDLE_VALUE;
handle->stdio_pipes[0].server_pipe = NULL; handle->child_stdio[0] = INVALID_HANDLE_VALUE;
handle->stdio_pipes[0].child_pipe = INVALID_HANDLE_VALUE; handle->child_stdio[1] = INVALID_HANDLE_VALUE;
handle->stdio_pipes[1].server_pipe = NULL; handle->child_stdio[2] = INVALID_HANDLE_VALUE;
handle->stdio_pipes[1].child_pipe = INVALID_HANDLE_VALUE;
handle->stdio_pipes[2].server_pipe = NULL;
handle->stdio_pipes[2].child_pipe = INVALID_HANDLE_VALUE;
uv_req_init(loop, (uv_req_t*)&handle->exit_req); uv_req_init(loop, (uv_req_t*)&handle->exit_req);
handle->exit_req.type = UV_PROCESS_EXIT; handle->exit_req.type = UV_PROCESS_EXIT;
@ -625,7 +622,7 @@ static DWORD WINAPI spawn_failure(void* data) {
char unknown[] = "unknown error\n"; char unknown[] = "unknown error\n";
uv_process_t* process = (uv_process_t*) data; uv_process_t* process = (uv_process_t*) data;
uv_loop_t* loop = process->loop; uv_loop_t* loop = process->loop;
HANDLE child_stderr = process->stdio_pipes[2].child_pipe; HANDLE child_stderr = process->child_stdio[2];
char* buf = NULL; char* buf = NULL;
DWORD count, written; DWORD count, written;
@ -657,18 +654,23 @@ static DWORD WINAPI spawn_failure(void* data) {
} }
/* Called on main thread after a child process has exited. */ static void close_child_stdio(uv_process_t* process) {
void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
int i; int i;
DWORD exit_code; HANDLE handle;
/* Close stdio handles. */ for (i = 0; i < COUNTOF(process->child_stdio); i++) {
for (i = 0; i < COUNTOF(handle->stdio_pipes); i++) { handle = process->child_stdio[i];
if (handle->stdio_pipes[i].child_pipe != INVALID_HANDLE_VALUE) { if (handle != NULL && handle != INVALID_HANDLE_VALUE) {
CloseHandle(handle->stdio_pipes[i].child_pipe); CloseHandle(handle);
handle->stdio_pipes[i].child_pipe = INVALID_HANDLE_VALUE; process->child_stdio[i] = INVALID_HANDLE_VALUE;
} }
} }
}
/* Called on main thread after a child process has exited. */
void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
DWORD exit_code;
/* Unregister from process notification. */ /* Unregister from process notification. */
if (handle->wait_handle != INVALID_HANDLE_VALUE) { if (handle->wait_handle != INVALID_HANDLE_VALUE) {
@ -686,6 +688,10 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
CloseHandle(handle->process_handle); CloseHandle(handle->process_handle);
handle->process_handle = INVALID_HANDLE_VALUE; handle->process_handle = INVALID_HANDLE_VALUE;
} else { } else {
/* We probably left the child stdio handles open to report the error */
/* asynchronously, so close them now. */
close_child_stdio(handle);
/* The process never even started in the first place. */ /* The process never even started in the first place. */
exit_code = 127; exit_code = 127;
} }
@ -805,13 +811,45 @@ done:
} }
static int duplicate_std_handle(uv_loop_t* loop, DWORD id, HANDLE* dup) {
HANDLE handle;
HANDLE current_process = GetCurrentProcess();
handle = GetStdHandle(id);
if (handle == NULL) {
*dup = NULL;
return 0;
} else if (handle == INVALID_HANDLE_VALUE) {
*dup = INVALID_HANDLE_VALUE;
uv_set_sys_error(loop, GetLastError());
return -1;
}
if (!DuplicateHandle(current_process,
handle,
current_process,
dup,
0,
TRUE,
DUPLICATE_SAME_ACCESS)) {
*dup = INVALID_HANDLE_VALUE;
uv_set_sys_error(loop, GetLastError());
return -1;
}
return 0;
}
int uv_spawn(uv_loop_t* loop, uv_process_t* process, int uv_spawn(uv_loop_t* loop, uv_process_t* process,
uv_process_options_t options) { uv_process_options_t options) {
int err = 0, i; int err = 0, keep_child_stdio_open = 0;
wchar_t* path; wchar_t* path;
int size; int size;
BOOL result; BOOL result;
wchar_t* application_path, *application, *arguments, *env, *cwd; wchar_t* application_path, *application, *arguments, *env, *cwd;
HANDLE* child_stdio = process->child_stdio;
STARTUPINFOW startup; STARTUPINFOW startup;
PROCESS_INFORMATION info; PROCESS_INFORMATION info;
@ -864,41 +902,41 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
err = uv_create_stdio_pipe_pair( err = uv_create_stdio_pipe_pair(
loop, loop,
options.stdin_stream, options.stdin_stream,
&process->stdio_pipes[0].child_pipe, &child_stdio[0],
PIPE_ACCESS_OUTBOUND, PIPE_ACCESS_OUTBOUND,
GENERIC_READ | FILE_WRITE_ATTRIBUTES); GENERIC_READ | FILE_WRITE_ATTRIBUTES);
if (err) { } else {
goto done; err = duplicate_std_handle(loop, STD_INPUT_HANDLE, &child_stdio[0]);
} }
if (err) {
process->stdio_pipes[0].server_pipe = options.stdin_stream; goto done;
} }
if (options.stdout_stream) { if (options.stdout_stream) {
err = uv_create_stdio_pipe_pair( err = uv_create_stdio_pipe_pair(
loop, options.stdout_stream, loop, options.stdout_stream,
&process->stdio_pipes[1].child_pipe, &child_stdio[1],
PIPE_ACCESS_INBOUND, PIPE_ACCESS_INBOUND,
GENERIC_WRITE); GENERIC_WRITE);
if (err) { } else {
goto done; err = duplicate_std_handle(loop, STD_OUTPUT_HANDLE, &child_stdio[1]);
} }
if (err) {
process->stdio_pipes[1].server_pipe = options.stdout_stream; goto done;
} }
if (options.stderr_stream) { if (options.stderr_stream) {
err = uv_create_stdio_pipe_pair( err = uv_create_stdio_pipe_pair(
loop, loop,
options.stderr_stream, options.stderr_stream,
&process->stdio_pipes[2].child_pipe, &child_stdio[2],
PIPE_ACCESS_INBOUND, PIPE_ACCESS_INBOUND,
GENERIC_WRITE); GENERIC_WRITE);
if (err) { } else {
goto done; err = duplicate_std_handle(loop, STD_ERROR_HANDLE, &child_stdio[2]);
} }
if (err) {
process->stdio_pipes[2].server_pipe = options.stderr_stream; goto done;
} }
startup.cb = sizeof(startup); startup.cb = sizeof(startup);
@ -908,9 +946,9 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
startup.dwFlags = STARTF_USESTDHANDLES; startup.dwFlags = STARTF_USESTDHANDLES;
startup.cbReserved2 = 0; startup.cbReserved2 = 0;
startup.lpReserved2 = NULL; startup.lpReserved2 = NULL;
startup.hStdInput = process->stdio_pipes[0].child_pipe; startup.hStdInput = child_stdio[0];
startup.hStdOutput = process->stdio_pipes[1].child_pipe; startup.hStdOutput = child_stdio[1];
startup.hStdError = process->stdio_pipes[2].child_pipe; startup.hStdError = child_stdio[2];
if (CreateProcessW(application_path, if (CreateProcessW(application_path,
arguments, arguments,
@ -942,6 +980,7 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
/* succeeded, and start a thread instead that prints an error */ /* succeeded, and start a thread instead that prints an error */
/* to the child's intended stderr. */ /* to the child's intended stderr. */
process->spawn_errno = GetLastError(); process->spawn_errno = GetLastError();
keep_child_stdio_open = 1;
if (!QueueUserWorkItem(spawn_failure, process, WT_EXECUTEDEFAULT)) { if (!QueueUserWorkItem(spawn_failure, process, WT_EXECUTEDEFAULT)) {
uv_fatal_error(GetLastError(), "QueueUserWorkItem"); uv_fatal_error(GetLastError(), "QueueUserWorkItem");
} }
@ -957,14 +996,22 @@ done:
free(env); free(env);
free(path); free(path);
if (err) { /* Under normal circumstances we should close the stdio handles now - */
for (i = 0; i < COUNTOF(process->stdio_pipes); i++) { /* the child now has its own duplicates, or something went horribly wrong. */
if (process->stdio_pipes[i].child_pipe != INVALID_HANDLE_VALUE) { /* The only exception is when CreateProcess has failed, then we actually */
CloseHandle(process->stdio_pipes[i].child_pipe); /* need to keep the stdio handles to report the error asynchronously. */
process->stdio_pipes[i].child_pipe = INVALID_HANDLE_VALUE; if (!keep_child_stdio_open) {
} close_child_stdio(process);
} else {
/* We're keeping the handles open, the thread pool is going to have */
/* it's way with them. But at least make them noninheritable. */
int i;
for (i = 0; i < COUNTOF(process->child_stdio); i++) {
SetHandleInformation(child_stdio[1], HANDLE_FLAG_INHERIT, 0);
} }
}
if (err) {
if (process->wait_handle != INVALID_HANDLE_VALUE) { if (process->wait_handle != INVALID_HANDLE_VALUE) {
UnregisterWait(process->wait_handle); UnregisterWait(process->wait_handle);
process->wait_handle = INVALID_HANDLE_VALUE; process->wait_handle = INVALID_HANDLE_VALUE;

155
deps/uv/test/test-fs.c

@ -43,6 +43,14 @@
# define close _close # define close _close
#endif #endif
typedef struct {
const char* path;
double atime;
double mtime;
} utime_check_t;
static int close_cb_count; static int close_cb_count;
static int create_cb_count; static int create_cb_count;
static int open_cb_count; static int open_cb_count;
@ -66,6 +74,8 @@ static int fchown_cb_count;
static int link_cb_count; static int link_cb_count;
static int symlink_cb_count; static int symlink_cb_count;
static int readlink_cb_count; static int readlink_cb_count;
static int utime_cb_count;
static int futime_cb_count;
static uv_loop_t* loop; static uv_loop_t* loop;
@ -84,6 +94,8 @@ static uv_fs_t fsync_req;
static uv_fs_t fdatasync_req; static uv_fs_t fdatasync_req;
static uv_fs_t ftruncate_req; static uv_fs_t ftruncate_req;
static uv_fs_t sendfile_req; static uv_fs_t sendfile_req;
static uv_fs_t utime_req;
static uv_fs_t futime_req;
static char buf[32]; static char buf[32];
static char test_buf[] = "test-buffer\n"; static char test_buf[] = "test-buffer\n";
@ -395,6 +407,61 @@ TEST_IMPL(fs_file_noent) {
} }
static void check_utime(const char* path, double atime, double mtime) {
struct stat* s;
uv_fs_t req;
int r;
r = uv_fs_stat(loop, &req, path, NULL);
ASSERT(r == 0);
ASSERT(req.result == 0);
s = req.ptr;
#if _WIN32
ASSERT(s->st_atime == atime);
ASSERT(s->st_mtime == mtime);
#else
ASSERT(s->st_atim.tv_sec == atime);
ASSERT(s->st_atim.tv_nsec == 0); /* FIXME check sub-second precision */
ASSERT(s->st_mtim.tv_sec == mtime);
ASSERT(s->st_mtim.tv_nsec == 0); /* FIXME check sub-second precision */
#endif
uv_fs_req_cleanup(&req);
}
static void utime_cb(uv_fs_t* req) {
utime_check_t* c;
ASSERT(req == &utime_req);
ASSERT(req->result == 0);
ASSERT(req->fs_type == UV_FS_UTIME);
c = req->data;
check_utime(c->path, c->atime, c->mtime);
uv_fs_req_cleanup(req);
utime_cb_count++;
}
static void futime_cb(uv_fs_t* req) {
utime_check_t* c;
ASSERT(req == &futime_req);
ASSERT(req->result == 0);
ASSERT(req->fs_type == UV_FS_FUTIME);
c = req->data;
check_utime(c->path, c->atime, c->mtime);
uv_fs_req_cleanup(req);
futime_cb_count++;
}
TEST_IMPL(fs_file_async) { TEST_IMPL(fs_file_async) {
int r; int r;
@ -1103,3 +1170,91 @@ TEST_IMPL(fs_symlink) {
return 0; return 0;
} }
TEST_IMPL(fs_utime) {
utime_check_t checkme;
const char* path = ".";
double atime;
double mtime;
uv_fs_t req;
int r;
uv_init();
loop = uv_default_loop();
atime = mtime = 400497753; /* 1982-09-10 11:22:33 */
r = uv_fs_utime(loop, &req, path, atime, mtime, NULL);
ASSERT(r == 0);
ASSERT(utime_req.result == 0);
uv_fs_req_cleanup(&req);
r = uv_fs_stat(loop, &req, path, NULL);
ASSERT(r == 0);
ASSERT(req.result == 0);
check_utime(path, atime, mtime);
uv_fs_req_cleanup(&req);
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
checkme.path = path;
checkme.atime = atime;
checkme.mtime = mtime;
/* async utime */
utime_req.data = &checkme;
r = uv_fs_utime(loop, &utime_req, path, atime, mtime, utime_cb);
ASSERT(r == 0);
uv_run(loop);
ASSERT(utime_cb_count == 1);
return 0;
}
TEST_IMPL(fs_futime) {
utime_check_t checkme;
const char* path = ".";
double atime;
double mtime;
uv_file file;
uv_fs_t req;
int r;
uv_init();
loop = uv_default_loop();
atime = mtime = 400497753; /* 1982-09-10 11:22:33 */
r = uv_fs_open(loop, &req, path, O_RDONLY, 0, NULL);
ASSERT(r == 0);
ASSERT(req.result != -1);
file = req.result; /* FIXME probably not how it's supposed to be used */
uv_fs_req_cleanup(&req);
r = uv_fs_futime(loop, &req, file, atime, mtime, NULL);
ASSERT(r == 0);
ASSERT(req.result == 0);
uv_fs_req_cleanup(&req);
r = uv_fs_stat(loop, &req, path, NULL);
ASSERT(r == 0);
ASSERT(req.result == 0);
check_utime(path, atime, mtime);
uv_fs_req_cleanup(&req);
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
checkme.atime = atime;
checkme.mtime = mtime;
checkme.path = path;
/* async futime */
futime_req.data = &checkme;
r = uv_fs_futime(loop, &futime_req, file, atime, mtime, futime_cb);
ASSERT(r == 0);
uv_run(loop);
ASSERT(futime_cb_count == 1);
return 0;
}

6
deps/uv/test/test-list.h

@ -82,6 +82,8 @@ TEST_DECLARE (fs_chmod)
TEST_DECLARE (fs_chown) TEST_DECLARE (fs_chown)
TEST_DECLARE (fs_link) TEST_DECLARE (fs_link)
TEST_DECLARE (fs_symlink) TEST_DECLARE (fs_symlink)
TEST_DECLARE (fs_utime)
TEST_DECLARE (fs_futime)
TEST_DECLARE (threadpool_queue_work_simple) TEST_DECLARE (threadpool_queue_work_simple)
#ifdef _WIN32 #ifdef _WIN32
TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows)
@ -189,7 +191,9 @@ TASK_LIST_START
TEST_ENTRY (fs_fstat) TEST_ENTRY (fs_fstat)
TEST_ENTRY (fs_chmod) TEST_ENTRY (fs_chmod)
TEST_ENTRY (fs_chown) TEST_ENTRY (fs_chown)
TEST_ENTRY (fs_link) TEST_ENTRY (fs_utime)
TEST_ENTRY (fs_futime)
TEST_ENTRY (fs_symlink)
TEST_ENTRY (fs_symlink) TEST_ENTRY (fs_symlink)
TEST_ENTRY (threadpool_queue_work_simple) TEST_ENTRY (threadpool_queue_work_simple)

Loading…
Cancel
Save