aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-09-18 20:56:43 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2007-09-18 20:56:43 +0000
commitc9255ac03041680e738f5032a37dc59a6b1a1ac7 (patch)
tree571b5792bb6b866cfa8970c516aa3e7b9b74f999
parentb889122d407739b0267fba583889e2d757c231cf (diff)
Fix a memory leak that can occur on systems under higher load. The issue is
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: http://svn.digium.com/svn/asterisk/branches/1.4@82867 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--main/manager.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/main/manager.c b/main/manager.c
index 2256a30f8..351fcd713 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -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 */