]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix a memory leak that can occur on systems under higher load. The issue is
authorRussell Bryant <russell@russellbryant.com>
Tue, 18 Sep 2007 20:56:43 +0000 (20:56 +0000)
committerRussell Bryant <russell@russellbryant.com>
Tue, 18 Sep 2007 20:56:43 +0000 (20:56 +0000)
that when events are appended to the master event queue, they use the number
of active sessions as a use count so it will know when all active sessions
at the time the event happened have consumed it.  However, the handling of
the number of sessions was not properly synchronized, so the use count was
not always correct, causing an event to disappear early, or get stuck in
the event queue for forever.

(closes issue #9238, reported by bweschke, patch from Ivan, modified by me)

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@82867 65c4cc65-6c06-0410-ace0-fbb531ad65f3

main/manager.c

index 2256a30f8aedb9aa2c1ab0af5d1b855b01ef8080..351fcd713ffc35caed8c5678240a1431cf3b7612 100644 (file)
@@ -683,9 +683,9 @@ static void destroy_session(struct mansession *s)
 {
        AST_LIST_LOCK(&sessions);
        AST_LIST_REMOVE(&sessions, s, list);
+       num_sessions--;
        AST_LIST_UNLOCK(&sessions);
 
-       ast_atomic_fetchadd_int(&num_sessions, -1);
        free_session(s);
 }
 
@@ -2235,6 +2235,7 @@ static void *accept_thread(void *ignore)
                AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, s, list) {
                        if (s->sessiontimeout && (now > s->sessiontimeout) && !s->inuse) {
                                AST_LIST_REMOVE_CURRENT(&sessions, list);
+                               num_sessions--;
                                if (s->authenticated && (option_verbose > 1) && displayconnects) {
                                        ast_verbose(VERBOSE_PREFIX_2 "HTTP Manager '%s' timed out from %s\n",
                                                s->username, ast_inet_ntoa(s->sin.sin_addr));
@@ -2253,8 +2254,6 @@ static void *accept_thread(void *ignore)
                        free(eqe);
                }
                AST_LIST_UNLOCK(&sessions);
-               if (s)
-                       ast_atomic_fetchadd_int(&num_sessions, -1);
 
                sinlen = sizeof(sin);
                pfds[0].fd = asock;
@@ -2277,8 +2276,6 @@ static void *accept_thread(void *ignore)
                if (!(s = ast_calloc(1, sizeof(*s))))
                        continue;
 
-               ast_atomic_fetchadd_int(&num_sessions, 1);
-               
                memcpy(&s->sin, &sin, sizeof(sin));
                s->writetimeout = 100;
                s->waiting_thread = AST_PTHREADT_NULL;
@@ -2296,13 +2293,14 @@ static void *accept_thread(void *ignore)
                s->send_events = -1;
                AST_LIST_LOCK(&sessions);
                AST_LIST_INSERT_HEAD(&sessions, s, list);
+               num_sessions++;
                /* Find the last place in the master event queue and hook ourselves
                   in there */
                s->eventq = master_eventq;
                while(s->eventq->next)
                        s->eventq = s->eventq->next;
-               AST_LIST_UNLOCK(&sessions);
                ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
+               AST_LIST_UNLOCK(&sessions);
                if (ast_pthread_create_background(&s->t, &attr, session_do, s))
                        destroy_session(s);
        }
@@ -2580,9 +2578,9 @@ static char *generic_http_callback(int format, struct sockaddr_in *requestor, co
                s->eventq = master_eventq;
                while (s->eventq->next)
                        s->eventq = s->eventq->next;
-               AST_LIST_UNLOCK(&sessions);
                ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
                ast_atomic_fetchadd_int(&num_sessions, 1);
+               AST_LIST_UNLOCK(&sessions);
        }
 
        /* Reset HTTP timeout.  If we're not yet authenticated, keep it extremely short */