]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix an issue where dynamic threads can get free'd, but still exist in the
authorRussell Bryant <russell@russellbryant.com>
Mon, 6 Aug 2007 20:44:09 +0000 (20:44 +0000)
committerRussell Bryant <russell@russellbryant.com>
Mon, 6 Aug 2007 20:44:09 +0000 (20:44 +0000)
dynamic thread list.
(closes issue #10392, patch from Mihai, with credit to his colleague, Pete)

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

channels/chan_iax2.c

index 14f44cebcb1e50dc4be68e4b901fdd5707eeea83..1c5cbf8ea652a83a821dcc527bac08a32ca88bf1 100644 (file)
@@ -856,6 +856,9 @@ static const struct ast_channel_tech iax2_tech = {
        .fixup = iax2_fixup,
 };
 
+/* WARNING: insert_idle_thread should only ever be called within the
+ * context of an iax2_process_thread() thread.
+ */
 static void insert_idle_thread(struct iax2_thread *thread)
 {
        if (thread->type == IAX_TYPE_DYNAMIC) {
@@ -6384,11 +6387,13 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
                if (errno != ECONNREFUSED && errno != EAGAIN)
                        ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
                handle_error();
-               insert_idle_thread(thread);
+               thread->iostate = IAX_IOSTATE_IDLE;
+               signal_condition(&thread->lock, &thread->cond);
                return 1;
        }
        if (test_losspct && ((100.0 * ast_random() / (RAND_MAX + 1.0)) < test_losspct)) { /* simulate random loss condition */
-               insert_idle_thread(thread);
+               thread->iostate = IAX_IOSTATE_IDLE;
+               signal_condition(&thread->lock, &thread->cond);
                return 1;
        }
        
@@ -6411,7 +6416,8 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
                           so queue it up for processing later. */
                        defer_full_frame(thread, cur);
                        AST_LIST_UNLOCK(&active_list);
-                       insert_idle_thread(thread);
+                       thread->iostate = IAX_IOSTATE_IDLE;
+                       signal_condition(&thread->lock, &thread->cond);
                        return 1;
                } else {
                        /* this thread is going to process this frame, so mark it */
@@ -7896,13 +7902,27 @@ static void *iax2_process_thread(void *data)
                                /* Someone grabbed our thread *right* after we timed out.
                                 * Wait for them to set us up with something to do and signal
                                 * us to continue. */
-                               ast_cond_wait(&thread->cond, &thread->lock);
+                               tv = ast_tvadd(ast_tvnow(), ast_samp2tv(30000, 1000));
+                               ts.tv_sec = tv.tv_sec;
+                               ts.tv_nsec = tv.tv_usec * 1000;
+                               if (ast_cond_timedwait(&thread->cond, &thread->lock, &ts) == ETIMEDOUT)
+                               {
+                                       ast_mutex_unlock(&thread->lock);
+                                       break;
+                               }
                        }
                } else {
                        ast_cond_wait(&thread->cond, &thread->lock);
                }
+
+               /* Go back into our respective list */
+               put_into_idle = 1;
+
                ast_mutex_unlock(&thread->lock);
 
+               if (thread->iostate == IAX_IOSTATE_IDLE)
+                       continue;
+
                /* Add ourselves to the active list now */
                AST_LIST_LOCK(&active_list);
                AST_LIST_INSERT_HEAD(&active_list, thread, list);
@@ -7937,9 +7957,6 @@ static void *iax2_process_thread(void *data)
 
                /* Make sure another frame didn't sneak in there after we thought we were done. */
                handle_deferred_full_frames(thread);
-
-               /* Go back into our respective list */
-               put_into_idle = 1;
        }
 
        /* I am exiting here on my own volition, I need to clean up my own data structures