From c3fe3cf1bc78cd454cfa114a59f631b9bae5c0d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Fri, 19 Feb 2021 12:25:10 +0100 Subject: [PATCH] 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 --- src/unix/core.c | 14 ++++++++++++-- src/unix/internal.h | 11 +++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/unix/core.c b/src/unix/core.c index 63f268f7..15aa57d9 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -88,6 +88,10 @@ extern char** environ; # define uv__accept4 accept4 #endif +#if defined(__linux__) && defined(__SANITIZE_THREAD__) && defined(__clang__) +# include +#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; diff --git a/src/unix/internal.h b/src/unix/internal.h index 11ff659d..5593e494 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -62,6 +62,17 @@ # include #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