]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix a race condition in the manager. It is possible that a new manager event
authorMark Michelson <mmichelson@digium.com>
Wed, 2 Apr 2008 17:36:04 +0000 (17:36 +0000)
committerMark Michelson <mmichelson@digium.com>
Wed, 2 Apr 2008 17:36:04 +0000 (17:36 +0000)
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: https://origsvn.digium.com/svn/asterisk/branches/1.4@112468 65c4cc65-6c06-0410-ace0-fbb531ad65f3

main/manager.c

index 4fadb744ca6c8d548b00894efc886a683a510cfd..10a00a79595a6422d9fc3ed06c27f9386c1746bb 100644 (file)
@@ -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);