Skip to content

Commit afabdf3

Browse files
soheilhytorvalds
authored andcommitted
epoll: add a selftest for epoll timeout race
Add a test case to ensure an event is observed by at least one poller when an epoll timeout is used. Signed-off-by: Guantao Liu <guantaol@google.com> Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Khazhismel Kumykov <khazhy@google.com> Acked-by: Willem de Bruijn <willemb@google.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Davidlohr Bueso <dave@stgolabs.net> Link: https://lkml.kernel.org/r/20201028180202.952079-2-soheil.kdev@gmail.com Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent f8f6ae5 commit afabdf3

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

tools/testing/selftests/filesystems/epoll/epoll_wakeup_test.c

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3282,4 +3282,99 @@ TEST(epoll60)
32823282
close(ctx.epfd);
32833283
}
32843284

3285+
struct epoll61_ctx {
3286+
int epfd;
3287+
int evfd;
3288+
};
3289+
3290+
static void *epoll61_write_eventfd(void *ctx_)
3291+
{
3292+
struct epoll61_ctx *ctx = ctx_;
3293+
int64_t l = 1;
3294+
3295+
usleep(10950);
3296+
write(ctx->evfd, &l, sizeof(l));
3297+
return NULL;
3298+
}
3299+
3300+
static void *epoll61_epoll_with_timeout(void *ctx_)
3301+
{
3302+
struct epoll61_ctx *ctx = ctx_;
3303+
struct epoll_event events[1];
3304+
int n;
3305+
3306+
n = epoll_wait(ctx->epfd, events, 1, 11);
3307+
/*
3308+
* If epoll returned the eventfd, write on the eventfd to wake up the
3309+
* blocking poller.
3310+
*/
3311+
if (n == 1) {
3312+
int64_t l = 1;
3313+
3314+
write(ctx->evfd, &l, sizeof(l));
3315+
}
3316+
return NULL;
3317+
}
3318+
3319+
static void *epoll61_blocking_epoll(void *ctx_)
3320+
{
3321+
struct epoll61_ctx *ctx = ctx_;
3322+
struct epoll_event events[1];
3323+
3324+
epoll_wait(ctx->epfd, events, 1, -1);
3325+
return NULL;
3326+
}
3327+
3328+
TEST(epoll61)
3329+
{
3330+
struct epoll61_ctx ctx;
3331+
struct epoll_event ev;
3332+
int i, r;
3333+
3334+
ctx.epfd = epoll_create1(0);
3335+
ASSERT_GE(ctx.epfd, 0);
3336+
ctx.evfd = eventfd(0, EFD_NONBLOCK);
3337+
ASSERT_GE(ctx.evfd, 0);
3338+
3339+
ev.events = EPOLLIN | EPOLLET | EPOLLERR | EPOLLHUP;
3340+
ev.data.ptr = NULL;
3341+
r = epoll_ctl(ctx.epfd, EPOLL_CTL_ADD, ctx.evfd, &ev);
3342+
ASSERT_EQ(r, 0);
3343+
3344+
/*
3345+
* We are testing a race. Repeat the test case 1000 times to make it
3346+
* more likely to fail in case of a bug.
3347+
*/
3348+
for (i = 0; i < 1000; i++) {
3349+
pthread_t threads[3];
3350+
int n;
3351+
3352+
/*
3353+
* Start 3 threads:
3354+
* Thread 1 sleeps for 10.9ms and writes to the evenfd.
3355+
* Thread 2 calls epoll with a timeout of 11ms.
3356+
* Thread 3 calls epoll with a timeout of -1.
3357+
*
3358+
* The eventfd write by Thread 1 should either wakeup Thread 2
3359+
* or Thread 3. If it wakes up Thread 2, Thread 2 writes on the
3360+
* eventfd to wake up Thread 3.
3361+
*
3362+
* If no events are missed, all three threads should eventually
3363+
* be joinable.
3364+
*/
3365+
ASSERT_EQ(pthread_create(&threads[0], NULL,
3366+
epoll61_write_eventfd, &ctx), 0);
3367+
ASSERT_EQ(pthread_create(&threads[1], NULL,
3368+
epoll61_epoll_with_timeout, &ctx), 0);
3369+
ASSERT_EQ(pthread_create(&threads[2], NULL,
3370+
epoll61_blocking_epoll, &ctx), 0);
3371+
3372+
for (n = 0; n < ARRAY_SIZE(threads); ++n)
3373+
ASSERT_EQ(pthread_join(threads[n], NULL), 0);
3374+
}
3375+
3376+
close(ctx.epfd);
3377+
close(ctx.evfd);
3378+
}
3379+
32853380
TEST_HARNESS_MAIN

0 commit comments

Comments
 (0)