Make Thread Sanitizer aware of file descriptor close in uv__close()

Thread Sanitizer can't intercept syscall(SYS_close, fd) that's used
instead of close(fd); on Linux.  That leads to false positives as Thread
Sanitizer thinks the descriptor is still being used by the thread.

clang defines pre- and post- syscall actions, so wrap the close
syscall() into the action macros.  For gcc, use close() from glibc
instead of the syscall. This allows the thread sanitizer to intercept
closing of the file descriptor when libuv is compiled with Thread
Sanitizer.

PR-URL: https://github.com/libuv/libuv/pull/3112
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
Ondřej Surý 2021-02-19 12:25:10 +01:00 committed by Santiago Gimeno
parent d2482ae121
commit c3fe3cf1bc
No known key found for this signature in database
GPG Key ID: F28C3C8DA33C03BE
2 changed files with 23 additions and 2 deletions

View File

@ -88,6 +88,10 @@ extern char** environ;
# define uv__accept4 accept4
#endif
#if defined(__linux__) && defined(__SANITIZE_THREAD__) && defined(__clang__)
# include <sanitizer/linux_syscall_hooks.h>
#endif
static int uv__run_pending(uv_loop_t* loop);
/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
@ -539,7 +543,13 @@ int uv__close_nocancel(int fd) {
return close$NOCANCEL$UNIX2003(fd);
#endif
#pragma GCC diagnostic pop
#elif defined(__linux__)
#elif defined(__linux__) && defined(__SANITIZE_THREAD__) && defined(__clang__)
long rc;
__sanitizer_syscall_pre_close(fd);
rc = syscall(SYS_close, fd);
__sanitizer_syscall_post_close(rc, fd);
return rc;
#elif defined(__linux__) && !defined(__SANITIZE_THREAD__)
return syscall(SYS_close, fd);
#else
return close(fd);
@ -1570,7 +1580,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) {
buf[*buflen] = '\0';
return 0;
}
}
/* Case iii). Search PATH environment variable */
cloned_path = NULL;

View File

@ -62,6 +62,17 @@
# include <AvailabilityMacros.h>
#endif
/*
* Define common detection for active Thread Sanitizer
* - clang uses __has_feature(thread_sanitizer)
* - gcc-7+ uses __SANITIZE_THREAD__
*/
#if defined(__has_feature)
# if __has_feature(thread_sanitizer)
# define __SANITIZE_THREAD__ 1
# endif
#endif
#if defined(PATH_MAX)
# define UV__PATH_MAX PATH_MAX
#else