windows/fs: handle _open_osfhandle() failure correctly

Until now we assumed that _open_osfhandle() would set _doserrno on
failure. This assumption was very wrong in one obvious case, namely when
the CRT file descriptor table would fill up. In that case errno is set
to EMFILE, but GetLastError() returns zero - which makes sense because
it's not a win32 error but rather a CRT problem.
This commit is contained in:
Bert Belder 2013-09-05 08:50:04 +02:00
parent 812717d0dd
commit faf2c5932c

View File

@ -400,7 +400,7 @@ void fs__open(uv_fs_t* req) {
DWORD disposition;
DWORD attributes = 0;
HANDLE file;
int result, current_umask;
int fd, current_umask;
int flags = req->file_flags;
/* Obtain the active umask. umask() never fails and returns the previous */
@ -512,8 +512,23 @@ void fs__open(uv_fs_t* req) {
}
return;
}
result = _open_osfhandle((intptr_t) file, flags);
SET_REQ_RESULT(req, result);
fd = _open_osfhandle((intptr_t) file, flags);
if (fd < 0) {
/* The only known failure mode for _open_osfhandle() is EMFILE, in which
* case GetLastError() will return zero. However we'll try to handle other
* errors as well, should they ever occur.
*/
if (errno == EMFILE)
SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES);
else if (GetLastError() != ERROR_SUCCESS)
SET_REQ_WIN32_ERROR(req, GetLastError());
else
SET_REQ_WIN32_ERROR(req, UV_UNKNOWN);
return;
}
SET_REQ_RESULT(req, fd);
return;
einval: