comment and cleanup the main thread.
authorLuigi Rizzo <rizzo@icir.org>
Wed, 18 Oct 2006 15:49:40 +0000 (15:49 +0000)
committerLuigi Rizzo <rizzo@icir.org>
Wed, 18 Oct 2006 15:49:40 +0000 (15:49 +0000)
On passing, fix a bug: close the socket if the allocation
of a structure for the new session fails.
(the bugfix is a candidate for 1.4)

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

main/manager.c

index d367dc8..ea547fe 100644 (file)
@@ -2046,29 +2046,32 @@ static void *session_do(void *data)
        return NULL;
 }
 
+/*! \brief The thread accepting connections on the manager interface port.
+ * As a side effect, it purges stale sessions, one per each iteration,
+ * which is at least every 5 seconds.
+ */
 static void *accept_thread(void *ignore)
 {
-       int as;
-       struct sockaddr_in sin;
-       socklen_t sinlen;
-       struct eventqent *eqe;
-       struct mansession *s;
-       struct protoent *p;
-       int arg = 1;
-       int flags;
        pthread_attr_t attr;
-       time_t now;
-       struct pollfd pfds[1];
 
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
        for (;;) {
-               time(&now);
+               struct mansession *s;
+               time_t now = time(NULL);
+               int as;
+               struct sockaddr_in sin;
+               socklen_t sinlen;
+               struct protoent *p;
+               int flags;
+               struct pollfd pfds[1];
+
                AST_LIST_LOCK(&sessions);
                AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, s, list) {
                        if (s->sessiontimeout && (now > s->sessiontimeout) && !s->inuse) {
                                AST_LIST_REMOVE_CURRENT(&sessions, list);
+                               ast_atomic_fetchadd_int(&num_sessions, -1);
                                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));
@@ -2082,13 +2085,11 @@ static void *accept_thread(void *ignore)
                   always keep at least one in the queue */
                /* XXX why do we need one entry in the queue ? */
                while (master_eventq->next && !master_eventq->usecount) {
-                       eqe = master_eventq;
+                       struct eventqent *eqe = master_eventq;
                        master_eventq = master_eventq->next;
                        free(eqe);
                }
                AST_LIST_UNLOCK(&sessions);
-               if (s)
-                       ast_atomic_fetchadd_int(&num_sessions, -1);
 
                sinlen = sizeof(sin);
                pfds[0].fd = asock;
@@ -2104,30 +2105,34 @@ static void *accept_thread(void *ignore)
                }
                p = getprotobyname("tcp");
                if (p) {
+                       int arg = 1;
                        if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
                                ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
                        }
                }
-               if (!(s = ast_calloc(1, sizeof(*s))))
+               s = ast_calloc(1, sizeof(*s));  /* allocate a new record */
+               if (!s) {
+                       close(as);
                        continue;
+               }
 
-               ast_atomic_fetchadd_int(&num_sessions, 1);
-               
-               memcpy(&s->sin, &sin, sizeof(sin));
+
+               s->sin = sin;
                s->writetimeout = 100;
                s->waiting_thread = AST_PTHREADT_NULL;
 
-               if (!block_sockets) {
-                       /* For safety, make sure socket is non-blocking */
-                       flags = fcntl(as, F_GETFL);
-                       fcntl(as, F_SETFL, flags | O_NONBLOCK);
-               } else {
-                       flags = fcntl(as, F_GETFL);
-                       fcntl(as, F_SETFL, flags & ~O_NONBLOCK);
-               }
+               flags = fcntl(as, F_GETFL);
+               if (!block_sockets) /* For safety, make sure socket is non-blocking */
+                       flags |= O_NONBLOCK;
+               else
+                       flags &= ~O_NONBLOCK;
+               fcntl(as, F_SETFL, flags);
+
                ast_mutex_init(&s->__lock);
                s->fd = as;
                s->send_events = -1;
+
+               ast_atomic_fetchadd_int(&num_sessions, 1);
                AST_LIST_LOCK(&sessions);
                AST_LIST_INSERT_HEAD(&sessions, s, list);
                /* Find the last place in the master event queue and hook ourselves