aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authormmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2008-04-02 17:36:04 +0000
committermmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2008-04-02 17:36:04 +0000
commit744a3dc1f28d3ff10308f8821c173aa59507ea55 (patch)
treec28c2b32eb88e2474bec86ed35fcf9c1328c0dba /main
parentbb54d7a0ad0e11bc6c763bf220585b387ee29bdb (diff)
Fix a race condition in the manager. It is possible that a new manager event
could be appended during a brief time when the manager is not waiting for input. If an event comes during this period, we need to set an indicator that there is an event pending so that the manager doesn't attempt to wait forever for an event that already happened. (closes issue #12354) Reported by: bamby Patches: manager_race_condition.diff uploaded by bamby (license 430) (comments added by me) git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@112468 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r--main/manager.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/main/manager.c b/main/manager.c
index 4fadb744c..10a00a795 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -175,6 +175,7 @@ struct mansession {
struct eventqent *eventq;
/* Timeout for ast_carefulwrite() */
int writetimeout;
+ int pending_event; /*!< Pending events indicator in case when waiting_thread is NULL */
AST_LIST_ENTRY(mansession) list;
};
@@ -2202,6 +2203,11 @@ static int get_input(struct mansession *s, char *output)
fds[0].events = POLLIN;
do {
ast_mutex_lock(&s->__lock);
+ if (s->pending_event) {
+ s->pending_event = 0;
+ ast_mutex_unlock(&s->__lock);
+ return 0;
+ }
s->waiting_thread = pthread_self();
ast_mutex_unlock(&s->__lock);
@@ -2463,6 +2469,13 @@ int manager_event(int category, const char *event, const char *fmt, ...)
ast_mutex_lock(&s->__lock);
if (s->waiting_thread != AST_PTHREADT_NULL)
pthread_kill(s->waiting_thread, SIGURG);
+ else
+ /* We have an event to process, but the mansession is
+ * not waiting for it. We still need to indicate that there
+ * is an event waiting so that get_input processes the pending
+ * event instead of polling.
+ */
+ s->pending_event = 1;
ast_mutex_unlock(&s->__lock);
}
AST_LIST_UNLOCK(&sessions);