Skip to content
This repository has been archived by the owner on Apr 3, 2019. It is now read-only.

Commit

Permalink
fix compatibility with cygwin pipes: be more tolerant of the pipes co…
Browse files Browse the repository at this point in the history
…nnected. also, duplicate handles to ensure the original handle remains valid after uv_close (esp. important for stdio)
  • Loading branch information
vtjnash committed Jan 1, 2014
1 parent 0bae155 commit 866b38b
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 9 deletions.
60 changes: 54 additions & 6 deletions src/win/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,15 +356,22 @@ static int uv_set_pipe_handle(uv_loop_t* loop, uv_pipe_t* handle,
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
FILE_MODE_INFORMATION mode_info;
DWORD mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;
DWORD oldmode, mode = PIPE_READMODE_BYTE | PIPE_WAIT;

if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) {
if (!GetNamedPipeHandleState(pipeHandle, &oldmode, NULL, NULL, NULL, NULL, 0)) {
oldmode = PIPE_READMODE_MESSAGE | PIPE_NOWAIT; // assume the worst
}

if (oldmode != mode && !SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) {
/* If this returns ERROR_INVALID_PARAMETER we probably opened something */
/* that is not a pipe. */
if (GetLastError() == ERROR_INVALID_PARAMETER) {
SetLastError(WSAENOTSOCK);
return -1;
}
if (oldmode & PIPE_NOWAIT) {
return -1;
}
return -1;
}

/* Check if the pipe was created with FILE_FLAG_OVERLAPPED. */
Expand Down Expand Up @@ -1844,16 +1851,57 @@ static void eof_timer_close_cb(uv_handle_t* handle) {


int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
HANDLE os_handle = (HANDLE)_get_osfhandle(file);
HANDLE os_handle = (HANDLE)_get_osfhandle(file), os_handle2;
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
FILE_ACCESS_INFORMATION access;

/* Try to duplicate the file handle, with FILE_WRITE_ATTRIBUTES access */
nt_status = pNtQueryInformationFile(os_handle,
&io_status,
&access,
sizeof(access),
FileAccessInformation);
if (nt_status != STATUS_SUCCESS) {
return UV_EINVAL;
}

if (pipe->flags&UV_HANDLE_PIPE_IPC) {
if (!(access.AccessFlags&FILE_WRITE_DATA) ||
!(access.AccessFlags&FILE_READ_DATA)){
return UV_EINVAL;
}
}

if (!DuplicateHandle(GetCurrentProcess(),
os_handle,
GetCurrentProcess(),
&os_handle2,
access.AccessFlags|FILE_WRITE_ATTRIBUTES,
TRUE,
0)) {
if (!DuplicateHandle(GetCurrentProcess(),
os_handle,
GetCurrentProcess(),
&os_handle2,
access.AccessFlags,
TRUE,
0)) {
return UV_EINVAL;
}
}

if (os_handle == INVALID_HANDLE_VALUE ||
uv_set_pipe_handle(pipe->loop, pipe, os_handle, 0) == -1) {
uv_set_pipe_handle(pipe->loop, pipe, os_handle2, 0) == -1) {
return UV_EINVAL;
}

uv_pipe_connection_init(pipe);
pipe->handle = os_handle;
pipe->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
if (access.AccessFlags&FILE_WRITE_DATA)
pipe->flags |= UV_HANDLE_READABLE;
if (access.AccessFlags&FILE_READ_DATA)
pipe->flags |= UV_HANDLE_WRITABLE;

This comment has been minimized.

Copy link
@vtjnash

vtjnash May 15, 2014

Author Collaborator

@loladiro was I asleep when I committed this? or I am forgetting something important

This comment has been minimized.

Copy link
@Keno

Keno May 15, 2014

Hmm, not sure either. I was thinking maybe it's the access information of the other pipe end, but that doesn't seem right.

This comment has been minimized.

Copy link
@vtjnash

vtjnash May 15, 2014

Author Collaborator

yeah, exactly (ps. why aren't you on IRC these days?)


if (pipe->flags&UV_HANDLE_PIPE_IPC) {
assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
Expand Down
15 changes: 12 additions & 3 deletions src/win/tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,20 @@ void uv_console_init() {


int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
HANDLE handle;
HANDLE handle, os_handle;
CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;

handle = (HANDLE) _get_osfhandle(fd);
if (handle == INVALID_HANDLE_VALUE) {
os_handle = (HANDLE) _get_osfhandle(fd);
if (os_handle == INVALID_HANDLE_VALUE) {
return UV_EBADF;
}
if (!DuplicateHandle(GetCurrentProcess(),
os_handle,
GetCurrentProcess(),
&handle,
0,
TRUE,
DUPLICATE_SAME_ACCESS)) {
return UV_EBADF;
}

Expand Down
4 changes: 4 additions & 0 deletions src/win/winapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -4124,6 +4124,10 @@ typedef struct _FILE_PIPE_LOCAL_INFORMATION {
ULONG NamedPipeEnd;
} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;

typedef struct _FILE_ACCESS_INFORMATION {
ULONG AccessFlags;
} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;

typedef struct _FILE_BASIC_INFORMATION {
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
Expand Down

3 comments on commit 866b38b

@vtjnash
Copy link
Collaborator Author

@vtjnash vtjnash commented on 866b38b Jan 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@loladiro do you think upstream would be interested in this?

@Keno
Copy link

@Keno Keno commented on 866b38b Jan 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should try.

@vtjnash
Copy link
Collaborator Author

@vtjnash vtjnash commented on 866b38b Jan 2, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I cherry-picked it to joyent/libuv#1067

Please sign in to comment.