diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index bb2b3de81f63..81b859510fc1 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -1357,6 +1357,18 @@ TSAN_INTERCEPTOR(int, __close, int fd) { return REAL(__close)(fd); } +// glibc guts +TSAN_INTERCEPTOR(void, __res_iclose, void *state, bool free_addr) { + SCOPED_TSAN_INTERCEPTOR(__res_iclose, state, free_addr); + int fds[64]; + int cnt = ExtractResolvFDs(state, fds, ARRAY_SIZE(fds)); + for (int i = 0; i < cnt; i++) { + if (fds[i] > 0) + FdClose(thr, pc, fds[i]); + } + REAL(__res_iclose)(state, free_addr); +} + TSAN_INTERCEPTOR(int, pipe, int *pipefd) { SCOPED_TSAN_INTERCEPTOR(pipe, pipefd); int res = REAL(pipe)(pipefd); @@ -1932,6 +1944,8 @@ void InitializeInterceptors() { TSAN_INTERCEPT(epoll_create); TSAN_INTERCEPT(epoll_create1); TSAN_INTERCEPT(close); + TSAN_INTERCEPT(__close); + TSAN_INTERCEPT(__res_iclose); TSAN_INTERCEPT(pipe); TSAN_INTERCEPT(pipe2); diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h index c859c3e85b19..87b41d96f56c 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform.h +++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h @@ -151,6 +151,7 @@ bool IsGlobalVar(uptr addr); uptr GetTlsSize(); void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, uptr *tls_addr, uptr *tls_size); +int ExtractResolvFDs(void *state, int *fds, int nfd); } // namespace __tsan diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc index 6cc424975125..a8664731c3cd 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc @@ -40,6 +40,8 @@ #include #include #include +#define __need_res_state +#include extern "C" int arch_prctl(int code, __sanitizer::uptr *addr); @@ -289,6 +291,19 @@ bool IsGlobalVar(uptr addr) { return g_data_start && addr >= g_data_start && addr < g_data_end; } +#ifndef TSAN_GO +int ExtractResolvFDs(void *state, int *fds, int nfd) { + int cnt = 0; + __res_state *statp = (__res_state*)state; + for (int i = 0; i < MAXNS && cnt < nfd; i++) { + if (statp->_u._ext.nsaddrs[i] && statp->_u._ext.nssocks[i] != -1) + fds[cnt++] = statp->_u._ext.nssocks[i]; + } + return cnt; +} +#endif + + } // namespace __tsan #endif // #ifdef __linux__ diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.cc b/compiler-rt/lib/tsan/rtl/tsan_stat.cc index 9e4baae0c5ab..7de1fec7b20a 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_stat.cc @@ -215,6 +215,7 @@ void StatOutput(u64 *stat) { name[StatInt_epoll_create1] = " epoll_create1 "; name[StatInt_close] = " close "; name[StatInt___close] = " __close "; + name[StatInt___res_iclose] = " __res_iclose "; name[StatInt_pipe] = " pipe "; name[StatInt_pipe2] = " pipe2 "; name[StatInt_read] = " read "; diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.h b/compiler-rt/lib/tsan/rtl/tsan_stat.h index 7ee31c14d246..9ef557abbd2a 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.h +++ b/compiler-rt/lib/tsan/rtl/tsan_stat.h @@ -210,6 +210,7 @@ enum StatType { StatInt_epoll_create1, StatInt_close, StatInt___close, + StatInt___res_iclose, StatInt_pipe, StatInt_pipe2, StatInt_read,