diff options
Diffstat (limited to 'file_io/win32/readwrite.c')
-rw-r--r-- | file_io/win32/readwrite.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/file_io/win32/readwrite.c b/file_io/win32/readwrite.c index ef3f7ad85..bf7cbfb30 100644 --- a/file_io/win32/readwrite.c +++ b/file_io/win32/readwrite.c @@ -490,10 +490,10 @@ APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, a (*nbytes) = 0; rv = apr_get_os_error(); - /* XXX: This must be corrected, per the apr_file_read logic!!! */ if (rv == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) { DWORD timeout_ms; + DWORD res; if (thefile->timeout == 0) { timeout_ms = 0; @@ -505,26 +505,38 @@ APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, a timeout_ms = (DWORD)(thefile->timeout / 1000); } - rv = WaitForSingleObject(thefile->pOverlapped->hEvent, timeout_ms); - switch (rv) { - case WAIT_OBJECT_0: - GetOverlappedResult(thefile->filehand, thefile->pOverlapped, - &bwrote, TRUE); - *nbytes = bwrote; - rv = APR_SUCCESS; - break; - case WAIT_TIMEOUT: - rv = (timeout_ms == 0) ? APR_EAGAIN : APR_TIMEUP; - break; - case WAIT_FAILED: - rv = apr_get_os_error(); - break; - default: - break; - } - if (rv != APR_SUCCESS) { + res = WaitForSingleObject(thefile->pOverlapped->hEvent, timeout_ms); + + /* There is one case that represents entirely + * successful operations, otherwise we will cancel + * the operation in progress. + */ + if (res != WAIT_OBJECT_0) { CancelIoEx(thefile->filehand, thefile->pOverlapped); } + + /* Ignore any failures above. Attempt to complete + * the overlapped operation and use only _its_ result. + * For example, CancelIo or WaitForSingleObject can + * fail if the handle is closed, yet the read may have + * completed before we attempted to CancelIo... + */ + if (GetOverlappedResult(thefile->filehand, thefile->pOverlapped, + &bwrote, TRUE)) { + *nbytes = bwrote; + rv = APR_SUCCESS; + } + else { + rv = apr_get_os_error(); + if (((rv == APR_FROM_OS_ERROR(ERROR_IO_INCOMPLETE)) + || (rv == APR_FROM_OS_ERROR(ERROR_OPERATION_ABORTED))) + && (res == WAIT_TIMEOUT)) + rv = APR_TIMEUP; + + if (rv == APR_TIMEUP && timeout_ms == 0) { + rv = APR_EAGAIN; + } + } } } if (rv == APR_SUCCESS && thefile->pOverlapped && !thefile->pipe) { |