summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2013-11-28 09:09:42 +0000
committerDmitry Vyukov <dvyukov@google.com>2013-11-28 09:09:42 +0000
commit8d1eb705c74e7b6ac0bbfab1e4f5e297315506f4 (patch)
tree29d0e2e692b456db2383d0632eb94a596e8b4313 /compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc
parent0fea3ad0c7414f7a90d7c3cbaf3bd6bfc7b173f0 (diff)
downloadbcm5719-llvm-8d1eb705c74e7b6ac0bbfab1e4f5e297315506f4.tar.gz
bcm5719-llvm-8d1eb705c74e7b6ac0bbfab1e4f5e297315506f4.zip
tsan: add support for passing file descriptors over UNIX domain sockets
tsan was missing new fd's arrived from recvmsg(), and thus was reporting false positives due to missed synchronization on the fd's llvm-svn: 195914
Diffstat (limited to 'compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc')
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc24
1 files changed, 24 insertions, 0 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc
index 906b5dc73be..282b2982fdd 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc
@@ -34,6 +34,7 @@
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
+#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/resource.h>
@@ -347,6 +348,9 @@ bool IsGlobalVar(uptr addr) {
}
#ifndef TSAN_GO
+// Extract file descriptors passed to glibc internal __res_iclose function.
+// This is required to properly "close" the fds, because we do not see internal
+// closes within glibc. The code is a pure hack.
int ExtractResolvFDs(void *state, int *fds, int nfd) {
int cnt = 0;
__res_state *statp = (__res_state*)state;
@@ -356,6 +360,26 @@ int ExtractResolvFDs(void *state, int *fds, int nfd) {
}
return cnt;
}
+
+// Extract file descriptors passed via UNIX domain sockets.
+// This is requried to properly handle "open" of these fds.
+// see 'man recvmsg' and 'man 3 cmsg'.
+int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
+ int res = 0;
+ msghdr *msg = (msghdr*)msgp;
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
+ for (; cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
+ continue;
+ int n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(fds[0]);
+ for (int i = 0; i < n; i++) {
+ fds[res++] = ((int*)CMSG_DATA(cmsg))[i];
+ if (res == nfd)
+ return res;
+ }
+ }
+ return res;
+}
#endif
OpenPOWER on IntegriCloud