[svn-commits] twilson: branch 1.8 r332320 - /branches/1.8/res/res_timing_timerfd.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Aug 17 12:35:31 CDT 2011


Author: twilson
Date: Wed Aug 17 12:35:27 2011
New Revision: 332320

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=332320
Log:
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-1842, ASTERISK-18197, AST-486, AST-495, AST-507
and possibly others.

Modified:
    branches/1.8/res/res_timing_timerfd.c

Modified: branches/1.8/res/res_timing_timerfd.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/res/res_timing_timerfd.c?view=diff&rev=332320&r1=332319&r2=332320
==============================================================================
--- branches/1.8/res/res_timing_timerfd.c (original)
+++ branches/1.8/res/res_timing_timerfd.c Wed Aug 17 12:35:27 2011
@@ -162,8 +162,32 @@
 {
 	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 @@
 		}
 	} 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);
 	}




More information about the svn-commits mailing list