[llvm-commits] [compiler-rt] r169621 - in /compiler-rt/trunk/lib/tsan: lit_tests/fd_close_norace.cc lit_tests/fd_pipe_race.cc lit_tests/fd_socket_norace.cc lit_tests/fd_stdout_race.cc rtl/tsan_interceptors.cc rtl/tsan_stat.cc rtl/tsan_stat.h
Dmitry Vyukov
dvyukov at google.com
Fri Dec 7 10:30:40 PST 2012
Author: dvyukov
Date: Fri Dec 7 12:30:40 2012
New Revision: 169621
URL: http://llvm.org/viewvc/llvm-project?rev=169621&view=rev
Log:
tsan: more fd interceptors + bug fixes + tests
Added:
compiler-rt/trunk/lib/tsan/lit_tests/fd_close_norace.cc
compiler-rt/trunk/lib/tsan/lit_tests/fd_socket_norace.cc
compiler-rt/trunk/lib/tsan/lit_tests/fd_stdout_race.cc
Modified:
compiler-rt/trunk/lib/tsan/lit_tests/fd_pipe_race.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
Added: compiler-rt/trunk/lib/tsan/lit_tests/fd_close_norace.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/fd_close_norace.cc?rev=169621&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/fd_close_norace.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/fd_close_norace.cc Fri Dec 7 12:30:40 2012
@@ -0,0 +1,32 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+void *Thread1(void *x) {
+ int f = open("/dev/random", O_RDONLY);
+ close(f);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ sleep(1);
+ int f = open("/dev/random", O_RDONLY);
+ close(f);
+ return NULL;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
+
+
Modified: compiler-rt/trunk/lib/tsan/lit_tests/fd_pipe_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/fd_pipe_race.cc?rev=169621&r1=169620&r2=169621&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/fd_pipe_race.cc (original)
+++ compiler-rt/trunk/lib/tsan/lit_tests/fd_pipe_race.cc Fri Dec 7 12:30:40 2012
@@ -27,10 +27,10 @@
}
// CHECK: WARNING: ThreadSanitizer: data race
-// CHECK: Write of size 1
+// CHECK: Write of size 8
// CHECK: #0 close
// CHECK: #1 Thread2
-// CHECK: Previous read of size 1
+// CHECK: Previous read of size 8
// CHECK: #0 write
// CHECK: #1 Thread1
Added: compiler-rt/trunk/lib/tsan/lit_tests/fd_socket_norace.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/fd_socket_norace.cc?rev=169621&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/fd_socket_norace.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/fd_socket_norace.cc Fri Dec 7 12:30:40 2012
@@ -0,0 +1,51 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+struct sockaddr_in addr;
+int X;
+
+void *ClientThread(void *x) {
+ X = 42;
+ int c = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (connect(c, (struct sockaddr*)&addr, sizeof(addr))) {
+ perror("connect");
+ exit(1);
+ }
+ if (send(c, "a", 1, 0) != 1) {
+ perror("send");
+ exit(1);
+ }
+ close(c);
+ return NULL;
+}
+
+int main() {
+ int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ addr.sin_family = AF_INET;
+ inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
+ addr.sin_port = INADDR_ANY;
+ socklen_t len = sizeof(addr);
+ bind(s, (sockaddr*)&addr, len);
+ getsockname(s, (sockaddr*)&addr, &len);
+ listen(s, 10);
+ pthread_t t;
+ pthread_create(&t, 0, ClientThread, 0);
+ int c = accept(s, 0, 0);
+ char buf;
+ while (read(c, &buf, 1) != 1) {
+ }
+ X = 43;
+ close(c);
+ close(s);
+ pthread_join(t, 0);
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
+
Added: compiler-rt/trunk/lib/tsan/lit_tests/fd_stdout_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/fd_stdout_race.cc?rev=169621&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/fd_stdout_race.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/fd_stdout_race.cc Fri Dec 7 12:30:40 2012
@@ -0,0 +1,41 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int X;
+
+void *Thread1(void *x) {
+ sleep(1);
+ int f = open("/dev/random", O_RDONLY);
+ char buf;
+ read(f, &buf, 1);
+ close(f);
+ X = 42;
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ X = 43;
+ write(STDOUT_FILENO, "a", 1);
+ return NULL;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 4
+// CHECK: #0 Thread1
+// CHECK: Previous write of size 4
+// CHECK: #0 Thread2
+
+
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=169621&r1=169620&r2=169621&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Fri Dec 7 12:30:40 2012
@@ -309,8 +309,8 @@
}
enum FdType {
- FdNone, // Does not require any sync.
FdGlobal, // Something we don't know about, global sync.
+ FdNone, // Does not require any sync.
FdFile,
FdSock,
FdPipe,
@@ -338,6 +338,9 @@
static FdContext fdctx;
static void FdInit() {
+ fdctx.desc[0].type = FdNone;
+ fdctx.desc[1].type = FdNone;
+ fdctx.desc[2].type = FdNone;
}
static void *FdAddr(int fd) {
@@ -365,19 +368,19 @@
static void FdAcquire(ThreadState *thr, uptr pc, int fd) {
void *addr = FdAddr(fd);
DPrintf("#%d: FdAcquire(%d) -> %p\n", thr->tid, fd, addr);
- if (addr) {
+ if (addr)
Acquire(thr, pc, (uptr)addr);
- MemoryRead1Byte(thr, pc, (uptr)addr);
- }
+ if (fd < FdContext::kMaxFds)
+ MemoryRead8Byte(thr, pc, (uptr)&fdctx.desc[fd].sync);
}
static void FdRelease(ThreadState *thr, uptr pc, int fd) {
void *addr = FdAddr(fd);
DPrintf("#%d: FdRelease(%d) -> %p\n", thr->tid, fd, addr);
- if (addr) {
+ if (addr)
Release(thr, pc, (uptr)addr);
- MemoryRead1Byte(thr, pc, (uptr)addr);
- }
+ if (fd < FdContext::kMaxFds)
+ MemoryRead8Byte(thr, pc, (uptr)&fdctx.desc[fd].sync);
}
static void FdClose(ThreadState *thr, uptr pc, int fd) {
@@ -385,14 +388,47 @@
return;
void *addr = FdAddr(fd);
if (addr) {
- // To catch races between fd usage and close.
- MemoryWrite1Byte(thr, pc, (uptr)addr);
SyncVar *s = CTX()->synctab.GetAndRemove(thr, pc, (uptr)addr);
if (s)
DestroyAndFree(s);
}
FdDesc *desc = &fdctx.desc[fd];
- desc->type = FdNone;
+ // FIXME(dvyukov): change to FdNone once we handle all fd operations.
+ desc->type = FdGlobal;
+ // To catch races between fd usage and close.
+ MemoryWrite8Byte(thr, pc, (uptr)&desc->sync);
+}
+
+static void FdCreateFile(ThreadState *thr, uptr pc, int fd) {
+ if (fd >= FdContext::kMaxFds)
+ return;
+ FdDesc *desc = &fdctx.desc[fd];
+ desc->type = FdFile;
+ // To catch races between fd usage and open.
+ MemoryRangeImitateWrite(thr, pc, (uptr)&desc->sync, sizeof(desc->sync));
+}
+
+static void FdDup(ThreadState *thr, uptr pc, int oldfd, int newfd) {
+ if (oldfd >= FdContext::kMaxFds || newfd >= FdContext::kMaxFds) {
+ if (oldfd < FdContext::kMaxFds) {
+ // FIXME(dvyukov): here we lose old sync object associated with the fd,
+ // this can lead to false positives.
+ FdDesc *odesc = &fdctx.desc[oldfd];
+ odesc->type = FdGlobal;
+ }
+ if (newfd < FdContext::kMaxFds) {
+ FdClose(thr, pc, newfd);
+ FdDesc *ndesc = &fdctx.desc[newfd];
+ ndesc->type = FdGlobal;
+ }
+ return;
+ }
+
+ FdClose(thr, pc, newfd);
+ FdDesc *ndesc = &fdctx.desc[newfd];
+ ndesc->type = FdFile;
+ // To catch races between fd usage and open.
+ MemoryRangeImitateWrite(thr, pc, (uptr)&ndesc->sync, sizeof(ndesc->sync));
}
static void FdCreatePipe(ThreadState *thr, uptr pc, int rfd, int wfd) {
@@ -405,21 +441,19 @@
FdDesc *wdesc = &fdctx.desc[wfd];
wdesc->type = FdGlobal;
}
+ return;
}
+
FdDesc *rdesc = &fdctx.desc[rfd];
rdesc->type = FdPipe;
- void *raddr = FdAddr(rfd);
- if (raddr) {
- // To catch races between fd usage and open.
- MemoryWrite1Byte(thr, pc, (uptr)raddr);
- }
+ // To catch races between fd usage and open.
+ MemoryRangeImitateWrite(thr, pc, (uptr)&rdesc->sync, sizeof(rdesc->sync));
+
FdDesc *wdesc = &fdctx.desc[wfd];
wdesc->type = FdPipe;
- void *waddr = FdAddr(wfd);
- if (waddr) {
- // To catch races between fd usage and open.
- MemoryWrite1Byte(thr, pc, (uptr)waddr);
- }
+ // To catch races between fd usage and open.
+ MemoryRangeImitateWrite(thr, pc, (uptr)&wdesc->sync, sizeof(rdesc->sync));
+
DPrintf("#%d: FdCreatePipe(%d, %d) -> (%p, %p)\n",
thr->tid, rfd, wfd, raddr, waddr);
}
@@ -1186,6 +1220,46 @@
return res;
}
+TSAN_INTERCEPTOR(int, open, const char *name, int flags, int mode) {
+ SCOPED_TSAN_INTERCEPTOR(open, name, flags, mode);
+ int fd = REAL(open)(name, flags, mode);
+ if (fd >= 0)
+ FdCreateFile(thr, pc, fd);
+ return fd;
+}
+
+TSAN_INTERCEPTOR(int, creat, const char *name, int mode) {
+ SCOPED_TSAN_INTERCEPTOR(creat, name, mode);
+ int fd = REAL(creat)(name, mode);
+ if (fd >= 0)
+ FdCreateFile(thr, pc, fd);
+ return fd;
+}
+
+TSAN_INTERCEPTOR(int, dup, int oldfd) {
+ SCOPED_TSAN_INTERCEPTOR(dup, oldfd);
+ int newfd = REAL(dup)(oldfd);
+ if (newfd >= 0 && newfd != oldfd)
+ FdDup(thr, pc, oldfd, newfd);
+ return newfd;
+}
+
+TSAN_INTERCEPTOR(int, dup2, int oldfd, int newfd) {
+ SCOPED_TSAN_INTERCEPTOR(dup2, oldfd, newfd);
+ int newfd2 = REAL(dup2)(oldfd, newfd);
+ if (newfd2 >= 0 && newfd2 != oldfd)
+ FdDup(thr, pc, oldfd, newfd2);
+ return newfd2;
+}
+
+TSAN_INTERCEPTOR(int, dup3, int oldfd, int newfd, int flags) {
+ SCOPED_TSAN_INTERCEPTOR(dup3, oldfd, newfd, flags);
+ int newfd2 = REAL(dup3)(oldfd, newfd, flags);
+ if (newfd2 >= 0 && newfd2 != oldfd)
+ FdDup(thr, pc, oldfd, newfd2);
+ return newfd2;
+}
+
TSAN_INTERCEPTOR(int, close, int fd) {
SCOPED_TSAN_INTERCEPTOR(close, fd);
FdClose(thr, pc, fd);
@@ -1694,6 +1768,11 @@
TSAN_INTERCEPT(sem_post);
TSAN_INTERCEPT(sem_getvalue);
+ TSAN_INTERCEPT(open);
+ TSAN_INTERCEPT(creat);
+ TSAN_INTERCEPT(dup);
+ TSAN_INTERCEPT(dup2);
+ TSAN_INTERCEPT(dup3);
TSAN_INTERCEPT(close);
TSAN_INTERCEPT(pipe);
TSAN_INTERCEPT(pipe2);
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc?rev=169621&r1=169620&r2=169621&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc Fri Dec 7 12:30:40 2012
@@ -181,6 +181,11 @@
name[StatInt_sem_timedwait] = " sem_timedwait ";
name[StatInt_sem_post] = " sem_post ";
name[StatInt_sem_getvalue] = " sem_getvalue ";
+ name[StatInt_open] = " open ";
+ name[StatInt_creat] = " creat ";
+ name[StatInt_dup] = " dup ";
+ name[StatInt_dup2] = " dup2 ";
+ name[StatInt_dup3] = " dup3 ";
name[StatInt_close] = " close ";
name[StatInt_pipe] = " pipe ";
name[StatInt_pipe2] = " pipe2 ";
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h?rev=169621&r1=169620&r2=169621&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h Fri Dec 7 12:30:40 2012
@@ -176,6 +176,11 @@
StatInt_sem_timedwait,
StatInt_sem_post,
StatInt_sem_getvalue,
+ StatInt_open,
+ StatInt_creat,
+ StatInt_dup,
+ StatInt_dup2,
+ StatInt_dup3,
StatInt_close,
StatInt_pipe,
StatInt_pipe2,
More information about the llvm-commits
mailing list