darwin: fix thread cancellation fd leak
The close() system call tests for thread cancellation first. That has the unfortunate side effect of aborting the sytem call with EINTR without actually closing the file descriptor when the thread is in the "cancel" state. Work around that by calling close$NOCANCEL(). This might well qualify as an academic bug because approximately no one uses thread cancellation but let's aim for correctness anyway. PR-URL: https://github.com/libuv/libuv/pull/2291 Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
parent
c4e9657d59
commit
9063c27f92
@ -510,6 +510,23 @@ skip:
|
||||
}
|
||||
|
||||
|
||||
/* close() on macos has the "interesting" quirk that it fails with EINTR
|
||||
* without closing the file descriptor when a thread is in the cancel state.
|
||||
* That's why libuv calls close$NOCANCEL() instead.
|
||||
*/
|
||||
int uv__close_nocancel(int fd) {
|
||||
#if defined(__APPLE__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
|
||||
extern int close$NOCANCEL(int);
|
||||
return close$NOCANCEL(fd);
|
||||
#pragma GCC diagnostic pop
|
||||
#else
|
||||
return close(fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int uv__close_nocheckstdio(int fd) {
|
||||
int saved_errno;
|
||||
int rc;
|
||||
@ -517,7 +534,7 @@ int uv__close_nocheckstdio(int fd) {
|
||||
assert(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */
|
||||
|
||||
saved_errno = errno;
|
||||
rc = close(fd);
|
||||
rc = uv__close_nocancel(fd);
|
||||
if (rc == -1) {
|
||||
rc = UV__ERR(errno);
|
||||
if (rc == UV_EINTR || rc == UV__ERR(EINPROGRESS))
|
||||
|
||||
@ -145,7 +145,7 @@ extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
|
||||
static int uv__fs_close(int fd) {
|
||||
int rc;
|
||||
|
||||
rc = close(fd);
|
||||
rc = uv__close_nocancel(fd);
|
||||
if (rc == -1)
|
||||
if (errno == EINTR || errno == EINPROGRESS)
|
||||
rc = 0; /* The close is in progress, not an error. */
|
||||
|
||||
@ -183,6 +183,7 @@ int uv__nonblock_ioctl(int fd, int set);
|
||||
int uv__nonblock_fcntl(int fd, int set);
|
||||
int uv__close(int fd); /* preserves errno */
|
||||
int uv__close_nocheckstdio(int fd);
|
||||
int uv__close_nocancel(int fd);
|
||||
int uv__socket(int domain, int type, int protocol);
|
||||
ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags);
|
||||
void uv__make_close_pending(uv_handle_t* handle);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user