[syslog-ng] bug in syslog-ng 3.9.1 triggered by bug in ivykis >= 0.40
Lennert Buytenhek
buytenh at wantstofly.org
Sat Apr 29 12:13:00 UTC 2017
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 at 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 at 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) {
More information about the syslog-ng
mailing list