From 20e774c62a0d7ae952e5c5f068215b148be0c7aa Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Thu, 5 Sep 2013 08:50:04 +0200 Subject: [PATCH] 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. --- src/win/fs.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/win/fs.c b/src/win/fs.c index 7275457e..a51f8f01 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -390,7 +390,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 */ @@ -502,8 +502,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: