win,pipe: race condition canceling readfile thread

Fixes a race condition where if uv_read_stop was called shortly
after uv_read_start or a successful read and before the
uv_pipe_zero_readfile_thread_proc thread started,
that thread would call the blocking ReadFile call after the
HANDLE_READING flag had already been cleared.

Also ignores EINTR to be more consistent with unix
(although we generally don't expect to see this condition on windows).

PR-URL: https://github.com/libuv/libuv/pull/1322
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
Reviewed-By: Bartosz Sosnowski <bartosz@janeasystems.com>
This commit is contained in:
Jameson Nash 2015-07-16 01:54:28 -04:00 committed by Santiago Gimeno
parent d5fc593b5f
commit c42a4ca372
No known key found for this signature in database
GPG Key ID: F28C3C8DA33C03BE

View File

@ -968,27 +968,31 @@ static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) {
uv_mutex_unlock(m); uv_mutex_unlock(m);
} }
restart_readfile: restart_readfile:
result = ReadFile(handle->handle, if (handle->flags & UV_HANDLE_READING) {
&uv_zero_, result = ReadFile(handle->handle,
0, &uv_zero_,
&bytes, 0,
NULL); &bytes,
if (!result) { NULL);
err = GetLastError(); if (!result) {
if (err == ERROR_OPERATION_ABORTED && err = GetLastError();
handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { if (err == ERROR_OPERATION_ABORTED &&
if (handle->flags & UV_HANDLE_READING) { handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
/* just a brief break to do something else */ if (handle->flags & UV_HANDLE_READING) {
handle->pipe.conn.readfile_thread = NULL; /* just a brief break to do something else */
/* resume after it is finished */ handle->pipe.conn.readfile_thread = NULL;
uv_mutex_lock(m); /* resume after it is finished */
handle->pipe.conn.readfile_thread = hThread; uv_mutex_lock(m);
uv_mutex_unlock(m); handle->pipe.conn.readfile_thread = hThread;
goto restart_readfile; uv_mutex_unlock(m);
} else { goto restart_readfile;
result = 1; /* successfully stopped reading */ } else {
result = 1; /* successfully stopped reading */
}
} }
} }
} else {
result = 1; /* successfully aborted read before it even started */
} }
if (hThread) { if (hThread) {
assert(hThread == handle->pipe.conn.readfile_thread); assert(hThread == handle->pipe.conn.readfile_thread);
@ -1515,7 +1519,10 @@ static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,
static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle, static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
int error, uv_buf_t buf) { int error, uv_buf_t buf) {
if (error == ERROR_BROKEN_PIPE) { if (error == ERROR_OPERATION_ABORTED) {
/* do nothing (equivalent to EINTR) */
}
else if (error == ERROR_BROKEN_PIPE) {
uv_pipe_read_eof(loop, handle, buf); uv_pipe_read_eof(loop, handle, buf);
} else { } else {
uv_pipe_read_error(loop, handle, error, buf); uv_pipe_read_error(loop, handle, error, buf);