diff options
author | Sylvain Henry <sylvain@haskus.fr> | 2020-04-22 15:50:10 +0200 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2020-04-22 23:17:34 -0400 |
commit | 8ea37b01b6ab16937f7b528b6bbae9fade9f1361 (patch) | |
tree | f463e948ce82ec572927e38349b4495b7d48b8c2 /rts/posix | |
parent | 125aa2b8b8bb402d7819c3a35255b65c15b8bf9a (diff) | |
download | haskell-8ea37b01b6ab16937f7b528b6bbae9fade9f1361.tar.gz |
RTS: workaround a Linux kernel bug in timerfd
Reading a timerfd may return 0: https://lkml.org/lkml/2019/8/16/335.
This is currently undocumented behavior and documentation "won't happen
anytime soon" (https://lkml.org/lkml/2020/2/13/295).
With this patch, we just ignore the result instead of crashing. It may
fix #18033 but we can't be sure because we don't have enough
information.
See also this discussion about the kernel bug:
https://github.com/Azure/sonic-swss-common/pull/302/files/1f070e7920c2e5d63316c0105bf4481e73d72dc9
Diffstat (limited to 'rts/posix')
-rw-r--r-- | rts/posix/itimer/Pthread.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/rts/posix/itimer/Pthread.c b/rts/posix/itimer/Pthread.c index d4b0342795..dd36137b72 100644 --- a/rts/posix/itimer/Pthread.c +++ b/rts/posix/itimer/Pthread.c @@ -122,10 +122,18 @@ static void *itimer_thread_func(void *_handle_tick) while (!exited) { if (USE_TIMERFD_FOR_ITIMER) { - if (read(timerfd, &nticks, sizeof(nticks)) != sizeof(nticks)) { - if (errno != EINTR) { - barf("Itimer: read(timerfd) failed: %s", strerror(errno)); - } + ssize_t r = read(timerfd, &nticks, sizeof(nticks)); + if ((r == 0) && (errno == 0)) { + /* r == 0 is expected only for non-blocking fd (in which case + * errno should be EAGAIN) but we use a blocking fd. + * + * Due to a kernel bug (cf https://lkml.org/lkml/2019/8/16/335) + * on some platforms we could see r == 0 and errno == 0. + */ + IF_DEBUG(scheduler, debugBelch("read(timerfd) returned 0 with errno=0. This is a known kernel bug. We just ignore it.")); + } + else if (r != sizeof(nticks) && errno != EINTR) { + barf("Itimer: read(timerfd) failed with %s and returned %zd", strerror(errno), r); } } else { if (rtsSleep(itimer_interval) != 0) { |