[asterisk-commits] bebuild: tag 11.4.0-rc2 r388174 - in /tags/11.4.0-rc2: ./ apps/ main/ res/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu May 9 09:21:33 CDT 2013


Author: bebuild
Date: Thu May  9 09:21:31 2013
New Revision: 388174

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=388174
Log:
Merge blockers for 11.4.0-rc2

(issue ASTERISK-21356)
Merged r386286

(issue ASTERISK-21738)
Merged r388108

(issue ASTERISK-21389)
Merged r386159

(issue ASTERISK-21394)
Merged r387038

(issue ASTERISK-21429)
Merged r385917

Modified:
    tags/11.4.0-rc2/   (props changed)
    tags/11.4.0-rc2/ChangeLog
    tags/11.4.0-rc2/apps/app_queue.c
    tags/11.4.0-rc2/main/channel.c
    tags/11.4.0-rc2/main/devicestate.c
    tags/11.4.0-rc2/main/features.c
    tags/11.4.0-rc2/res/res_jabber.c
    tags/11.4.0-rc2/res/res_timing_pthread.c

Propchange: tags/11.4.0-rc2/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.

Propchange: tags/11.4.0-rc2/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu May  9 09:21:31 2013
@@ -1,1 +1,2 @@
+/branches/11:385917,386159,386286,387038,388108
 /certified/branches/1.8.15:382389

Modified: tags/11.4.0-rc2/ChangeLog
URL: http://svnview.digium.com/svn/asterisk/tags/11.4.0-rc2/ChangeLog?view=diff&rev=388174&r1=388173&r2=388174
==============================================================================
--- tags/11.4.0-rc2/ChangeLog (original)
+++ tags/11.4.0-rc2/ChangeLog Thu May  9 09:21:31 2013
@@ -1,3 +1,94 @@
+2013-05-09  Asterisk Development Team <asteriskteam at digium.com>
+
+	* Asterisk 11.4.0-rc2 Released.
+
+	* Fix Segfault In app_queue When "persistentmembers" Is Enabled And
+	  Using Realtime
+
+	  When the "ignorebusy" setting was deprecated, we added some code to
+	  allow us to be compatible with older setups that are still using the
+	  "ignorebusy" setting instead of "ringinuse".  We set a char *variable
+	  with the column name to use, which helps the realtime functions to
+	  use the correct column in their SQL queries.  When "persistentmembers"
+	  is enabled, we are not setting this variable before the realtime
+	  functions were called to load members.  This results in the variable
+	  being NULL and therefore causing a segfault when loading members
+	  during the module's process of loading.
+
+	  The solution was to move the code that sets that variable to be
+	  before these realtime functions are called during the loading of the
+	  module.
+
+	* Distributed Device State broken at sites using res_xmpp or res_jabber
+	  where Secuity Advisory AST-2012-015 is inplace
+
+	  res_jabber/res_xmpp were not adding AST_EVENT_IE_CACHABLE to the
+	  event as each message came in, then devstate_change_collector_cb()
+	  was unable to find AST_EVENT_IE_CACHABLE in the event, so defaulted
+	  incorrectly to AST_DEVSTATE_NOT_CACHABLE.
+
+	* Fix CDR not being created during an externally initiated blind
+	  transfer
+
+	  Way back when in the dark days of Asterisk 1.8.9, blind transferring
+	  a call in a context that included the 'h' extension would
+	  inadvertently execute the hangup code logic on the transferred
+	  channel. This was a "bad thing". The fix was to properly check for
+	  the softhangup flags on the channel and only execute the 'h'
+	  extension logic (and, in later versions, hangup handler logic) if
+	  the channel was well and truly dead (Jim).
+
+	  Unfortunately, CDRs are fickle. Setting the softhangup flag when we
+	  detected that the channel was leaving the bridge (but not to die)
+	  caused some crucial snippet of CDR code, lying in ambush in the
+	  middle of the bridging code, to not get executed. This had the
+	  effect of blowing away one of the CDRs that is typically created
+	  during a blind transfer.
+
+	  While we live and die by the adage "don't touch CDRs in release
+	  branches", this was our bad. The attached patch restores the CDR
+	  behavior, and still manages to not run the 'h' extension during a
+	  blind transfer (at least not when it's supposed to).
+
+	  Thanks to Steve Davies for diagnosing this and providing a fix.
+
+	* Prevent res_timing_pthread from blocking callers
+
+	  There were several reports of deadlock when using res_timing_pthread.
+	  Backtraces indicated that one thread was blocked waiting for the
+	  write to the pipe to complete and this thread held the container lock
+	  for the timers.  Therefore any thread that wanted to create a new
+	  timer or read an existing timer would block waiting for either the
+	  timer lock or the container lock and deadlock ensued.
+
+	  This patch changes the way the pipe is used to eliminate this source
+	  of deadlocks:
+
+	  1) The pipe is placed in non-blocking mode so that it would never
+	     block even if the following changes someone fail...
+
+	  2) Instead of writing bytes into the pipe for each "tick" that's
+	     fired the pipe now has two states--signaled and unsignaled. If
+	     signaled, the pipe is hot and any pollers of the read side
+	     filedescriptor will be woken up. If unsigned the pipe is idle.
+	     This eliminates even the chance of filling up the pipe and reduces
+	     the potential overhead of calling unnecessary writes.
+
+	  3) Since we're tracking the signaled / unsignaled state, we can
+	  eliminate the exta poll system call for every firing because we know
+	  that there is data to be read.
+
+	* Fix crash when AMI redirect action redirects two channels out of a
+	  bridge.
+
+	  The two party bridging loops were changing the bridge peer pointers
+	  without the channel locks held.  Thus when ast_channel_massquerade()
+	  tested and used the pointer there is a small window of opportunity
+	  for the pointers to become NULL even though the masquerade code has
+	  the channels locked.
+
+
+
 2013-03-28  Asterisk Development Team <asteriskteam at digium.com>
 
 	* Asterisk 11.4.0-rc1 Released.

Modified: tags/11.4.0-rc2/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/tags/11.4.0-rc2/apps/app_queue.c?view=diff&rev=388174&r1=388173&r2=388174
==============================================================================
--- tags/11.4.0-rc2/apps/app_queue.c (original)
+++ tags/11.4.0-rc2/apps/app_queue.c Thu May  9 09:21:31 2013
@@ -9874,6 +9874,31 @@
 	if (reload_handler(0, &mask, NULL))
 		return AST_MODULE_LOAD_DECLINE;
 
+	ast_realtime_require_field("queue_members", "paused", RQ_INTEGER1, 1, "uniqueid", RQ_UINTEGER2, 5, SENTINEL);
+
+	/*
+	 * This section is used to determine which name for 'ringinuse' to use in realtime members
+	 * Necessary for supporting older setups.
+	 */
+	member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name LIKE", "%", SENTINEL);
+	if (!member_config) {
+		realtime_ringinuse_field = "ringinuse";
+	} else {
+		const char *config_val;
+		if ((config_val = ast_variable_retrieve(member_config, NULL, "ringinuse"))) {
+			ast_log(LOG_NOTICE, "ringinuse field entries found in queue_members table. Using 'ringinuse'\n");
+			realtime_ringinuse_field = "ringinuse";
+		} else if ((config_val = ast_variable_retrieve(member_config, NULL, "ignorebusy"))) {
+			ast_log(LOG_NOTICE, "ignorebusy field found in queue_members table with no ringinuse field. Using 'ignorebusy'\n");
+			realtime_ringinuse_field = "ignorebusy";
+		} else {
+			ast_log(LOG_NOTICE, "No entries were found for ringinuse/ignorebusy in queue_members table. Using 'ringinuse'\n");
+			realtime_ringinuse_field = "ringinuse";
+		}
+	}
+
+	ast_config_destroy(member_config);
+
 	if (queue_persistent_members)
 		reload_queue_members();
 
@@ -9917,31 +9942,6 @@
 
 	ast_extension_state_add(NULL, NULL, extension_state_cb, NULL);
 
-	ast_realtime_require_field("queue_members", "paused", RQ_INTEGER1, 1, "uniqueid", RQ_UINTEGER2, 5, SENTINEL);
-
-	/*
-	 * This section is used to determine which name for 'ringinuse' to use in realtime members
-	 * Necessary for supporting older setups.
-	 */
-	member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name LIKE", "%", SENTINEL);
-	if (!member_config) {
-		realtime_ringinuse_field = "ringinuse";
-	} else {
-		const char *config_val;
-		if ((config_val = ast_variable_retrieve(member_config, NULL, "ringinuse"))) {
-			ast_log(LOG_NOTICE, "ringinuse field entries found in queue_members table. Using 'ringinuse'\n");
-			realtime_ringinuse_field = "ringinuse";
-		} else if ((config_val = ast_variable_retrieve(member_config, NULL, "ignorebusy"))) {
-			ast_log(LOG_NOTICE, "ignorebusy field found in queue_members table with no ringinuse field. Using 'ignorebusy'\n");
-			realtime_ringinuse_field = "ignorebusy";
-		} else {
-			ast_log(LOG_NOTICE, "No entries were found for ringinuse/ignorebusy in queue_members table. Using 'ringinuse'\n");
-			realtime_ringinuse_field = "ringinuse";
-		}
-	}
-
-	ast_config_destroy(member_config);
-
 	return res ? AST_MODULE_LOAD_DECLINE : 0;
 }
 

Modified: tags/11.4.0-rc2/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/tags/11.4.0-rc2/main/channel.c?view=diff&rev=388174&r1=388173&r2=388174
==============================================================================
--- tags/11.4.0-rc2/main/channel.c (original)
+++ tags/11.4.0-rc2/main/channel.c Thu May  9 09:21:31 2013
@@ -7549,8 +7549,11 @@
 				if (ast_channel_softhangup_internal_flag(c1) & AST_SOFTHANGUP_UNBRIDGE) {
 					ast_channel_clear_softhangup(c1, AST_SOFTHANGUP_UNBRIDGE);
 				}
+				ast_channel_lock_both(c0, c1);
 				ast_channel_internal_bridged_channel_set(c0, c1);
 				ast_channel_internal_bridged_channel_set(c1, c0);
+				ast_channel_unlock(c0);
+				ast_channel_unlock(c1);
 			}
 			continue;
 		}
@@ -7831,8 +7834,11 @@
 	}
 
 	/* Keep track of bridge */
+	ast_channel_lock_both(c0, c1);
 	ast_channel_internal_bridged_channel_set(c0, c1);
 	ast_channel_internal_bridged_channel_set(c1, c0);
+	ast_channel_unlock(c0);
+	ast_channel_unlock(c1);
 
 	ast_set_owners_and_peers(c0, c1);
 
@@ -7926,8 +7932,11 @@
 			if (ast_channel_softhangup_internal_flag(c1) & AST_SOFTHANGUP_UNBRIDGE) {
 				ast_channel_clear_softhangup(c1, AST_SOFTHANGUP_UNBRIDGE);
 			}
+			ast_channel_lock_both(c0, c1);
 			ast_channel_internal_bridged_channel_set(c0, c1);
 			ast_channel_internal_bridged_channel_set(c1, c0);
+			ast_channel_unlock(c0);
+			ast_channel_unlock(c1);
 			ast_debug(1, "Unbridge signal received. Ending native bridge.\n");
 			continue;
 		}
@@ -7973,8 +7982,11 @@
 					continue;
 				}
 
+				ast_channel_lock_both(c0, c1);
 				ast_channel_internal_bridged_channel_set(c0, NULL);
 				ast_channel_internal_bridged_channel_set(c1, NULL);
+				ast_channel_unlock(c0);
+				ast_channel_unlock(c1);
 				ast_format_cap_destroy(o0nativeformats);
 				ast_format_cap_destroy(o1nativeformats);
 				return res;
@@ -8031,8 +8043,11 @@
 	ast_indicate(c0, AST_CONTROL_SRCUPDATE);
 	ast_indicate(c1, AST_CONTROL_SRCUPDATE);
 
+	ast_channel_lock_both(c0, c1);
 	ast_channel_internal_bridged_channel_set(c0, NULL);
 	ast_channel_internal_bridged_channel_set(c1, NULL);
+	ast_channel_unlock(c0);
+	ast_channel_unlock(c1);
 
 	manager_bridge_event(0, 1, c0, c1);
 	ast_debug(1, "Bridge stops bridging channels %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));

Modified: tags/11.4.0-rc2/main/devicestate.c
URL: http://svnview.digium.com/svn/asterisk/tags/11.4.0-rc2/main/devicestate.c?view=diff&rev=388174&r1=388173&r2=388174
==============================================================================
--- tags/11.4.0-rc2/main/devicestate.c (original)
+++ tags/11.4.0-rc2/main/devicestate.c Thu May  9 09:21:31 2013
@@ -705,7 +705,7 @@
 static void devstate_change_collector_cb(const struct ast_event *event, void *data)
 {
 	struct devstate_change *sc;
-	const char *device;
+	const char *device, *cachable_str;
 	const struct ast_eid *eid;
 	uint32_t state;
 	enum ast_devstate_cache cachable = AST_DEVSTATE_CACHABLE;
@@ -713,7 +713,6 @@
 	device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
 	eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID);
 	state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
-	cachable = ast_event_get_ie_uint(event, AST_EVENT_IE_CACHABLE);
 
 	if (ast_strlen_zero(device) || !eid) {
 		ast_log(LOG_ERROR, "Invalid device state change event received\n");
@@ -726,6 +725,16 @@
 	strcpy(sc->device, device);
 	sc->eid = *eid;
 	sc->state = state;
+
+	/* For 'cachable' we cannot use ast_event_get_ie_uint(), it overwrites the default of AST_DEVSTATE_CACHABLE we
+	 * have already setup for 'cachable', if for whatever reason the AST_EVENT_IE_CACHABLE wasn't
+	 * posted in the event ast_event_get_ie_uint() is going will return 0,
+	 * which equates to AST_DEVSTATE_NOT_CACHABLE the first enumeration in 'ast_devstate_cache'.
+	 */
+
+	if ((cachable_str = ast_event_get_ie_str(event, AST_EVENT_IE_CACHABLE))) {
+		sscanf(cachable_str, "%30u", &cachable);
+	}
 	sc->cachable = cachable;
 
 	ast_mutex_lock(&devstate_collector.lock);

Modified: tags/11.4.0-rc2/main/features.c
URL: http://svnview.digium.com/svn/asterisk/tags/11.4.0-rc2/main/features.c?view=diff&rev=388174&r1=388173&r2=388174
==============================================================================
--- tags/11.4.0-rc2/main/features.c (original)
+++ tags/11.4.0-rc2/main/features.c Thu May  9 09:21:31 2013
@@ -4552,17 +4552,6 @@
 		if (!f || (f->frametype == AST_FRAME_CONTROL &&
 				(f->subclass.integer == AST_CONTROL_HANGUP || f->subclass.integer == AST_CONTROL_BUSY ||
 					f->subclass.integer == AST_CONTROL_CONGESTION))) {
-			/*
-			 * If the bridge was broken for a hangup that isn't real,
-			 * then don't run the h extension, because the channel isn't
-			 * really hung up. This should really only happen with AST_SOFTHANGUP_ASYNCGOTO,
-			 * but it doesn't hurt to check AST_SOFTHANGUP_UNBRIDGE either.
-			 */
-			ast_channel_lock(chan);
-			if (ast_channel_softhangup_internal_flag(chan) & (AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE)) {
-				ast_set_flag(ast_channel_flags(chan), AST_FLAG_BRIDGE_HANGUP_DONT);
-			}
-			ast_channel_unlock(chan);
 			res = -1;
 			break;
 		}
@@ -4749,7 +4738,12 @@
 		config->end_bridge_callback(config->end_bridge_callback_data);
 	}
 
-	if (!ast_test_flag(&config->features_caller, AST_FEATURE_NO_H_EXTEN)) {
+	/* run the hangup exten on the chan object IFF it was NOT involved in a parking situation
+	 * if it were, then chan belongs to a different thread now, and might have been hung up long
+	 * ago.
+	 */
+	if (!(ast_channel_softhangup_internal_flag(chan) & (AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE))
+			&& !ast_test_flag(&config->features_caller, AST_FEATURE_NO_H_EXTEN)) {
 		struct ast_cdr *swapper = NULL;
 		char savelastapp[AST_MAX_EXTENSION];
 		char savelastdata[AST_MAX_EXTENSION];
@@ -7575,7 +7569,7 @@
 	return RESULT_SUCCESS;
 }
 
-/*! 
+/*!
  * \brief Dump parking lot status
  * \param s
  * \param m

Modified: tags/11.4.0-rc2/res/res_jabber.c
URL: http://svnview.digium.com/svn/asterisk/tags/11.4.0-rc2/res/res_jabber.c?view=diff&rev=388174&r1=388173&r2=388174
==============================================================================
--- tags/11.4.0-rc2/res/res_jabber.c (original)
+++ tags/11.4.0-rc2/res/res_jabber.c Thu May  9 09:21:31 2013
@@ -3339,14 +3339,15 @@
 		return IKS_FILTER_EAT;
 	}
 	if (!strcasecmp(iks_name(item_content), "state")) {
+		if ((cachable_str = iks_find_attrib(item_content, "cachable"))) {
+			sscanf(cachable_str, "%30d", &cachable);
+		}
 		device_state = iks_find_cdata(item, "state");
-		if ((cachable_str = iks_find_cdata(item, "cachable"))) {
-			sscanf(cachable_str, "%30d", &cachable);
-		}
 		if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE,
 					    AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE,
 					    AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID,
 					    AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid),
+					    AST_EVENT_IE_CACHABLE, AST_EVENT_IE_PLTYPE_UINT, cachable,
 					    AST_EVENT_IE_END))) {
 			return IKS_FILTER_EAT;
 		}

Modified: tags/11.4.0-rc2/res/res_timing_pthread.c
URL: http://svnview.digium.com/svn/asterisk/tags/11.4.0-rc2/res/res_timing_pthread.c?view=diff&rev=388174&r1=388173&r2=388174
==============================================================================
--- tags/11.4.0-rc2/res/res_timing_pthread.c (original)
+++ tags/11.4.0-rc2/res/res_timing_pthread.c Thu May  9 09:21:31 2013
@@ -31,8 +31,10 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
 
+#include <stdbool.h>
 #include <math.h>
-#include <sys/select.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include "asterisk/module.h"
 #include "asterisk/timing.h"
@@ -40,7 +42,6 @@
 #include "asterisk/astobj2.h"
 #include "asterisk/time.h"
 #include "asterisk/lock.h"
-#include "asterisk/poll-compat.h"
 
 static void *timing_funcs_handle;
 
@@ -91,13 +92,15 @@
 	unsigned int tick_count;
 	unsigned int pending_ticks;
 	struct timeval start;
-	unsigned int continuous:1;
+	bool continuous:1;
+	bool pipe_signaled:1;
 };
 
 static void pthread_timer_destructor(void *obj);
 static struct pthread_timer *find_timer(int handle, int unlinkobj);
-static void write_byte(struct pthread_timer *timer);
-static int read_pipe(struct pthread_timer *timer, unsigned int num);
+static void signal_pipe(struct pthread_timer *timer);
+static void unsignal_pipe(struct pthread_timer *timer);
+static void ack_ticks(struct pthread_timer *timer, unsigned int num);
 
 /*!
  * \brief Data for the timing thread
@@ -113,6 +116,7 @@
 {
 	struct pthread_timer *timer;
 	int fd;
+	int i;
 
 	if (!(timer = ao2_alloc(sizeof(*timer), pthread_timer_destructor))) {
 		errno = ENOMEM;
@@ -127,6 +131,12 @@
 		return -1;
 	}
 
+	for (i = 0; i < ARRAY_LEN(timer->pipe); ++i) {
+		int flags = fcntl(timer->pipe[i], F_GETFL);
+		flags |= O_NONBLOCK;
+		fcntl(timer->pipe[i], F_SETFL, flags);
+	}
+	
 	ao2_lock(pthread_timers);
 	if (!ao2_container_count(pthread_timers)) {
 		ast_mutex_lock(&timing_thread.lock);
@@ -193,7 +203,6 @@
 static int pthread_timer_ack(int handle, unsigned int quantity)
 {
 	struct pthread_timer *timer;
-	int res;
 
 	ast_assert(quantity > 0);
 
@@ -202,12 +211,12 @@
 	}
 
 	ao2_lock(timer);
-	res = read_pipe(timer, quantity);
+	ack_ticks(timer, quantity);
 	ao2_unlock(timer);
 
 	ao2_ref(timer, -1);
 
-	return res;
+	return 0;
 }
 
 static int pthread_timer_enable_continuous(int handle)
@@ -221,8 +230,8 @@
 
 	ao2_lock(timer);
 	if (!timer->continuous) {
-		timer->continuous = 1;
-		write_byte(timer);
+		timer->continuous = true;
+		signal_pipe(timer);
 	}
 	ao2_unlock(timer);
 
@@ -242,13 +251,8 @@
 
 	ao2_lock(timer);
 	if (timer->continuous) {
-		timer->continuous = 0;
-		if (read_pipe(timer, 1) != 0) {
-			/* Let the errno from read_pipe propagate up */
-			ao2_unlock(timer);
-			ao2_ref(timer, -1);
-			return -1;
-		}
+		timer->continuous = false;
+		unsignal_pipe(timer);
 	}
 	ao2_unlock(timer);
 
@@ -267,7 +271,7 @@
 	}
 
 	ao2_lock(timer);
-	if (timer->continuous && timer->pending_ticks == 1) {
+	if (timer->continuous) {
 		res = AST_TIMING_EVENT_CONTINUOUS;
 	}
 	ao2_unlock(timer);
@@ -366,79 +370,69 @@
 /*!
  * \internal
  * \pre timer is locked
- * \retval 0 if nothing to read or read success
- * \retval -1 on error
- */
-static int read_pipe(struct pthread_timer *timer, unsigned int quantity)
-{
-	int rd_fd = timer->pipe[PIPE_READ];
+ */
+static void ack_ticks(struct pthread_timer *timer, unsigned int quantity)
+{
 	int pending_ticks = timer->pending_ticks;
 
 	ast_assert(quantity);
-
-	if (timer->continuous && pending_ticks) {
-		pending_ticks--;
-	}
 
 	if (quantity > pending_ticks) {
 		quantity = pending_ticks;
 	}
 
 	if (!quantity) {
-		return 0;
-	}
-
-	do {
-		unsigned char buf[1024];
-		ssize_t res;
-		struct pollfd pfd = {
-			.fd = rd_fd,
-			.events = POLLIN,
-		};
-
-		if (ast_poll(&pfd, 1, 0) != 1) {
-			ast_debug(1, "Reading not available on timing pipe, "
-					"quantity: %u\n", quantity);
-			return -1;
-		}
-
-		res = read(rd_fd, buf,
-			(quantity < sizeof(buf)) ? quantity : sizeof(buf));
-
-		if (res == -1) {
-			if (errno == EAGAIN) {
-				continue;
-			}
-			ast_log(LOG_ERROR, "read failed on timing pipe: %s\n",
-					strerror(errno));
-			return -1;
-		}
-
-		quantity -= res;
-		timer->pending_ticks -= res;
-	} while (quantity);
-
-	return 0;
+		return;
+	}
+
+	timer->pending_ticks -= quantity;
+
+	if ((0 == timer->pending_ticks) && !timer->continuous) {
+		unsignal_pipe(timer);
+	}
 }
 
 /*!
  * \internal
  * \pre timer is locked
  */
-static void write_byte(struct pthread_timer *timer)
+static void signal_pipe(struct pthread_timer *timer)
 {
 	ssize_t res;
 	unsigned char x = 42;
 
-	do {
-		res = write(timer->pipe[PIPE_WRITE], &x, 1);
-	} while (res == -1 && errno == EAGAIN);
-
-	if (res == -1) {
+	if (timer->pipe_signaled) {
+		return;
+	}
+
+	res = write(timer->pipe[PIPE_WRITE], &x, 1);
+	if (-1 == res) {
 		ast_log(LOG_ERROR, "Error writing to timing pipe: %s\n",
 				strerror(errno));
 	} else {
-		timer->pending_ticks++;
+		timer->pipe_signaled = true;
+	}
+}
+
+/*!
+ * \internal
+ * \pre timer is locked
+ */
+static void unsignal_pipe(struct pthread_timer *timer)
+{
+	ssize_t res;
+	unsigned long buffer;
+
+	if (!timer->pipe_signaled) {
+		return;
+	}
+
+	res = read(timer->pipe[PIPE_READ], &buffer, sizeof(buffer));
+	if (-1 == res) {
+		ast_log(LOG_ERROR, "Error reading from pipe: %s\n",
+				strerror(errno));
+	} else {
+		timer->pipe_signaled = false;
 	}
 }
 
@@ -452,7 +446,8 @@
 
 	ao2_lock(timer);
 	if (check_timer(timer)) {
-		write_byte(timer);
+		timer->pending_ticks++;
+		signal_pipe(timer);
 	}
 	ao2_unlock(timer);
 




More information about the asterisk-commits mailing list