Alien-uv
view release on metacpan or search on metacpan
libuv/src/win/pipe.c view on Meta::CPAN
goto error;
}
REGISTER_HANDLE_REQ(loop, handle, req);
handle->reqs_pending++;
return;
}
err = GetLastError();
goto error;
}
assert(pipeHandle != INVALID_HANDLE_VALUE);
if (uv_set_pipe_handle(loop,
(uv_pipe_t*) req->handle,
pipeHandle,
-1,
duplex_flags)) {
err = GetLastError();
goto error;
}
SET_REQ_SUCCESS(req);
uv_insert_pending_req(loop, (uv_req_t*) req);
handle->reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
return;
error:
if (handle->name) {
uv__free(handle->name);
handle->name = NULL;
}
if (pipeHandle != INVALID_HANDLE_VALUE) {
CloseHandle(pipeHandle);
}
/* Make this req pending reporting an error. */
SET_REQ_ERROR(req, err);
uv_insert_pending_req(loop, (uv_req_t*) req);
handle->reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
return;
}
void uv__pipe_interrupt_read(uv_pipe_t* handle) {
BOOL r;
if (!(handle->flags & UV_HANDLE_READ_PENDING))
return; /* No pending reads. */
if (handle->flags & UV_HANDLE_CANCELLATION_PENDING)
return; /* Already cancelled. */
if (handle->handle == INVALID_HANDLE_VALUE)
return; /* Pipe handle closed. */
if (!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)) {
/* Cancel asynchronous read. */
r = CancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);
assert(r || GetLastError() == ERROR_NOT_FOUND);
} else {
/* Cancel synchronous read (which is happening in the thread pool). */
HANDLE thread;
volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle;
EnterCriticalSection(&handle->pipe.conn.readfile_thread_lock);
thread = *thread_ptr;
if (thread == NULL) {
/* The thread pool thread has not yet reached the point of blocking, we
* can pre-empt it by setting thread_handle to INVALID_HANDLE_VALUE. */
*thread_ptr = INVALID_HANDLE_VALUE;
} else {
/* Spin until the thread has acknowledged (by setting the thread to
* INVALID_HANDLE_VALUE) that it is past the point of blocking. */
while (thread != INVALID_HANDLE_VALUE) {
r = CancelSynchronousIo(thread);
assert(r || GetLastError() == ERROR_NOT_FOUND);
SwitchToThread(); /* Yield thread. */
thread = *thread_ptr;
}
}
LeaveCriticalSection(&handle->pipe.conn.readfile_thread_lock);
}
/* Set flag to indicate that read has been cancelled. */
handle->flags |= UV_HANDLE_CANCELLATION_PENDING;
}
void uv__pipe_read_stop(uv_pipe_t* handle) {
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(handle->loop, handle);
uv__pipe_interrupt_read(handle);
}
/* Cleans up uv_pipe_t (server or connection) and all resources associated with
* it. */
void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
int i;
HANDLE pipeHandle;
uv__pipe_interrupt_read(handle);
if (handle->name) {
uv__free(handle->name);
handle->name = NULL;
}
if (handle->flags & UV_HANDLE_PIPESERVER) {
for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
pipeHandle = handle->pipe.serv.accept_reqs[i].pipeHandle;
if (pipeHandle != INVALID_HANDLE_VALUE) {
CloseHandle(pipeHandle);
handle->pipe.serv.accept_reqs[i].pipeHandle = INVALID_HANDLE_VALUE;
}
}
handle->handle = INVALID_HANDLE_VALUE;
libuv/src/win/pipe.c view on Meta::CPAN
&io_status,
&access,
sizeof(access),
FileAccessInformation);
if (nt_status != STATUS_SUCCESS)
return UV_EINVAL;
if (pipe->ipc) {
if (!(access.AccessFlags & FILE_WRITE_DATA) ||
!(access.AccessFlags & FILE_READ_DATA)) {
return UV_EINVAL;
}
}
if (access.AccessFlags & FILE_WRITE_DATA)
duplex_flags |= UV_HANDLE_WRITABLE;
if (access.AccessFlags & FILE_READ_DATA)
duplex_flags |= UV_HANDLE_READABLE;
if (os_handle == INVALID_HANDLE_VALUE ||
uv_set_pipe_handle(pipe->loop,
pipe,
os_handle,
file,
duplex_flags) == -1) {
return UV_EINVAL;
}
uv_pipe_connection_init(pipe);
if (pipe->ipc) {
assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
pipe->pipe.conn.ipc_remote_pid = uv_os_getppid();
assert(pipe->pipe.conn.ipc_remote_pid != (DWORD) -1);
}
return 0;
}
static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) {
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
FILE_NAME_INFORMATION tmp_name_info;
FILE_NAME_INFORMATION* name_info;
WCHAR* name_buf;
unsigned int addrlen;
unsigned int name_size;
unsigned int name_len;
int err;
uv__once_init();
name_info = NULL;
if (handle->handle == INVALID_HANDLE_VALUE) {
*size = 0;
return UV_EINVAL;
}
/* NtQueryInformationFile will block if another thread is performing a
* blocking operation on the queried handle. If the pipe handle is
* synchronous, there may be a worker thread currently calling ReadFile() on
* the pipe handle, which could cause a deadlock. To avoid this, interrupt
* the read. */
if (handle->flags & UV_HANDLE_CONNECTION &&
handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
uv__pipe_interrupt_read((uv_pipe_t*) handle); /* cast away const warning */
}
nt_status = pNtQueryInformationFile(handle->handle,
&io_status,
&tmp_name_info,
sizeof tmp_name_info,
FileNameInformation);
if (nt_status == STATUS_BUFFER_OVERFLOW) {
name_size = sizeof(*name_info) + tmp_name_info.FileNameLength;
name_info = uv__malloc(name_size);
if (!name_info) {
*size = 0;
err = UV_ENOMEM;
goto cleanup;
}
nt_status = pNtQueryInformationFile(handle->handle,
&io_status,
name_info,
name_size,
FileNameInformation);
}
if (nt_status != STATUS_SUCCESS) {
*size = 0;
err = uv_translate_sys_error(pRtlNtStatusToDosError(nt_status));
goto error;
}
if (!name_info) {
/* the struct on stack was used */
name_buf = tmp_name_info.FileName;
name_len = tmp_name_info.FileNameLength;
} else {
name_buf = name_info->FileName;
name_len = name_info->FileNameLength;
}
if (name_len == 0) {
*size = 0;
err = 0;
goto error;
}
name_len /= sizeof(WCHAR);
/* check how much space we need */
addrlen = WideCharToMultiByte(CP_UTF8,
0,
name_buf,
name_len,
NULL,
0,
NULL,
NULL);
( run in 0.502 second using v1.01-cache-2.11-cpan-411bb0df24b )