61 lines · cpp
1// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s2#include "test.h"3#include <sys/types.h>4#include <sys/stat.h>5#include <fcntl.h>6#include <errno.h>7 8// dup2(oldfd, newfd) races with read(newfd).9// This is not reported as race because:10// 1. Some software dups a closed pipe in place of a socket before closing11// the socket (to prevent races actually).12// 2. Some daemons dup /dev/null in place of stdin/stdout.13 14int fd;15 16void *Thread(void *x) {17 char buf;18 int n = read(fd, &buf, 1);19 if (n != 1) {20 // This read can "legitimately" fail regardless of the fact that glibc claims21 // that "there is no instant in the middle of calling dup2 at which new is22 // closed and not yet a duplicate of old". Strace of the failing runs23 // looks as follows:24 //25 // [pid 122196] open("/dev/urandom", O_RDONLY) = 326 // [pid 122196] open("/dev/urandom", O_RDONLY) = 427 // Process 122382 attached28 // [pid 122382] read(3, <unfinished ...>29 // [pid 122196] dup2(4, 3 <unfinished ...>30 // [pid 122382] <... read resumed> 0x7fcd139960b7, 1) = -1 EBADF (Bad file descriptor)31 // [pid 122196] <... dup2 resumed> ) = 332 // read failed: n=-1 errno=933 //34 // The failing read does not interfere with what this test tests,35 // so we just ignore the failure.36 //37 // exit(printf("read failed: n=%d errno=%d\n", n, errno));38 }39 return 0;40}41 42int main() {43 fd = open("/dev/urandom", O_RDONLY);44 int fd2 = open("/dev/urandom", O_RDONLY);45 if (fd == -1 || fd2 == -1)46 exit(printf("open failed\n"));47 pthread_t th;48 pthread_create(&th, 0, Thread, 0);49 if (dup2(fd2, fd) == -1)50 exit(printf("dup2 failed\n"));51 pthread_join(th, 0);52 if (close(fd) == -1)53 exit(printf("close failed\n"));54 if (close(fd2) == -1)55 exit(printf("close failed\n"));56 fprintf(stderr, "DONE\n");57}58 59// CHECK-NOT: WARNING: ThreadSanitizer: data race60// CHECK: DONE61