diff options
author | Terry Wilson <twilson@digium.com> | 2011-08-17 18:31:39 +0000 |
---|---|---|
committer | Terry Wilson <twilson@digium.com> | 2011-08-17 18:31:39 +0000 |
commit | c38cb9586377120b2aea5651b4df025cee315b60 (patch) | |
tree | 201db06d7b6a06b7b0b44d6c8b4a3b71ea7ad002 /res/res_timing_timerfd.c | |
parent | 265102faf89e95381910eb0b69a47e338f3baf63 (diff) |
Merged revisions 332321 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10
................
r332321 | twilson | 2011-08-17 13:09:49 -0500 (Wed, 17 Aug 2011) | 17 lines
Merged revisions 332320 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r332320 | twilson | 2011-08-17 12:35:27 -0500 (Wed, 17 Aug 2011) | 10 lines
Don't read from a disarmed or invalid timerfd
Numerous isues have been reported for deadlocks that are caused by
a blocking read in res_timing_timerfd on a file descriptor that will
never be written to. This patch adds some checks to make sure that
the timerfd is both valid and armed before calling read().
Should fix: ASTERISK-18142, ASTERISK-18166, ASTERISK-18197, AST-486,
AST-495, AST-507 and possibly others.
Review: https://reviewboard.asterisk.org/r/1361/
........
................
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@332337 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/res_timing_timerfd.c')
-rw-r--r-- | res/res_timing_timerfd.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/res/res_timing_timerfd.c b/res/res_timing_timerfd.c index 80e5ca8a5..81331a99f 100644 --- a/res/res_timing_timerfd.c +++ b/res/res_timing_timerfd.c @@ -162,8 +162,32 @@ static void timerfd_timer_ack(int handle, unsigned int quantity) { uint64_t expirations; int read_result = 0; + struct timerfd_timer *our_timer, find_helper = { + .handle = handle, + }; + + if (!(our_timer = ao2_find(timerfd_timers, &find_helper, OBJ_POINTER))) { + ast_log(LOG_ERROR, "Couldn't find a timer with handle %d\n", handle); + return; + } + + ao2_lock(our_timer); do { + struct itimerspec timer_status; + + if (timerfd_gettime(handle, &timer_status)) { + ast_log(LOG_ERROR, "Call to timerfd_gettime() error: %s\n", strerror(errno)); + expirations = 0; + break; + } + + if (timer_status.it_value.tv_sec == 0 && timer_status.it_value.tv_nsec == 0) { + ast_debug(1, "Avoiding read on disarmed timerfd %d\n", handle); + expirations = 0; + break; + } + read_result = read(handle, &expirations, sizeof(expirations)); if (read_result == -1) { if (errno == EINTR || errno == EAGAIN) { @@ -175,6 +199,9 @@ static void timerfd_timer_ack(int handle, unsigned int quantity) } } while (read_result != sizeof(expirations)); + ao2_unlock(our_timer); + ao2_ref(our_timer, -1); + if (expirations != quantity) { ast_debug(2, "Expected to acknowledge %u ticks but got %llu instead\n", quantity, (unsigned long long) expirations); } |