On Wed, Apr 26, 2017 at 08:49:04PM +0300, Lennert Buytenhek wrote:
A syslog-ng user tried to use syslog-ng with ivykis 0.41 and ran into the following issue:
https://github.com/buytenh/ivykis/issues/11
In a nutshell, syslog-ng seems to be registering an ivykis timer (iv_timer) with timeout tv_sec = 0, tv_nsec = 0, and ivykis >= 0.40 added support for timerfd_create, but due to a bug in ivykis, this {0, 0} timeout would get passed into timerfd_settime() verbatim, and timerfd_settime() interprets this zero timeout as a request to disable the timerfd, which would cause timer processing to stop.
I will release a new ivykis release with a workaround for this, but I figured that you'd probably want to know about this as well, as I don't think it makes sense for syslog-ng to be registering timers with an absolute timeout of zero.
FWIW, I just released ivykis 0.42 with the commit below, which fixes this issue. (And sorry, no, I don't have a syslog-ng backtrace, so I have no idea which code in syslog-ng is registering a timer with an expiry time of zero. :-( ) commit 580ea0f50c9ea1c537398bed1b1e3a861440c97f Author: Lennert Buytenhek <buytenh@wantstofly.org> Date: Wed Apr 26 22:28:20 2017 +0300 Fix ->set_poll_timeout() related bug with timers that expire at time zero. If the ivykis core decides to use ->set_poll_timeout() to offload the handling of a timer, the epoll_create(2) / port_create(3C) poll methods pass the given timeout directly into the timerfd_settime(2) / timer_settime(3C) system calls, but if an ivykis user has registered an iv_timer with an expiration time of (tv_sec, tv_nsec) = (0, 0), the *_settime() system calls will interpret such a zero timeout value as a request to disable the timer, and as a result, no timer handlers will be run. To work around this, we'll pass a timeout of (tv_sec, tv_nsec) = (0, 1) into these system calls if the next expiring timer expires at (0, 0). This bug was reported by and tracked down with the kind help of Brian De Wolf (github: bldewolf), who ran into this issue with syslog-ng 3.9.1. Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org> diff --git a/src/iv_fd_epoll.c b/src/iv_fd_epoll.c index 5517d19..c6b2285 100644 --- a/src/iv_fd_epoll.c +++ b/src/iv_fd_epoll.c @@ -388,6 +388,8 @@ iv_fd_epoll_timerfd_set_poll_timeout(struct iv_state *st, val.it_interval.tv_sec = 0; val.it_interval.tv_nsec = 0; val.it_value = *abs; + if (val.it_value.tv_sec == 0 && val.it_value.tv_nsec == 0) + val.it_value.tv_nsec = 1; ret = timerfd_settime(st->u.epoll.timer_fd, TFD_TIMER_ABSTIME, &val, NULL); diff --git a/src/iv_fd_port.c b/src/iv_fd_port.c index 2d427b5..510c948 100644 --- a/src/iv_fd_port.c +++ b/src/iv_fd_port.c @@ -296,6 +296,8 @@ iv_fd_port_set_poll_timeout(struct iv_state *st, const struct timespec *abs) val.it_interval.tv_sec = 0; val.it_interval.tv_nsec = 0; val.it_value = *abs; + if (val.it_value.tv_sec == 0 && val.it_value.tv_nsec == 0) + val.it_value.tv_nsec = 1; ret = timer_settime(st->u.port.timer_id, TIMER_ABSTIME, &val, NULL); if (ret < 0) {