mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-28 15:11:12 +00:00
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-18197, ASTERISK-18166, 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/branches/1.8@332320 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -162,8 +162,32 @@ static void timerfd_timer_ack(int handle, unsigned int quantity)
|
|||||||
{
|
{
|
||||||
uint64_t expirations;
|
uint64_t expirations;
|
||||||
int read_result = 0;
|
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 {
|
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));
|
read_result = read(handle, &expirations, sizeof(expirations));
|
||||||
if (read_result == -1) {
|
if (read_result == -1) {
|
||||||
if (errno == EINTR || errno == EAGAIN) {
|
if (errno == EINTR || errno == EAGAIN) {
|
||||||
@@ -175,6 +199,9 @@ static void timerfd_timer_ack(int handle, unsigned int quantity)
|
|||||||
}
|
}
|
||||||
} while (read_result != sizeof(expirations));
|
} while (read_result != sizeof(expirations));
|
||||||
|
|
||||||
|
ao2_unlock(our_timer);
|
||||||
|
ao2_ref(our_timer, -1);
|
||||||
|
|
||||||
if (expirations != quantity) {
|
if (expirations != quantity) {
|
||||||
ast_debug(2, "Expected to acknowledge %u ticks but got %llu instead\n", quantity, (unsigned long long) expirations);
|
ast_debug(2, "Expected to acknowledge %u ticks but got %llu instead\n", quantity, (unsigned long long) expirations);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user