in source/windows/iocp/pipe.c [189:343]
int aws_pipe_init(
struct aws_pipe_read_end *read_end,
struct aws_event_loop *read_end_event_loop,
struct aws_pipe_write_end *write_end,
struct aws_event_loop *write_end_event_loop,
struct aws_allocator *allocator) {
AWS_ASSERT(read_end);
AWS_ASSERT(read_end_event_loop);
AWS_ASSERT(write_end);
AWS_ASSERT(write_end_event_loop);
AWS_ASSERT(allocator);
AWS_ZERO_STRUCT(*write_end);
AWS_ZERO_STRUCT(*read_end);
struct write_end_impl *write_impl = NULL;
struct read_end_impl *read_impl = NULL;
/* Init write-end */
write_impl = aws_mem_calloc(allocator, 1, sizeof(struct write_end_impl));
if (!write_impl) {
goto clean_up;
}
write_impl->alloc = allocator;
write_impl->state = WRITE_END_STATE_OPEN;
write_impl->handle.data.handle = INVALID_HANDLE_VALUE;
aws_linked_list_init(&write_impl->write_list);
/* Anonymous pipes don't support overlapped I/O so named pipes are used. Names must be unique system-wide.
* We generate random names, but collisions are theoretically possible, so try several times before giving up. */
char pipe_name[256];
int tries = 0;
while (true) {
int err = aws_pipe_get_unique_name(pipe_name, sizeof(pipe_name));
if (err) {
goto clean_up;
}
const DWORD open_mode = PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE;
const DWORD pipe_mode = PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS;
write_impl->handle.data.handle = CreateNamedPipeA(
pipe_name,
open_mode,
pipe_mode,
1, /*nMaxInstances*/
PIPE_BUFFER_SIZE, /*nOutBufferSize*/
PIPE_BUFFER_SIZE, /*nInBufferSize*/
0, /*nDefaultTimeout: 0 means default*/
NULL); /*lpSecurityAttributes: NULL means default */
if (write_impl->handle.data.handle != INVALID_HANDLE_VALUE) {
/* Success, break out of loop */
break;
}
if (++tries >= PIPE_UNIQUE_NAME_MAX_TRIES) {
s_raise_last_windows_error();
goto clean_up;
}
}
int err = aws_event_loop_connect_handle_to_io_completion_port(write_end_event_loop, &write_impl->handle);
if (err) {
goto clean_up;
}
write_impl->event_loop = write_end_event_loop;
/* Init read-end */
read_impl = aws_mem_calloc(allocator, 1, sizeof(struct read_end_impl));
if (!read_impl) {
goto clean_up;
}
read_impl->alloc = allocator;
read_impl->state = READ_END_STATE_OPEN;
read_impl->handle.data.handle = INVALID_HANDLE_VALUE;
read_impl->handle.data.handle = CreateFileA(
pipe_name, /*lpFileName*/
GENERIC_READ, /*dwDesiredAccess*/
0, /*dwShareMode: 0 prevents acess by external processes*/
NULL, /*lpSecurityAttributes: NULL prevents inheritance by child processes*/
OPEN_EXISTING, /*dwCreationDisposition*/
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, /*dwFlagsAndAttributes*/
NULL); /*hTemplateFile: ignored when opening existing file*/
if (read_impl->handle.data.handle == INVALID_HANDLE_VALUE) {
s_raise_last_windows_error();
goto clean_up;
}
err = aws_event_loop_connect_handle_to_io_completion_port(read_end_event_loop, &read_impl->handle);
if (err) {
goto clean_up;
}
read_impl->event_loop = read_end_event_loop;
/* Init the read-end's async operations */
read_impl->async_monitoring = aws_mem_calloc(allocator, 1, sizeof(struct async_operation));
if (!read_impl->async_monitoring) {
goto clean_up;
}
read_impl->async_monitoring->alloc = allocator;
aws_overlapped_init(&read_impl->async_monitoring->op.overlapped, s_read_end_on_zero_byte_read_completion, read_end);
read_impl->async_error_report = aws_mem_calloc(allocator, 1, sizeof(struct async_operation));
if (!read_impl->async_error_report) {
goto clean_up;
}
read_impl->async_error_report->alloc = allocator;
aws_task_init(
&read_impl->async_error_report->op.task, s_read_end_report_error_task, read_end, "pipe_read_end_report_error");
/* Success */
write_end->impl_data = write_impl;
read_end->impl_data = read_impl;
return AWS_OP_SUCCESS;
clean_up:
if (write_impl) {
if (write_impl->handle.data.handle != INVALID_HANDLE_VALUE) {
CloseHandle(write_impl->handle.data.handle);
}
aws_mem_release(allocator, write_impl);
write_impl = NULL;
}
if (read_impl) {
if (read_impl->handle.data.handle != INVALID_HANDLE_VALUE) {
CloseHandle(read_impl->handle.data.handle);
}
if (read_impl->async_monitoring) {
aws_mem_release(allocator, read_impl->async_monitoring);
}
if (read_impl->async_error_report) {
aws_mem_release(allocator, read_impl->async_error_report);
}
aws_mem_release(allocator, read_impl);
read_impl = NULL;
}
return AWS_OP_ERR;
}