Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tsan: avoid false positives related to epoll
An application can use the mere fact of epoll_wait returning an fd as synchronization with the write on the fd that triggered the notification. This pattern come up in an internal networking server (b/229276331). If an fd is added to epoll, setup a link from the fd to the epoll fd and use it for synchronization as well. Reviewed By: melver Differential Revision: https://reviews.llvm.org/D124518
- Loading branch information
Showing
4 changed files
with
83 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s | ||
|
||
// The test captures what some high-performance networking servers do. | ||
// One thread writes to an fd, and another just receives an epoll | ||
// notification about the write to synchronize with the first thread | ||
// w/o actually reading from the fd. | ||
|
||
#include "../test.h" | ||
#include <errno.h> | ||
#include <sys/epoll.h> | ||
#include <sys/eventfd.h> | ||
|
||
int main() { | ||
int efd = epoll_create(1); | ||
if (efd == -1) | ||
exit(printf("epoll_create failed: %d\n", errno)); | ||
int fd = eventfd(0, 0); | ||
if (fd == -1) | ||
exit(printf("eventfd failed: %d\n", errno)); | ||
epoll_event event = {.events = EPOLLIN | EPOLLET}; | ||
if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event)) | ||
exit(printf("epoll_ctl failed: %d\n", errno)); | ||
pthread_t th; | ||
pthread_create( | ||
&th, nullptr, | ||
+[](void *arg) -> void * { | ||
long long to_add = 1; | ||
if (write((long)arg, &to_add, sizeof(to_add)) != sizeof(to_add)) | ||
exit(printf("write failed: %d\n", errno)); | ||
return nullptr; | ||
}, | ||
(void *)(long)fd); | ||
struct epoll_event events[1] = {}; | ||
if (epoll_wait(efd, events, 1, -1) != 1) | ||
exit(printf("epoll_wait failed: %d\n", errno)); | ||
close(fd); | ||
pthread_join(th, nullptr); | ||
close(efd); | ||
fprintf(stderr, "DONE\n"); | ||
} | ||
|
||
// CHECK: DONE |