Merge remote-tracking branch 'origin/v0.6'
Conflicts: src/win/pipe.c test/run-tests.c
This commit is contained in:
commit
e99fba47c8
@ -91,6 +91,8 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
|
|||||||
case WSAEFAULT: return UV_EFAULT;
|
case WSAEFAULT: return UV_EFAULT;
|
||||||
case ERROR_HOST_UNREACHABLE: return UV_EHOSTUNREACH;
|
case ERROR_HOST_UNREACHABLE: return UV_EHOSTUNREACH;
|
||||||
case WSAEHOSTUNREACH: return UV_EHOSTUNREACH;
|
case WSAEHOSTUNREACH: return UV_EHOSTUNREACH;
|
||||||
|
case ERROR_OPERATION_ABORTED: return UV_EINTR;
|
||||||
|
case WSAEINTR: return UV_EINTR;
|
||||||
case ERROR_INVALID_DATA: return UV_EINVAL;
|
case ERROR_INVALID_DATA: return UV_EINVAL;
|
||||||
case WSAEINVAL: return UV_EINVAL;
|
case WSAEINVAL: return UV_EINVAL;
|
||||||
case ERROR_CANT_RESOLVE_FILENAME: return UV_ELOOP;
|
case ERROR_CANT_RESOLVE_FILENAME: return UV_ELOOP;
|
||||||
|
|||||||
@ -547,7 +547,8 @@ static void fs__stat(uv_fs_t* req, const wchar_t* path) {
|
|||||||
req->stat.st_size = ((int64_t) info.nFileSizeHigh << 32) +
|
req->stat.st_size = ((int64_t) info.nFileSizeHigh << 32) +
|
||||||
(int64_t) info.nFileSizeLow;
|
(int64_t) info.nFileSizeLow;
|
||||||
|
|
||||||
req->stat.st_nlink = info.nNumberOfLinks;
|
req->stat.st_nlink = (info.nNumberOfLinks <= SHRT_MAX) ?
|
||||||
|
(short) info.nNumberOfLinks : SHRT_MAX;
|
||||||
|
|
||||||
req->ptr = &req->stat;
|
req->ptr = &req->stat;
|
||||||
req->result = 0;
|
req->result = 0;
|
||||||
|
|||||||
@ -27,9 +27,15 @@
|
|||||||
|
|
||||||
|
|
||||||
uv_handle_type uv_guess_handle(uv_file file) {
|
uv_handle_type uv_guess_handle(uv_file file) {
|
||||||
HANDLE handle = (HANDLE) _get_osfhandle(file);
|
HANDLE handle;
|
||||||
DWORD mode;
|
DWORD mode;
|
||||||
|
|
||||||
|
if (file < 0) {
|
||||||
|
return UV_UNKNOWN_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle = (HANDLE) _get_osfhandle(file);
|
||||||
|
|
||||||
switch (GetFileType(handle)) {
|
switch (GetFileType(handle)) {
|
||||||
case FILE_TYPE_CHAR:
|
case FILE_TYPE_CHAR:
|
||||||
if (GetConsoleMode(handle, &mode)) {
|
if (GetConsoleMode(handle, &mode)) {
|
||||||
@ -85,9 +91,10 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
|
|||||||
tcp = (uv_tcp_t*)handle;
|
tcp = (uv_tcp_t*)handle;
|
||||||
/* If we don't shutdown before calling closesocket, windows will */
|
/* If we don't shutdown before calling closesocket, windows will */
|
||||||
/* silently discard the kernel send buffer and reset the connection. */
|
/* silently discard the kernel send buffer and reset the connection. */
|
||||||
if (!(tcp->flags & UV_HANDLE_SHUT)) {
|
if ((tcp->flags & UV_HANDLE_CONNECTION) &&
|
||||||
|
!(tcp->flags & UV_HANDLE_SHUT)) {
|
||||||
shutdown(tcp->socket, SD_SEND);
|
shutdown(tcp->socket, SD_SEND);
|
||||||
tcp->flags |= UV_HANDLE_SHUT;
|
tcp->flags |= UV_HANDLE_SHUTTING | UV_HANDLE_SHUT;
|
||||||
}
|
}
|
||||||
tcp->flags &= ~(UV_HANDLE_READING | UV_HANDLE_LISTENING);
|
tcp->flags &= ~(UV_HANDLE_READING | UV_HANDLE_LISTENING);
|
||||||
closesocket(tcp->socket);
|
closesocket(tcp->socket);
|
||||||
@ -173,7 +180,7 @@ void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) {
|
|||||||
void uv_process_endgames(uv_loop_t* loop) {
|
void uv_process_endgames(uv_loop_t* loop) {
|
||||||
uv_handle_t* handle;
|
uv_handle_t* handle;
|
||||||
|
|
||||||
while (loop->endgame_handles) {
|
while (loop->endgame_handles && loop->refs > 0) {
|
||||||
handle = loop->endgame_handles;
|
handle = loop->endgame_handles;
|
||||||
loop->endgame_handles = handle->endgame_next;
|
loop->endgame_handles = handle->endgame_next;
|
||||||
|
|
||||||
|
|||||||
120
src/win/pipe.c
120
src/win/pipe.c
@ -98,21 +98,23 @@ static void uv_pipe_connection_init(uv_pipe_t* handle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int open_named_pipe(uv_pipe_t* handle) {
|
static HANDLE open_named_pipe(WCHAR* name, DWORD* duplex_flags) {
|
||||||
|
HANDLE pipeHandle;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Assume that we have a duplex pipe first, so attempt to
|
* Assume that we have a duplex pipe first, so attempt to
|
||||||
* connect with GENERIC_READ | GENERIC_WRITE.
|
* connect with GENERIC_READ | GENERIC_WRITE.
|
||||||
*/
|
*/
|
||||||
handle->handle = CreateFileW(handle->name,
|
pipeHandle = CreateFileW(name,
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
FILE_FLAG_OVERLAPPED,
|
FILE_FLAG_OVERLAPPED,
|
||||||
NULL);
|
NULL);
|
||||||
|
if (pipeHandle != INVALID_HANDLE_VALUE) {
|
||||||
if (handle->handle != INVALID_HANDLE_VALUE) {
|
*duplex_flags = 0;
|
||||||
return 0;
|
return pipeHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -121,7 +123,7 @@ static int open_named_pipe(uv_pipe_t* handle) {
|
|||||||
* as a read-only or write-only.
|
* as a read-only or write-only.
|
||||||
*/
|
*/
|
||||||
if (GetLastError() == ERROR_ACCESS_DENIED) {
|
if (GetLastError() == ERROR_ACCESS_DENIED) {
|
||||||
handle->handle = CreateFileW(handle->name,
|
pipeHandle = CreateFileW(name,
|
||||||
GENERIC_READ | FILE_WRITE_ATTRIBUTES,
|
GENERIC_READ | FILE_WRITE_ATTRIBUTES,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
@ -129,14 +131,14 @@ static int open_named_pipe(uv_pipe_t* handle) {
|
|||||||
FILE_FLAG_OVERLAPPED,
|
FILE_FLAG_OVERLAPPED,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (handle->handle != INVALID_HANDLE_VALUE) {
|
if (pipeHandle != INVALID_HANDLE_VALUE) {
|
||||||
handle->flags |= UV_HANDLE_SHUT;
|
*duplex_flags = UV_HANDLE_SHUTTING;
|
||||||
return 0;
|
return pipeHandle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetLastError() == ERROR_ACCESS_DENIED) {
|
if (GetLastError() == ERROR_ACCESS_DENIED) {
|
||||||
handle->handle = CreateFileW(handle->name,
|
pipeHandle = CreateFileW(name,
|
||||||
GENERIC_WRITE | FILE_READ_ATTRIBUTES,
|
GENERIC_WRITE | FILE_READ_ATTRIBUTES,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
@ -144,13 +146,13 @@ static int open_named_pipe(uv_pipe_t* handle) {
|
|||||||
FILE_FLAG_OVERLAPPED,
|
FILE_FLAG_OVERLAPPED,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (handle->handle != INVALID_HANDLE_VALUE) {
|
if (pipeHandle != INVALID_HANDLE_VALUE) {
|
||||||
handle->flags |= UV_HANDLE_EOF;
|
*duplex_flags = UV_HANDLE_EOF;
|
||||||
return 0;
|
return pipeHandle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -208,7 +210,7 @@ done:
|
|||||||
|
|
||||||
|
|
||||||
static int uv_set_pipe_handle(uv_loop_t* loop, uv_pipe_t* handle,
|
static int uv_set_pipe_handle(uv_loop_t* loop, uv_pipe_t* handle,
|
||||||
HANDLE pipeHandle) {
|
HANDLE pipeHandle, DWORD duplex_flags) {
|
||||||
NTSTATUS nt_status;
|
NTSTATUS nt_status;
|
||||||
IO_STATUS_BLOCK io_status;
|
IO_STATUS_BLOCK io_status;
|
||||||
FILE_MODE_INFORMATION mode_info;
|
FILE_MODE_INFORMATION mode_info;
|
||||||
@ -242,6 +244,9 @@ static int uv_set_pipe_handle(uv_loop_t* loop, uv_pipe_t* handle,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle->handle = pipeHandle;
|
||||||
|
handle->flags |= duplex_flags;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,11 +281,25 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
|
|||||||
IO_STATUS_BLOCK io_status;
|
IO_STATUS_BLOCK io_status;
|
||||||
FILE_PIPE_LOCAL_INFORMATION pipe_info;
|
FILE_PIPE_LOCAL_INFORMATION pipe_info;
|
||||||
|
|
||||||
if (handle->flags & UV_HANDLE_SHUTTING &&
|
if ((handle->flags & UV_HANDLE_CONNECTION) &&
|
||||||
!(handle->flags & UV_HANDLE_SHUT) &&
|
handle->shutdown_req != NULL &&
|
||||||
handle->write_reqs_pending == 0) {
|
handle->write_reqs_pending == 0) {
|
||||||
req = handle->shutdown_req;
|
req = handle->shutdown_req;
|
||||||
|
|
||||||
|
/* Clear the shutdown_req field so we don't go here again. */
|
||||||
|
handle->shutdown_req = NULL;
|
||||||
|
|
||||||
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
|
/* Already closing. Cancel the shutdown. */
|
||||||
|
if (req->cb) {
|
||||||
|
uv__set_sys_error(loop, WSAEINTR);
|
||||||
|
req->cb(req, -1);
|
||||||
|
}
|
||||||
|
uv_unref(loop);
|
||||||
|
DECREASE_PENDING_REQ_COUNT(handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Try to avoid flushing the pipe buffer in the thread pool. */
|
/* Try to avoid flushing the pipe buffer in the thread pool. */
|
||||||
nt_status = pNtQueryInformationFile(handle->handle,
|
nt_status = pNtQueryInformationFile(handle->handle,
|
||||||
&io_status,
|
&io_status,
|
||||||
@ -295,13 +314,12 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
|
|||||||
uv__set_sys_error(loop, pRtlNtStatusToDosError(nt_status));
|
uv__set_sys_error(loop, pRtlNtStatusToDosError(nt_status));
|
||||||
req->cb(req, -1);
|
req->cb(req, -1);
|
||||||
}
|
}
|
||||||
|
uv_unref(loop);
|
||||||
DECREASE_PENDING_REQ_COUNT(handle);
|
DECREASE_PENDING_REQ_COUNT(handle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) {
|
if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) {
|
||||||
handle->flags |= UV_HANDLE_SHUT;
|
|
||||||
|
|
||||||
/* Short-circuit, no need to call FlushFileBuffers. */
|
/* Short-circuit, no need to call FlushFileBuffers. */
|
||||||
uv_insert_pending_req(loop, (uv_req_t*) req);
|
uv_insert_pending_req(loop, (uv_req_t*) req);
|
||||||
return;
|
return;
|
||||||
@ -312,8 +330,6 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
|
|||||||
req,
|
req,
|
||||||
WT_EXECUTELONGFUNCTION);
|
WT_EXECUTELONGFUNCTION);
|
||||||
if (result) {
|
if (result) {
|
||||||
/* Mark the handle as shut now to avoid going through this again. */
|
|
||||||
handle->flags |= UV_HANDLE_SHUT;
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -323,6 +339,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
|
|||||||
uv__set_sys_error(loop, GetLastError());
|
uv__set_sys_error(loop, GetLastError());
|
||||||
req->cb(req, -1);
|
req->cb(req, -1);
|
||||||
}
|
}
|
||||||
|
uv_unref(loop);
|
||||||
DECREASE_PENDING_REQ_COUNT(handle);
|
DECREASE_PENDING_REQ_COUNT(handle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -449,7 +466,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uv_set_pipe_handle(loop, handle, handle->accept_reqs[0].pipeHandle)) {
|
if (uv_set_pipe_handle(loop, handle, handle->accept_reqs[0].pipeHandle, 0)) {
|
||||||
uv__set_sys_error(loop, GetLastError());
|
uv__set_sys_error(loop, GetLastError());
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -476,11 +493,12 @@ error:
|
|||||||
|
|
||||||
|
|
||||||
static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
|
static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
|
||||||
HANDLE pipeHandle = INVALID_HANDLE_VALUE;
|
|
||||||
int errno;
|
int errno;
|
||||||
uv_loop_t* loop;
|
uv_loop_t* loop;
|
||||||
uv_pipe_t* handle;
|
uv_pipe_t* handle;
|
||||||
uv_connect_t* req;
|
uv_connect_t* req;
|
||||||
|
HANDLE pipeHandle = INVALID_HANDLE_VALUE;
|
||||||
|
DWORD duplex_flags;
|
||||||
|
|
||||||
req = (uv_connect_t*) parameter;
|
req = (uv_connect_t*) parameter;
|
||||||
assert(req);
|
assert(req);
|
||||||
@ -493,7 +511,8 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
|
|||||||
/* We wait for the pipe to become available with WaitNamedPipe. */
|
/* We wait for the pipe to become available with WaitNamedPipe. */
|
||||||
while (WaitNamedPipeW(handle->name, 30000)) {
|
while (WaitNamedPipeW(handle->name, 30000)) {
|
||||||
/* The pipe is now available, try to connect. */
|
/* The pipe is now available, try to connect. */
|
||||||
if (open_named_pipe(handle) == 0) {
|
pipeHandle = open_named_pipe(handle->name, &duplex_flags);
|
||||||
|
if (pipeHandle != INVALID_HANDLE_VALUE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,8 +520,7 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pipeHandle != INVALID_HANDLE_VALUE &&
|
if (pipeHandle != INVALID_HANDLE_VALUE &&
|
||||||
!uv_set_pipe_handle(loop, handle, pipeHandle)) {
|
!uv_set_pipe_handle(loop, handle, pipeHandle, duplex_flags)) {
|
||||||
handle->handle = pipeHandle;
|
|
||||||
SET_REQ_SUCCESS(req);
|
SET_REQ_SUCCESS(req);
|
||||||
} else {
|
} else {
|
||||||
SET_REQ_ERROR(req, GetLastError());
|
SET_REQ_ERROR(req, GetLastError());
|
||||||
@ -519,8 +537,8 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
|||||||
const char* name, uv_connect_cb cb) {
|
const char* name, uv_connect_cb cb) {
|
||||||
uv_loop_t* loop = handle->loop;
|
uv_loop_t* loop = handle->loop;
|
||||||
int errno, nameSize;
|
int errno, nameSize;
|
||||||
|
HANDLE pipeHandle = INVALID_HANDLE_VALUE;
|
||||||
handle->handle = INVALID_HANDLE_VALUE;
|
DWORD duplex_flags;
|
||||||
|
|
||||||
uv_req_init(loop, (uv_req_t*) req);
|
uv_req_init(loop, (uv_req_t*) req);
|
||||||
req->type = UV_CONNECT;
|
req->type = UV_CONNECT;
|
||||||
@ -539,7 +557,8 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (open_named_pipe(handle) != 0) {
|
pipeHandle = open_named_pipe(handle->name, &duplex_flags);
|
||||||
|
if (pipeHandle == INVALID_HANDLE_VALUE) {
|
||||||
if (GetLastError() == ERROR_PIPE_BUSY) {
|
if (GetLastError() == ERROR_PIPE_BUSY) {
|
||||||
/* Wait for the server to make a pipe instance available. */
|
/* Wait for the server to make a pipe instance available. */
|
||||||
if (!QueueUserWorkItem(&pipe_connect_thread_proc,
|
if (!QueueUserWorkItem(&pipe_connect_thread_proc,
|
||||||
@ -549,6 +568,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uv_ref(loop);
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -558,15 +578,12 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(handle->handle != INVALID_HANDLE_VALUE);
|
assert(pipeHandle != INVALID_HANDLE_VALUE);
|
||||||
|
|
||||||
/* Ensure that what we just opened is actually a pipe */
|
if (uv_set_pipe_handle(loop,
|
||||||
if (!GetNamedPipeInfo(handle->handle, NULL, NULL, NULL, NULL)) {
|
(uv_pipe_t*) req->handle,
|
||||||
errno = WSAENOTSOCK;
|
pipeHandle,
|
||||||
goto error;
|
duplex_flags)) {
|
||||||
}
|
|
||||||
|
|
||||||
if (uv_set_pipe_handle(loop, (uv_pipe_t*)req->handle, handle->handle)) {
|
|
||||||
errno = GetLastError();
|
errno = GetLastError();
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -574,6 +591,7 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
|
|||||||
SET_REQ_SUCCESS(req);
|
SET_REQ_SUCCESS(req);
|
||||||
uv_insert_pending_req(loop, (uv_req_t*) req);
|
uv_insert_pending_req(loop, (uv_req_t*) req);
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
|
uv_ref(loop);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@ -582,15 +600,15 @@ error:
|
|||||||
handle->name = NULL;
|
handle->name = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle->handle != INVALID_HANDLE_VALUE) {
|
if (pipeHandle != INVALID_HANDLE_VALUE) {
|
||||||
CloseHandle(handle->handle);
|
CloseHandle(pipeHandle);
|
||||||
handle->handle = INVALID_HANDLE_VALUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make this req pending reporting an error. */
|
/* Make this req pending reporting an error. */
|
||||||
SET_REQ_ERROR(req, errno);
|
SET_REQ_ERROR(req, errno);
|
||||||
uv_insert_pending_req(loop, (uv_req_t*) req);
|
uv_insert_pending_req(loop, (uv_req_t*) req);
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
|
uv_ref(loop);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,6 +635,7 @@ void close_pipe(uv_pipe_t* handle, int* status, uv_err_t* err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (handle->flags & UV_HANDLE_CONNECTION) {
|
if (handle->flags & UV_HANDLE_CONNECTION) {
|
||||||
|
handle->flags |= UV_HANDLE_SHUTTING;
|
||||||
eof_timer_destroy(handle);
|
eof_timer_destroy(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,8 +644,6 @@ void close_pipe(uv_pipe_t* handle, int* status, uv_err_t* err) {
|
|||||||
CloseHandle(handle->handle);
|
CloseHandle(handle->handle);
|
||||||
handle->handle = INVALID_HANDLE_VALUE;
|
handle->handle = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle->flags |= UV_HANDLE_SHUT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -649,7 +666,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uv_set_pipe_handle(loop, handle, req->pipeHandle)) {
|
if (uv_set_pipe_handle(loop, handle, req->pipeHandle, 0)) {
|
||||||
CloseHandle(req->pipeHandle);
|
CloseHandle(req->pipeHandle);
|
||||||
req->pipeHandle = INVALID_HANDLE_VALUE;
|
req->pipeHandle = INVALID_HANDLE_VALUE;
|
||||||
SET_REQ_ERROR(req, GetLastError());
|
SET_REQ_ERROR(req, GetLastError());
|
||||||
@ -1129,10 +1146,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req,
|
|||||||
handle->write_queue_size += req->queued_bytes;
|
handle->write_queue_size += req->queued_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle->write_reqs_pending == 0) {
|
|
||||||
uv_ref(loop);
|
uv_ref(loop);
|
||||||
}
|
|
||||||
|
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
handle->write_reqs_pending++;
|
handle->write_reqs_pending++;
|
||||||
|
|
||||||
@ -1187,10 +1201,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle->write_reqs_pending == 0) {
|
|
||||||
uv_ref(loop);
|
uv_ref(loop);
|
||||||
}
|
|
||||||
|
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
handle->write_reqs_pending++;
|
handle->write_reqs_pending++;
|
||||||
|
|
||||||
@ -1446,15 +1457,12 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
|
|||||||
uv_queue_non_overlapped_write(handle);
|
uv_queue_non_overlapped_write(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle->write_reqs_pending == 0) {
|
|
||||||
uv_unref(loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle->write_reqs_pending == 0 &&
|
if (handle->write_reqs_pending == 0 &&
|
||||||
handle->flags & UV_HANDLE_SHUTTING) {
|
handle->flags & UV_HANDLE_SHUTTING) {
|
||||||
uv_want_endgame(loop, (uv_handle_t*)handle);
|
uv_want_endgame(loop, (uv_handle_t*)handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uv_unref(loop);
|
||||||
DECREASE_PENDING_REQ_COUNT(handle);
|
DECREASE_PENDING_REQ_COUNT(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1501,6 +1509,7 @@ void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uv_unref(loop);
|
||||||
DECREASE_PENDING_REQ_COUNT(handle);
|
DECREASE_PENDING_REQ_COUNT(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1525,6 +1534,7 @@ void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
|
|||||||
req->cb(req, 0);
|
req->cb(req, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uv_unref(loop);
|
||||||
DECREASE_PENDING_REQ_COUNT(handle);
|
DECREASE_PENDING_REQ_COUNT(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1540,6 +1550,7 @@ static void eof_timer_init(uv_pipe_t* pipe) {
|
|||||||
r = uv_timer_init(pipe->loop, pipe->eof_timer);
|
r = uv_timer_init(pipe->loop, pipe->eof_timer);
|
||||||
assert(r == 0); /* timers can't fail */
|
assert(r == 0); /* timers can't fail */
|
||||||
pipe->eof_timer->data = pipe;
|
pipe->eof_timer->data = pipe;
|
||||||
|
uv_unref(pipe->loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1602,6 +1613,7 @@ static void eof_timer_destroy(uv_pipe_t* pipe) {
|
|||||||
assert(pipe->flags && UV_HANDLE_CONNECTION);
|
assert(pipe->flags && UV_HANDLE_CONNECTION);
|
||||||
|
|
||||||
if (pipe->eof_timer) {
|
if (pipe->eof_timer) {
|
||||||
|
uv_ref(pipe->loop);
|
||||||
uv_close((uv_handle_t*) pipe->eof_timer, eof_timer_close_cb);
|
uv_close((uv_handle_t*) pipe->eof_timer, eof_timer_close_cb);
|
||||||
pipe->eof_timer = NULL;
|
pipe->eof_timer = NULL;
|
||||||
}
|
}
|
||||||
@ -1618,7 +1630,7 @@ void uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
|
|||||||
HANDLE os_handle = (HANDLE)_get_osfhandle(file);
|
HANDLE os_handle = (HANDLE)_get_osfhandle(file);
|
||||||
|
|
||||||
if (os_handle == INVALID_HANDLE_VALUE ||
|
if (os_handle == INVALID_HANDLE_VALUE ||
|
||||||
uv_set_pipe_handle(pipe->loop, pipe, os_handle) == -1) {
|
uv_set_pipe_handle(pipe->loop, pipe, os_handle, 0) == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -47,6 +47,8 @@ void uv_connection_init(uv_stream_t* handle) {
|
|||||||
handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
|
handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
|
||||||
handle->read_req.type = UV_READ;
|
handle->read_req.type = UV_READ;
|
||||||
handle->read_req.data = handle;
|
handle->read_req.data = handle;
|
||||||
|
|
||||||
|
handle->shutdown_req = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -169,6 +171,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
|
|||||||
handle->flags |= UV_HANDLE_SHUTTING;
|
handle->flags |= UV_HANDLE_SHUTTING;
|
||||||
handle->shutdown_req = req;
|
handle->shutdown_req = req;
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
|
uv_ref(loop);
|
||||||
|
|
||||||
uv_want_endgame(loop, (uv_handle_t*)handle);
|
uv_want_endgame(loop, (uv_handle_t*)handle);
|
||||||
|
|
||||||
@ -194,5 +197,5 @@ int uv_is_readable(uv_stream_t* handle) {
|
|||||||
|
|
||||||
|
|
||||||
int uv_is_writable(uv_stream_t* handle) {
|
int uv_is_writable(uv_stream_t* handle) {
|
||||||
return !(handle->flags & UV_HANDLE_SHUT);
|
return !(handle->flags & UV_HANDLE_SHUTTING);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -167,11 +167,13 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
|
|||||||
uv_tcp_accept_t* req;
|
uv_tcp_accept_t* req;
|
||||||
|
|
||||||
if (handle->flags & UV_HANDLE_CONNECTION &&
|
if (handle->flags & UV_HANDLE_CONNECTION &&
|
||||||
handle->flags & UV_HANDLE_SHUTTING &&
|
handle->shutdown_req != NULL &&
|
||||||
!(handle->flags & UV_HANDLE_SHUT) &&
|
|
||||||
handle->write_reqs_pending == 0) {
|
handle->write_reqs_pending == 0) {
|
||||||
|
|
||||||
if (shutdown(handle->socket, SD_SEND) != SOCKET_ERROR) {
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
|
status = -1;
|
||||||
|
sys_error = WSAEINTR;
|
||||||
|
} else if (shutdown(handle->socket, SD_SEND) != SOCKET_ERROR) {
|
||||||
status = 0;
|
status = 0;
|
||||||
handle->flags |= UV_HANDLE_SHUT;
|
handle->flags |= UV_HANDLE_SHUT;
|
||||||
} else {
|
} else {
|
||||||
@ -185,6 +187,9 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
|
|||||||
handle->shutdown_req->cb(handle->shutdown_req, status);
|
handle->shutdown_req->cb(handle->shutdown_req, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle->shutdown_req = NULL;
|
||||||
|
|
||||||
|
uv_unref(loop);
|
||||||
DECREASE_PENDING_REQ_COUNT(handle);
|
DECREASE_PENDING_REQ_COUNT(handle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -639,10 +644,12 @@ int uv__tcp_connect(uv_connect_t* req,
|
|||||||
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
|
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
|
||||||
/* Process the req without IOCP. */
|
/* Process the req without IOCP. */
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
|
uv_ref(loop);
|
||||||
uv_insert_pending_req(loop, (uv_req_t*)req);
|
uv_insert_pending_req(loop, (uv_req_t*)req);
|
||||||
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
|
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
|
||||||
/* The req will be processed with IOCP. */
|
/* The req will be processed with IOCP. */
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
|
uv_ref(loop);
|
||||||
} else {
|
} else {
|
||||||
uv__set_sys_error(loop, WSAGetLastError());
|
uv__set_sys_error(loop, WSAGetLastError());
|
||||||
return -1;
|
return -1;
|
||||||
@ -698,9 +705,11 @@ int uv__tcp_connect6(uv_connect_t* req,
|
|||||||
|
|
||||||
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
|
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
|
uv_ref(loop);
|
||||||
uv_insert_pending_req(loop, (uv_req_t*)req);
|
uv_insert_pending_req(loop, (uv_req_t*)req);
|
||||||
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
|
} else if (UV_SUCCEEDED_WITH_IOCP(success)) {
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
|
uv_ref(loop);
|
||||||
} else {
|
} else {
|
||||||
uv__set_sys_error(loop, WSAGetLastError());
|
uv__set_sys_error(loop, WSAGetLastError());
|
||||||
return -1;
|
return -1;
|
||||||
@ -795,12 +804,14 @@ int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,
|
|||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
handle->write_reqs_pending++;
|
handle->write_reqs_pending++;
|
||||||
uv_insert_pending_req(loop, (uv_req_t*) req);
|
uv_insert_pending_req(loop, (uv_req_t*) req);
|
||||||
|
uv_ref(loop);
|
||||||
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
|
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
|
||||||
/* Request queued by the kernel. */
|
/* Request queued by the kernel. */
|
||||||
req->queued_bytes = uv_count_bufs(bufs, bufcnt);
|
req->queued_bytes = uv_count_bufs(bufs, bufcnt);
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
handle->write_reqs_pending++;
|
handle->write_reqs_pending++;
|
||||||
handle->write_queue_size += req->queued_bytes;
|
handle->write_queue_size += req->queued_bytes;
|
||||||
|
uv_ref(loop);
|
||||||
} else {
|
} else {
|
||||||
/* Send failed due to an error. */
|
/* Send failed due to an error. */
|
||||||
uv__set_sys_error(loop, WSAGetLastError());
|
uv__set_sys_error(loop, WSAGetLastError());
|
||||||
@ -946,6 +957,7 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DECREASE_PENDING_REQ_COUNT(handle);
|
DECREASE_PENDING_REQ_COUNT(handle);
|
||||||
|
uv_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1020,6 +1032,7 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DECREASE_PENDING_REQ_COUNT(handle);
|
DECREASE_PENDING_REQ_COUNT(handle);
|
||||||
|
uv_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1683,6 +1683,7 @@ int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle,
|
|||||||
|
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
handle->write_reqs_pending++;
|
handle->write_reqs_pending++;
|
||||||
|
uv_ref(loop);
|
||||||
|
|
||||||
req->queued_bytes = 0;
|
req->queued_bytes = 0;
|
||||||
|
|
||||||
@ -1715,10 +1716,13 @@ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DECREASE_PENDING_REQ_COUNT(handle);
|
DECREASE_PENDING_REQ_COUNT(handle);
|
||||||
|
uv_unref(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uv_tty_close(uv_tty_t* handle) {
|
void uv_tty_close(uv_tty_t* handle) {
|
||||||
|
handle->flags |= UV_HANDLE_SHUTTING;
|
||||||
|
|
||||||
uv_tty_read_stop(handle);
|
uv_tty_read_stop(handle);
|
||||||
CloseHandle(handle->handle);
|
CloseHandle(handle->handle);
|
||||||
|
|
||||||
@ -1729,17 +1733,22 @@ void uv_tty_close(uv_tty_t* handle) {
|
|||||||
|
|
||||||
|
|
||||||
void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
|
void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
|
||||||
if (handle->flags & UV_HANDLE_CONNECTION &&
|
if ((handle->flags && UV_HANDLE_CONNECTION) &&
|
||||||
handle->flags & UV_HANDLE_SHUTTING &&
|
handle->shutdown_req != NULL &&
|
||||||
!(handle->flags & UV_HANDLE_SHUT) &&
|
|
||||||
handle->write_reqs_pending == 0) {
|
handle->write_reqs_pending == 0) {
|
||||||
handle->flags |= UV_HANDLE_SHUT;
|
|
||||||
|
|
||||||
/* TTY shutdown is really just a no-op */
|
/* TTY shutdown is really just a no-op */
|
||||||
if (handle->shutdown_req->cb) {
|
if (handle->shutdown_req->cb) {
|
||||||
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
|
uv__set_sys_error(loop, WSAEINTR);
|
||||||
|
handle->shutdown_req->cb(handle->shutdown_req, -1);
|
||||||
|
} else {
|
||||||
handle->shutdown_req->cb(handle->shutdown_req, 0);
|
handle->shutdown_req->cb(handle->shutdown_req, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->shutdown_req = NULL;
|
||||||
|
|
||||||
|
uv_unref(loop);
|
||||||
DECREASE_PENDING_REQ_COUNT(handle);
|
DECREASE_PENDING_REQ_COUNT(handle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -400,11 +400,13 @@ static int uv__udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],
|
|||||||
/* Request completed immediately. */
|
/* Request completed immediately. */
|
||||||
req->queued_bytes = 0;
|
req->queued_bytes = 0;
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
|
uv_ref(loop);
|
||||||
uv_insert_pending_req(loop, (uv_req_t*)req);
|
uv_insert_pending_req(loop, (uv_req_t*)req);
|
||||||
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
|
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
|
||||||
/* Request queued by the kernel. */
|
/* Request queued by the kernel. */
|
||||||
req->queued_bytes = uv_count_bufs(bufs, bufcnt);
|
req->queued_bytes = uv_count_bufs(bufs, bufcnt);
|
||||||
handle->reqs_pending++;
|
handle->reqs_pending++;
|
||||||
|
uv_ref(loop);
|
||||||
} else {
|
} else {
|
||||||
/* Send failed due to an error. */
|
/* Send failed due to an error. */
|
||||||
uv__set_sys_error(loop, WSAGetLastError());
|
uv__set_sys_error(loop, WSAGetLastError());
|
||||||
@ -569,6 +571,7 @@ void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uv_unref(loop);
|
||||||
DECREASE_PENDING_REQ_COUNT(handle);
|
DECREASE_PENDING_REQ_COUNT(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -107,7 +107,9 @@ static void connect_cb(uv_connect_t* req, int status) {
|
|||||||
|
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
fprintf(stderr, "connect error %s\n", uv_err_name(uv_last_error()));
|
fprintf(stderr,
|
||||||
|
"connect error %s\n",
|
||||||
|
uv_err_name(uv_last_error(uv_default_loop())));
|
||||||
#endif
|
#endif
|
||||||
uv_close((uv_handle_t*)req->handle, close_cb);
|
uv_close((uv_handle_t*)req->handle, close_cb);
|
||||||
conns_failed++;
|
conns_failed++;
|
||||||
|
|||||||
@ -131,8 +131,8 @@ static int ipc_helper(int listen_after_write) {
|
|||||||
|
|
||||||
uv_pipe_open(&channel, 0);
|
uv_pipe_open(&channel, 0);
|
||||||
|
|
||||||
ASSERT(uv_is_readable((uv_stream_t*)&channel));
|
ASSERT(uv_is_readable((uv_stream_t*) &channel));
|
||||||
ASSERT(uv_is_writable((uv_stream_t*)&channel));
|
ASSERT(uv_is_writable((uv_stream_t*) &channel));
|
||||||
|
|
||||||
r = uv_tcp_init(uv_default_loop(), &tcp_server);
|
r = uv_tcp_init(uv_default_loop(), &tcp_server);
|
||||||
ASSERT(r == 0);
|
ASSERT(r == 0);
|
||||||
|
|||||||
@ -135,7 +135,7 @@ int process_start(char *name, char *part, process_info_t *p) {
|
|||||||
p->stdio_in = nul;
|
p->stdio_in = nul;
|
||||||
p->stdio_out = file;
|
p->stdio_out = file;
|
||||||
p->process = pi.hProcess;
|
p->process = pi.hProcess;
|
||||||
p->name = name;
|
p->name = part;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@ -186,7 +186,8 @@ out:
|
|||||||
process_terminate(&processes[i]);
|
process_terminate(&processes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process_wait(processes, process_count - 1, -1) < 0) {
|
if (process_count > 0 &&
|
||||||
|
process_wait(processes, process_count - 1, -1) < 0) {
|
||||||
FATAL("process_wait failed");
|
FATAL("process_wait failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -92,21 +92,21 @@ static void create_cb(uv_fs_t* req) {
|
|||||||
|
|
||||||
TEST_IMPL(counters_init) {
|
TEST_IMPL(counters_init) {
|
||||||
int r;
|
int r;
|
||||||
int eio_init_prev;
|
uint64_t eio_init_prev;
|
||||||
int req_init_prev;
|
uint64_t req_init_prev;
|
||||||
int handle_init_prev;
|
uint64_t handle_init_prev;
|
||||||
int stream_init_prev;
|
uint64_t stream_init_prev;
|
||||||
int tcp_init_prev;
|
uint64_t tcp_init_prev;
|
||||||
int udp_init_prev;
|
uint64_t udp_init_prev;
|
||||||
int pipe_init_prev;
|
uint64_t pipe_init_prev;
|
||||||
int tty_init_prev;
|
uint64_t tty_init_prev;
|
||||||
int prepare_init_prev;
|
uint64_t prepare_init_prev;
|
||||||
int check_init_prev;
|
uint64_t check_init_prev;
|
||||||
int idle_init_prev;
|
uint64_t idle_init_prev;
|
||||||
int async_init_prev;
|
uint64_t async_init_prev;
|
||||||
int timer_init_prev;
|
uint64_t timer_init_prev;
|
||||||
int process_init_prev;
|
uint64_t process_init_prev;
|
||||||
int fs_event_init_prev;
|
uint64_t fs_event_init_prev;
|
||||||
|
|
||||||
/* req_init and eio_init test by uv_fs_open() */
|
/* req_init and eio_init test by uv_fs_open() */
|
||||||
unlink("test_file");
|
unlink("test_file");
|
||||||
|
|||||||
@ -37,17 +37,20 @@ TEST_IMPL(cwd_and_chdir) {
|
|||||||
err = uv_cwd(buffer_orig, size);
|
err = uv_cwd(buffer_orig, size);
|
||||||
ASSERT(err.code == UV_OK);
|
ASSERT(err.code == UV_OK);
|
||||||
|
|
||||||
last_slash = strrchr(buffer_orig,
|
/* Remove trailing slash unless at a root directory. */
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
'\\'
|
last_slash = strrchr(buffer_orig, '\\');
|
||||||
#else
|
|
||||||
'/'
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
|
|
||||||
ASSERT(last_slash);
|
ASSERT(last_slash);
|
||||||
|
if (last_slash > buffer_orig && *(last_slash - 1) != ':') {
|
||||||
*last_slash = '\0';
|
*last_slash = '\0';
|
||||||
|
}
|
||||||
|
#else /* Unix */
|
||||||
|
last_slash = strrchr(buffer_orig, '/');
|
||||||
|
ASSERT(last_slash);
|
||||||
|
if (last_slash != buffer_orig) {
|
||||||
|
*last_slash = '\0';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
err = uv_chdir(buffer_orig);
|
err = uv_chdir(buffer_orig);
|
||||||
ASSERT(err.code == UV_OK);
|
ASSERT(err.code == UV_OK);
|
||||||
|
|||||||
@ -186,8 +186,14 @@ static void chown_cb(uv_fs_t* req) {
|
|||||||
|
|
||||||
static void chown_root_cb(uv_fs_t* req) {
|
static void chown_root_cb(uv_fs_t* req) {
|
||||||
ASSERT(req->fs_type == UV_FS_CHOWN);
|
ASSERT(req->fs_type == UV_FS_CHOWN);
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* On windows, chown is a no-op and always succeeds. */
|
||||||
|
ASSERT(req->result == 0);
|
||||||
|
#else
|
||||||
|
/* On unix, chown'ing the root directory is not allowed. */
|
||||||
ASSERT(req->result == -1);
|
ASSERT(req->result == -1);
|
||||||
ASSERT(req->errorno == UV_EPERM);
|
ASSERT(req->errorno == UV_EPERM);
|
||||||
|
#endif
|
||||||
chown_cb_count++;
|
chown_cb_count++;
|
||||||
uv_fs_req_cleanup(req);
|
uv_fs_req_cleanup(req);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,6 +61,8 @@ TEST_DECLARE (pipe_connect_bad_name)
|
|||||||
TEST_DECLARE (pipe_connect_to_file)
|
TEST_DECLARE (pipe_connect_to_file)
|
||||||
TEST_DECLARE (connection_fail)
|
TEST_DECLARE (connection_fail)
|
||||||
TEST_DECLARE (connection_fail_doesnt_auto_close)
|
TEST_DECLARE (connection_fail_doesnt_auto_close)
|
||||||
|
TEST_DECLARE (shutdown_close_tcp)
|
||||||
|
TEST_DECLARE (shutdown_close_pipe)
|
||||||
TEST_DECLARE (shutdown_eof)
|
TEST_DECLARE (shutdown_eof)
|
||||||
TEST_DECLARE (callback_stack)
|
TEST_DECLARE (callback_stack)
|
||||||
TEST_DECLARE (error_message)
|
TEST_DECLARE (error_message)
|
||||||
@ -81,12 +83,16 @@ TEST_DECLARE (fs_event_ref)
|
|||||||
TEST_DECLARE (tcp_ref)
|
TEST_DECLARE (tcp_ref)
|
||||||
TEST_DECLARE (tcp_ref2)
|
TEST_DECLARE (tcp_ref2)
|
||||||
TEST_DECLARE (tcp_ref3)
|
TEST_DECLARE (tcp_ref3)
|
||||||
|
TEST_DECLARE (tcp_ref4)
|
||||||
|
TEST_DECLARE (tcp_ref5)
|
||||||
TEST_DECLARE (udp_ref)
|
TEST_DECLARE (udp_ref)
|
||||||
TEST_DECLARE (udp_ref2)
|
TEST_DECLARE (udp_ref2)
|
||||||
TEST_DECLARE (udp_ref3)
|
TEST_DECLARE (udp_ref3)
|
||||||
TEST_DECLARE (pipe_ref)
|
TEST_DECLARE (pipe_ref)
|
||||||
TEST_DECLARE (pipe_ref2)
|
TEST_DECLARE (pipe_ref2)
|
||||||
TEST_DECLARE (pipe_ref3)
|
TEST_DECLARE (pipe_ref3)
|
||||||
|
TEST_DECLARE (pipe_ref4)
|
||||||
|
TEST_DECLARE (pipe_ref5)
|
||||||
TEST_DECLARE (process_ref)
|
TEST_DECLARE (process_ref)
|
||||||
TEST_DECLARE (async)
|
TEST_DECLARE (async)
|
||||||
TEST_DECLARE (get_currentexe)
|
TEST_DECLARE (get_currentexe)
|
||||||
@ -218,6 +224,11 @@ TASK_LIST_START
|
|||||||
TEST_ENTRY (connection_fail)
|
TEST_ENTRY (connection_fail)
|
||||||
TEST_ENTRY (connection_fail_doesnt_auto_close)
|
TEST_ENTRY (connection_fail_doesnt_auto_close)
|
||||||
|
|
||||||
|
TEST_ENTRY (shutdown_close_tcp)
|
||||||
|
TEST_HELPER (shutdown_close_tcp, tcp4_echo_server)
|
||||||
|
TEST_ENTRY (shutdown_close_pipe)
|
||||||
|
TEST_HELPER (shutdown_close_pipe, pipe_echo_server)
|
||||||
|
|
||||||
TEST_ENTRY (shutdown_eof)
|
TEST_ENTRY (shutdown_eof)
|
||||||
TEST_HELPER (shutdown_eof, tcp4_echo_server)
|
TEST_HELPER (shutdown_eof, tcp4_echo_server)
|
||||||
|
|
||||||
@ -244,6 +255,10 @@ TASK_LIST_START
|
|||||||
TEST_ENTRY (tcp_ref2)
|
TEST_ENTRY (tcp_ref2)
|
||||||
TEST_ENTRY (tcp_ref3)
|
TEST_ENTRY (tcp_ref3)
|
||||||
TEST_HELPER (tcp_ref3, tcp4_echo_server)
|
TEST_HELPER (tcp_ref3, tcp4_echo_server)
|
||||||
|
TEST_ENTRY (tcp_ref4)
|
||||||
|
TEST_HELPER (tcp_ref4, tcp4_echo_server)
|
||||||
|
TEST_ENTRY (tcp_ref5)
|
||||||
|
TEST_HELPER (tcp_ref5, tcp4_echo_server)
|
||||||
TEST_ENTRY (udp_ref)
|
TEST_ENTRY (udp_ref)
|
||||||
TEST_ENTRY (udp_ref2)
|
TEST_ENTRY (udp_ref2)
|
||||||
TEST_ENTRY (udp_ref3)
|
TEST_ENTRY (udp_ref3)
|
||||||
@ -252,6 +267,10 @@ TASK_LIST_START
|
|||||||
TEST_ENTRY (pipe_ref2)
|
TEST_ENTRY (pipe_ref2)
|
||||||
TEST_ENTRY (pipe_ref3)
|
TEST_ENTRY (pipe_ref3)
|
||||||
TEST_HELPER (pipe_ref3, pipe_echo_server)
|
TEST_HELPER (pipe_ref3, pipe_echo_server)
|
||||||
|
TEST_ENTRY (pipe_ref4)
|
||||||
|
TEST_HELPER (pipe_ref4, pipe_echo_server)
|
||||||
|
TEST_ENTRY (pipe_ref5)
|
||||||
|
TEST_HELPER (pipe_ref5, pipe_echo_server)
|
||||||
TEST_ENTRY (process_ref)
|
TEST_ENTRY (process_ref)
|
||||||
|
|
||||||
TEST_ENTRY (loop_handles)
|
TEST_ENTRY (loop_handles)
|
||||||
|
|||||||
@ -26,11 +26,39 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
static uv_write_t write_req;
|
||||||
|
static uv_shutdown_t shutdown_req;
|
||||||
|
static uv_connect_t connect_req;
|
||||||
|
|
||||||
|
static char buffer[32767];
|
||||||
|
|
||||||
|
|
||||||
static void fail_cb(void) {
|
static void fail_cb(void) {
|
||||||
FATAL("fail_cb should not have been called");
|
FATAL("fail_cb should not have been called");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void write_unref_cb(uv_connect_t* req, int status) {
|
||||||
|
uv_buf_t buf = uv_buf_init(buffer, sizeof buffer);
|
||||||
|
|
||||||
|
ASSERT(req == &connect_req);
|
||||||
|
ASSERT(status == 0);
|
||||||
|
|
||||||
|
uv_write(&write_req, req->handle, &buf, 1, (uv_write_cb) fail_cb);
|
||||||
|
uv_unref(uv_default_loop()); // uv_write refs the loop
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void shutdown_unref_cb(uv_connect_t* req, int status) {
|
||||||
|
ASSERT(req == &connect_req);
|
||||||
|
ASSERT(status == 0);
|
||||||
|
|
||||||
|
uv_shutdown(&shutdown_req, req->handle, (uv_shutdown_cb) fail_cb);
|
||||||
|
uv_unref(uv_default_loop()); // uv_shutdown refs the loop
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_IMPL(ref) {
|
TEST_IMPL(ref) {
|
||||||
uv_run(uv_default_loop());
|
uv_run(uv_default_loop());
|
||||||
return 0;
|
return 0;
|
||||||
@ -142,10 +170,9 @@ TEST_IMPL(tcp_ref2) {
|
|||||||
|
|
||||||
TEST_IMPL(tcp_ref3) {
|
TEST_IMPL(tcp_ref3) {
|
||||||
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
|
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
|
||||||
uv_connect_t req;
|
|
||||||
uv_tcp_t h;
|
uv_tcp_t h;
|
||||||
uv_tcp_init(uv_default_loop(), &h);
|
uv_tcp_init(uv_default_loop(), &h);
|
||||||
uv_tcp_connect(&req, &h, addr, (uv_connect_cb)fail_cb);
|
uv_tcp_connect(&connect_req, &h, addr, (uv_connect_cb)fail_cb);
|
||||||
uv_unref(uv_default_loop());
|
uv_unref(uv_default_loop());
|
||||||
uv_unref(uv_default_loop()); /* connect req refs the loop */
|
uv_unref(uv_default_loop()); /* connect req refs the loop */
|
||||||
uv_run(uv_default_loop());
|
uv_run(uv_default_loop());
|
||||||
@ -153,6 +180,28 @@ TEST_IMPL(tcp_ref3) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_IMPL(tcp_ref4) {
|
||||||
|
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
|
||||||
|
uv_tcp_t h;
|
||||||
|
uv_tcp_init(uv_default_loop(), &h);
|
||||||
|
uv_tcp_connect(&connect_req, &h, addr, write_unref_cb);
|
||||||
|
uv_unref(uv_default_loop());
|
||||||
|
uv_run(uv_default_loop());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_IMPL(tcp_ref5) {
|
||||||
|
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
|
||||||
|
uv_tcp_t h;
|
||||||
|
uv_tcp_init(uv_default_loop(), &h);
|
||||||
|
uv_tcp_connect(&connect_req, &h, addr, shutdown_unref_cb);
|
||||||
|
uv_unref(uv_default_loop());
|
||||||
|
uv_run(uv_default_loop());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_IMPL(udp_ref) {
|
TEST_IMPL(udp_ref) {
|
||||||
uv_udp_t h;
|
uv_udp_t h;
|
||||||
uv_udp_init(uv_default_loop(), &h);
|
uv_udp_init(uv_default_loop(), &h);
|
||||||
@ -210,10 +259,9 @@ TEST_IMPL(pipe_ref2) {
|
|||||||
|
|
||||||
|
|
||||||
TEST_IMPL(pipe_ref3) {
|
TEST_IMPL(pipe_ref3) {
|
||||||
uv_connect_t req;
|
|
||||||
uv_pipe_t h;
|
uv_pipe_t h;
|
||||||
uv_pipe_init(uv_default_loop(), &h, 0);
|
uv_pipe_init(uv_default_loop(), &h, 0);
|
||||||
uv_pipe_connect(&req, &h, TEST_PIPENAME, (uv_connect_cb)fail_cb);
|
uv_pipe_connect(&connect_req, &h, TEST_PIPENAME, (uv_connect_cb)fail_cb);
|
||||||
uv_unref(uv_default_loop());
|
uv_unref(uv_default_loop());
|
||||||
uv_unref(uv_default_loop()); /* connect req refs the loop */
|
uv_unref(uv_default_loop()); /* connect req refs the loop */
|
||||||
uv_run(uv_default_loop());
|
uv_run(uv_default_loop());
|
||||||
@ -221,6 +269,26 @@ TEST_IMPL(pipe_ref3) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_IMPL(pipe_ref4) {
|
||||||
|
uv_pipe_t h;
|
||||||
|
uv_pipe_init(uv_default_loop(), &h, 0);
|
||||||
|
uv_pipe_connect(&connect_req, &h, TEST_PIPENAME, write_unref_cb);
|
||||||
|
uv_unref(uv_default_loop());
|
||||||
|
uv_run(uv_default_loop());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_IMPL(pipe_ref5) {
|
||||||
|
uv_pipe_t h;
|
||||||
|
uv_pipe_init(uv_default_loop(), &h, 0);
|
||||||
|
uv_pipe_connect(&connect_req, &h, TEST_PIPENAME, shutdown_unref_cb);
|
||||||
|
uv_unref(uv_default_loop());
|
||||||
|
uv_run(uv_default_loop());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_IMPL(process_ref) {
|
TEST_IMPL(process_ref) {
|
||||||
/* spawn_helper4 blocks indefinitely. */
|
/* spawn_helper4 blocks indefinitely. */
|
||||||
char *argv[] = { NULL, "spawn_helper4", NULL };
|
char *argv[] = { NULL, "spawn_helper4", NULL };
|
||||||
|
|||||||
101
test/test-shutdown-close.c
Normal file
101
test/test-shutdown-close.c
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These tests verify that the uv_shutdown callback is always made, even when
|
||||||
|
* it is immediately followed by an uv_close call.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uv.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
|
||||||
|
static uv_shutdown_t shutdown_req;
|
||||||
|
static uv_connect_t connect_req;
|
||||||
|
|
||||||
|
static int connect_cb_called = 0;
|
||||||
|
static int shutdown_cb_called = 0;
|
||||||
|
static int close_cb_called = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static void shutdown_cb(uv_shutdown_t* req, int status) {
|
||||||
|
ASSERT(req == &shutdown_req);
|
||||||
|
ASSERT(status == 0 ||
|
||||||
|
(status == -1 && uv_last_error(uv_default_loop()).code == UV_EINTR));
|
||||||
|
shutdown_cb_called++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void close_cb(uv_handle_t* handle) {
|
||||||
|
close_cb_called++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void connect_cb(uv_connect_t* req, int status) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
ASSERT(req == &connect_req);
|
||||||
|
ASSERT(status == 0);
|
||||||
|
|
||||||
|
r = uv_shutdown(&shutdown_req, req->handle, shutdown_cb);
|
||||||
|
ASSERT(r == 0);
|
||||||
|
uv_close((uv_handle_t*) req->handle, close_cb);
|
||||||
|
|
||||||
|
connect_cb_called++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_IMPL(shutdown_close_tcp) {
|
||||||
|
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
|
||||||
|
uv_tcp_t h;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = uv_tcp_init(uv_default_loop(), &h);
|
||||||
|
ASSERT(r == 0);
|
||||||
|
r = uv_tcp_connect(&connect_req, &h, addr, connect_cb);
|
||||||
|
ASSERT(r == 0);
|
||||||
|
r = uv_run(uv_default_loop());
|
||||||
|
ASSERT(r == 0);
|
||||||
|
|
||||||
|
ASSERT(connect_cb_called == 1);
|
||||||
|
ASSERT(shutdown_cb_called == 1);
|
||||||
|
ASSERT(close_cb_called == 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_IMPL(shutdown_close_pipe) {
|
||||||
|
uv_pipe_t h;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = uv_pipe_init(uv_default_loop(), &h, 0);
|
||||||
|
ASSERT(r == 0);
|
||||||
|
uv_pipe_connect(&connect_req, &h, TEST_PIPENAME, connect_cb);
|
||||||
|
r = uv_run(uv_default_loop());
|
||||||
|
ASSERT(r == 0);
|
||||||
|
|
||||||
|
ASSERT(connect_cb_called == 1);
|
||||||
|
ASSERT(shutdown_cb_called == 1);
|
||||||
|
ASSERT(close_cb_called == 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -22,23 +22,64 @@
|
|||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include <io.h>
|
||||||
|
# include <windows.h>
|
||||||
|
#else // Unix
|
||||||
|
# include <fcntl.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
TEST_IMPL(tty) {
|
TEST_IMPL(tty) {
|
||||||
int r, width, height;
|
int r, width, height;
|
||||||
uv_tty_t tty;
|
int ttyin_fd, ttyout_fd;
|
||||||
|
uv_tty_t tty_in, tty_out;
|
||||||
uv_loop_t* loop = uv_default_loop();
|
uv_loop_t* loop = uv_default_loop();
|
||||||
|
|
||||||
|
// Make sure we have an FD that refers to a tty
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE handle;
|
||||||
|
handle = CreateFileA("conin$",
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL);
|
||||||
|
ASSERT(handle != INVALID_HANDLE_VALUE);
|
||||||
|
ttyin_fd = _open_osfhandle((intptr_t) handle, 0);
|
||||||
|
|
||||||
|
handle = CreateFileA("conout$",
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL);
|
||||||
|
ASSERT(handle != INVALID_HANDLE_VALUE);
|
||||||
|
ttyout_fd = _open_osfhandle((intptr_t) handle, 0);
|
||||||
|
|
||||||
|
#else /* unix */
|
||||||
|
ttyin_fd = open("/dev/tty", O_RDONLY, 0);
|
||||||
|
ttyout_fd = open("/dev/tty", O_WRONLY, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ASSERT(ttyin_fd >= 0);
|
||||||
|
ASSERT(ttyout_fd >= 0);
|
||||||
|
|
||||||
ASSERT(UV_UNKNOWN_HANDLE == uv_guess_handle(-1));
|
ASSERT(UV_UNKNOWN_HANDLE == uv_guess_handle(-1));
|
||||||
|
|
||||||
/*
|
ASSERT(UV_TTY == uv_guess_handle(ttyin_fd));
|
||||||
* Not necessarily a problem if this assert goes off. E.G you are piping
|
ASSERT(UV_TTY == uv_guess_handle(ttyout_fd));
|
||||||
* this test to a file. 0 == stdin.
|
|
||||||
*/
|
|
||||||
ASSERT(UV_TTY == uv_guess_handle(0));
|
|
||||||
|
|
||||||
r = uv_tty_init(uv_default_loop(), &tty, 0, 1);
|
r = uv_tty_init(uv_default_loop(), &tty_in, ttyin_fd, 1);
|
||||||
ASSERT(r == 0);
|
ASSERT(r == 0);
|
||||||
|
|
||||||
r = uv_tty_get_winsize(&tty, &width, &height);
|
r = uv_tty_init(uv_default_loop(), &tty_out, ttyout_fd, 2);
|
||||||
|
ASSERT(r == 0);
|
||||||
|
|
||||||
|
r = uv_tty_get_winsize(&tty_out, &width, &height);
|
||||||
ASSERT(r == 0);
|
ASSERT(r == 0);
|
||||||
|
|
||||||
printf("width=%d height=%d\n", width, height);
|
printf("width=%d height=%d\n", width, height);
|
||||||
@ -51,16 +92,17 @@ TEST_IMPL(tty) {
|
|||||||
ASSERT(height > 10);
|
ASSERT(height > 10);
|
||||||
|
|
||||||
/* Turn on raw mode. */
|
/* Turn on raw mode. */
|
||||||
r = uv_tty_set_mode(&tty, 1);
|
r = uv_tty_set_mode(&tty_in, 1);
|
||||||
ASSERT(r == 0);
|
ASSERT(r == 0);
|
||||||
|
|
||||||
/* Turn off raw mode. */
|
/* Turn off raw mode. */
|
||||||
r = uv_tty_set_mode(&tty, 0);
|
r = uv_tty_set_mode(&tty_in, 0);
|
||||||
ASSERT(r == 0);
|
ASSERT(r == 0);
|
||||||
|
|
||||||
/* TODO check the actual mode! */
|
/* TODO check the actual mode! */
|
||||||
|
|
||||||
uv_close((uv_handle_t*)&tty, NULL);
|
uv_close((uv_handle_t*) &tty_in, NULL);
|
||||||
|
uv_close((uv_handle_t*) &tty_out, NULL);
|
||||||
|
|
||||||
uv_run(loop);
|
uv_run(loop);
|
||||||
|
|
||||||
|
|||||||
1
uv.gyp
1
uv.gyp
@ -319,6 +319,7 @@
|
|||||||
'test/test-platform-output.c',
|
'test/test-platform-output.c',
|
||||||
'test/test-process-title.c',
|
'test/test-process-title.c',
|
||||||
'test/test-ref.c',
|
'test/test-ref.c',
|
||||||
|
'test/test-shutdown-close.c',
|
||||||
'test/test-shutdown-eof.c',
|
'test/test-shutdown-eof.c',
|
||||||
'test/test-spawn.c',
|
'test/test-spawn.c',
|
||||||
'test/test-stdio-over-pipes.c',
|
'test/test-stdio-over-pipes.c',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user