diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-05-20 22:38:58 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-05-20 22:38:58 +0000 |
commit | d94b0a420fec3599db18c2dc495243e62620e22d (patch) | |
tree | be859f88f90a4a479d1f1256bc8a1eb2476ce835 | |
parent | 0a6414d92e59371794a4358a755c78dee18185ec (diff) | |
parent | 33e9e9f4b753fbf5518afcc967190b875fefb568 (diff) |
create 1.4.20 from 1.4.20-rc3
git-svn-id: http://svn.digium.com/svn/asterisk/tags/1.4.20@117333 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | .version | 2 | ||||
-rw-r--r-- | ChangeLog | 74 | ||||
-rw-r--r-- | channels/chan_alsa.c | 3 | ||||
-rw-r--r-- | channels/chan_local.c | 25 | ||||
-rw-r--r-- | channels/chan_sip.c | 2 | ||||
-rw-r--r-- | include/asterisk/lock.h | 9 | ||||
-rw-r--r-- | main/asterisk.c | 2 | ||||
-rw-r--r-- | main/autoservice.c | 14 | ||||
-rw-r--r-- | main/channel.c | 20 | ||||
-rw-r--r-- | main/utils.c | 78 |
10 files changed, 160 insertions, 69 deletions
@@ -1 +1 @@ -1.4.20 +1.4.20-rc3 @@ -1,6 +1,76 @@ -2008-05-12 Russell Bryant <russell@digium.com> +2008-05-07 Russell Bryant <russell@digium.com> + + * Asterisk 1.4.20-rc3 released. + +2008-05-14 12:51 +0000 [r116230] Olle Johansson <oej@edvina.net> + + * channels/chan_sip.c: Accept text messages even with Content-Type: + text/plain;charset=Södermanländska + +2008-05-13 23:47 +0000 [r116088] Mark Michelson <mmichelson@digium.com> + + * main/channel.c, include/asterisk/lock.h: A change to the way + channel locks are handled when DEBUG_CHANNEL_LOCKS is defined. + After debugging a deadlock, it was noticed that when + DEBUG_CHANNEL_LOCKS is enabled in menuselect, the actual origin + of channel locks is obscured by the fact that all channel locks + appear to happen in the function ast_channel_lock(). This code + change redefines ast_channel_lock to be a macro which maps to + __ast_channel_lock(), which then relays the proper file name, + line number, and function name information to the core lock + functions so that this information will be displayed in the case + that there is some sort of locking error or core show locks is + issued. + +2008-05-13 21:17 +0000 [r115990-116038] Russell Bryant <russell@digium.com> + + * channels/chan_local.c: Fix a deadlock involving channel + autoservice and chan_local that was debugged and fixed by + mmichelson and me. We observed a system that had a bunch of + threads stuck in ast_autoservice_stop(). The reason these threads + were waiting around is because this function waits to ensure that + the channel list in the autoservice thread gets rebuilt before + the stop() function returns. However, the autoservice thread was + also locked, so the autoservice channel list was never getting + rebuilt. The autoservice thread was stuck waiting for the channel + lock on a local channel. However, the local channel was locked by + a thread that was stuck in the autoservice stop function. It + turned out that the issue came down to the local_queue_frame() + function in chan_local. This function assumed that one of the + channels passed in as an argument was locked when called. + However, that was not always the case. There were multiple cases + in which this channel was not locked when the function was + called. We fixed up chan_local to indicate to this function + whether this channel was locked or not. The previous assumption + had caused local_queue_frame() to improperly return with the + channel locked, where it would then never get unlocked. (closes + issue #12584) (related to issue #12603) + + * main/autoservice.c: Fix an issue that I noticed in autoservice + while mmichelson and I were debugging a different problem. I + noticed that it was theoretically possible for two threads to + attempt to start the autoservice thread at the same time. This + change makes the process of starting the autoservice thread, + thread-safe. + +2008-05-13 20:28 +0000 [r115944] Joshua Colp <jcolp@digium.com> + + * channels/chan_alsa.c: Use the right flag to open the audio in + non-blocking. (closes issue #12616) Reported by: + nicklewisdigiumuser + +2008-05-13 18:36 +0000 [r115884] Tilghman Lesher <tlesher@digium.com> + + * main/asterisk.c: If the socket dies (read returns 0=EOF), return + immediately. (Closes issue #12637) + +2008-05-12 17:51 +0000 [r115735] Mark Michelson <mmichelson@digium.com> - * Asterisk 1.4.20 released. + * main/utils.c: If a thread holds no locks, do not print any + information on the thread when issuing a core show locks command. + This will help to de-clutter output somewhat. Russell said it + would be fine to place this improvement in the 1.4 branch, so + that's why it's going here too. 2008-05-09 16:34 +0000 [r115579] Joshua Colp <jcolp@digium.com> diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c index 9a416837b..d5817493f 100644 --- a/channels/chan_alsa.c +++ b/channels/chan_alsa.c @@ -105,7 +105,6 @@ static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; static snd_pcm_format_t format = SND_PCM_FORMAT_S16_BE; #endif -/* static int block = O_NONBLOCK; */ static char indevname[50] = ALSA_INDEV; static char outdevname[50] = ALSA_OUTDEV; @@ -360,7 +359,7 @@ static snd_pcm_t *alsa_card_init(char *dev, snd_pcm_stream_t stream) /* unsigned int per_max = 8; */ snd_pcm_uframes_t start_threshold, stop_threshold; - err = snd_pcm_open(&handle, dev, stream, O_NONBLOCK); + err = snd_pcm_open(&handle, dev, stream, SND_PCM_NONBLOCK); if (err < 0) { ast_log(LOG_ERROR, "snd_pcm_open failed: %s\n", snd_strerror(err)); return NULL; diff --git a/channels/chan_local.c b/channels/chan_local.c index b0e51f90d..e0c743137 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -160,7 +160,8 @@ static struct local_pvt *local_pvt_destroy(struct local_pvt *pvt) return NULL; } -static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f, struct ast_channel *us) +static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f, + struct ast_channel *us, int us_locked) { struct ast_channel *other = NULL; @@ -184,11 +185,13 @@ static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_fra /* Ensure that we have both channels locked */ while (other && ast_channel_trylock(other)) { ast_mutex_unlock(&p->lock); - if (us) + if (us && us_locked) { ast_channel_unlock(us); + } usleep(1); - if (us) + if (us && us_locked) { ast_channel_lock(us); + } ast_mutex_lock(&p->lock); other = isoutbound ? p->owner : p->chan; } @@ -217,7 +220,7 @@ static int local_answer(struct ast_channel *ast) if (isoutbound) { /* Pass along answer since somebody answered us */ struct ast_frame answer = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; - res = local_queue_frame(p, isoutbound, &answer, ast); + res = local_queue_frame(p, isoutbound, &answer, ast, 1); } else ast_log(LOG_WARNING, "Huh? Local is being asked to answer?\n"); if (!res) @@ -306,7 +309,7 @@ static int local_write(struct ast_channel *ast, struct ast_frame *f) if (f && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)) check_bridge(p, isoutbound); if (!ast_test_flag(p, LOCAL_ALREADY_MASQED)) - res = local_queue_frame(p, isoutbound, f, ast); + res = local_queue_frame(p, isoutbound, f, ast, 1); else { if (option_debug) ast_log(LOG_DEBUG, "Not posting to queue since already masked on '%s'\n", ast->name); @@ -361,7 +364,7 @@ static int local_indicate(struct ast_channel *ast, int condition, const void *da f.subclass = condition; f.data = (void*)data; f.datalen = datalen; - if (!(res = local_queue_frame(p, isoutbound, &f, ast))) + if (!(res = local_queue_frame(p, isoutbound, &f, ast, 1))) ast_mutex_unlock(&p->lock); } @@ -381,7 +384,7 @@ static int local_digit_begin(struct ast_channel *ast, char digit) ast_mutex_lock(&p->lock); isoutbound = IS_OUTBOUND(ast, p); f.subclass = digit; - if (!(res = local_queue_frame(p, isoutbound, &f, ast))) + if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0))) ast_mutex_unlock(&p->lock); return res; @@ -401,7 +404,7 @@ static int local_digit_end(struct ast_channel *ast, char digit, unsigned int dur isoutbound = IS_OUTBOUND(ast, p); f.subclass = digit; f.len = duration; - if (!(res = local_queue_frame(p, isoutbound, &f, ast))) + if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0))) ast_mutex_unlock(&p->lock); return res; @@ -421,7 +424,7 @@ static int local_sendtext(struct ast_channel *ast, const char *text) isoutbound = IS_OUTBOUND(ast, p); f.data = (char *) text; f.datalen = strlen(text) + 1; - if (!(res = local_queue_frame(p, isoutbound, &f, ast))) + if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0))) ast_mutex_unlock(&p->lock); return res; } @@ -441,7 +444,7 @@ static int local_sendhtml(struct ast_channel *ast, int subclass, const char *dat f.subclass = subclass; f.data = (char *)data; f.datalen = datalen; - if (!(res = local_queue_frame(p, isoutbound, &f, ast))) + if (!(res = local_queue_frame(p, isoutbound, &f, ast, 0))) ast_mutex_unlock(&p->lock); return res; } @@ -564,7 +567,7 @@ static int local_hangup(struct ast_channel *ast) /* Need to actually hangup since there is no PBX */ ochan = p->chan; else - res = local_queue_frame(p, isoutbound, &f, NULL); + res = local_queue_frame(p, isoutbound, &f, NULL, 1); if (!res) ast_mutex_unlock(&p->lock); if (ochan) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 715fb134c..b96968940 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -9735,7 +9735,7 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req) struct ast_frame f; const char *content_type = get_header(req, "Content-Type"); - if (strcmp(content_type, "text/plain")) { /* No text/plain attachment */ + if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */ transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */ if (!p->owner) sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h index cc68a13aa..2570ee7bb 100644 --- a/include/asterisk/lock.h +++ b/include/asterisk/lock.h @@ -1196,18 +1196,21 @@ AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p), struct ast_channel; +#define ast_channel_lock(a) __ast_channel_lock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! \brief Lock AST channel (and print debugging output) \note You need to enable DEBUG_CHANNEL_LOCKS for this function */ -int ast_channel_lock(struct ast_channel *chan); +int __ast_channel_lock(struct ast_channel *chan, const char *file, int lineno, const char *func); +#define ast_channel_unlock(a) __ast_channel_unlock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! \brief Unlock AST channel (and print debugging output) \note You need to enable DEBUG_CHANNEL_LOCKS for this function */ -int ast_channel_unlock(struct ast_channel *chan); +int __ast_channel_unlock(struct ast_channel *chan, const char *file, int lineno, const char *func); +#define ast_channel_trylock(a) __ast_channel_trylock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__) /*! \brief Lock AST channel (and print debugging output) \note You need to enable DEBUG_CHANNEL_LOCKS for this function */ -int ast_channel_trylock(struct ast_channel *chan); +int __ast_channel_trylock(struct ast_channel *chan, const char *file, int lineno, const char *func); #endif #endif /* _ASTERISK_LOCK_H */ diff --git a/main/asterisk.c b/main/asterisk.c index 37823e989..934a61731 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -2307,7 +2307,7 @@ static void ast_remotecontrol(char * data) char buf[512] = "", *curline = buf, *nextline; int not_written = 1; - if (read(ast_consock, buf, sizeof(buf) - 1) < 0) { + if (read(ast_consock, buf, sizeof(buf) - 1) <= 0) { break; } diff --git a/main/autoservice.c b/main/autoservice.c index 88ab0d4e6..fb0840f92 100644 --- a/main/autoservice.c +++ b/main/autoservice.c @@ -201,25 +201,29 @@ int ast_autoservice_start(struct ast_channel *chan) ast_channel_unlock(chan); AST_LIST_LOCK(&aslist); - if (AST_LIST_EMPTY(&aslist)) + + if (AST_LIST_EMPTY(&aslist) && asthread != AST_PTHREADT_NULL) { ast_cond_signal(&as_cond); + } + AST_LIST_INSERT_HEAD(&aslist, as, list); - AST_LIST_UNLOCK(&aslist); if (asthread == AST_PTHREADT_NULL) { /* need start the thread */ if (ast_pthread_create_background(&asthread, NULL, autoservice_run, NULL)) { ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n"); /* There will only be a single member in the list at this point, the one we just added. */ - AST_LIST_LOCK(&aslist); AST_LIST_REMOVE(&aslist, as, list); - AST_LIST_UNLOCK(&aslist); free(as); + asthread = AST_PTHREADT_NULL; res = -1; - } else + } else { pthread_kill(asthread, SIGURG); + } } + AST_LIST_UNLOCK(&aslist); + return res; } diff --git a/main/channel.c b/main/channel.c index f61d365b7..d9ab77c38 100644 --- a/main/channel.c +++ b/main/channel.c @@ -4534,7 +4534,7 @@ const char *channelreloadreason2txt(enum channelreloadreason reason) /*! \brief Unlock AST channel (and print debugging output) \note You need to enable DEBUG_CHANNEL_LOCKS for this function */ -int ast_channel_unlock(struct ast_channel *chan) +int __ast_channel_unlock(struct ast_channel *chan, const char *filename, int lineno, const char *func) { int res = 0; if (option_debug > 2) @@ -4545,8 +4545,11 @@ int ast_channel_unlock(struct ast_channel *chan) ast_log(LOG_DEBUG, "::::==== Unlocking non-existing channel \n"); return 0; } - +#ifdef DEBUG_THREADS + res = __ast_pthread_mutex_unlock(filename, lineno, func, "(channel lock)", &chan->lock); +#else res = ast_mutex_unlock(&chan->lock); +#endif if (option_debug > 2) { #ifdef DEBUG_THREADS @@ -4573,14 +4576,18 @@ int ast_channel_unlock(struct ast_channel *chan) /*! \brief Lock AST channel (and print debugging output) \note You need to enable DEBUG_CHANNEL_LOCKS for this function */ -int ast_channel_lock(struct ast_channel *chan) +int __ast_channel_lock(struct ast_channel *chan, const char *filename, int lineno, const char *func) { int res; if (option_debug > 3) ast_log(LOG_DEBUG, "====:::: Locking AST channel %s\n", chan->name); +#ifdef DEBUG_THREADS + res = __ast_pthread_mutex_lock(filename, lineno, func, "(channel lock)", &chan->lock); +#else res = ast_mutex_lock(&chan->lock); +#endif if (option_debug > 3) { #ifdef DEBUG_THREADS @@ -4605,14 +4612,17 @@ int ast_channel_lock(struct ast_channel *chan) /*! \brief Lock AST channel (and print debugging output) \note You need to enable DEBUG_CHANNEL_LOCKS for this function */ -int ast_channel_trylock(struct ast_channel *chan) +int __ast_channel_trylock(struct ast_channel *chan, const char *filename, int lineno, const char *func) { int res; if (option_debug > 2) ast_log(LOG_DEBUG, "====:::: Trying to lock AST channel %s\n", chan->name); - +#ifdef DEBUG_THREADS + res = __ast_pthread_mutex_trylock(filename, lineno, func, "(channel lock)", &chan->lock); +#else res = ast_mutex_trylock(&chan->lock); +#endif if (option_debug > 2) { #ifdef DEBUG_THREADS diff --git a/main/utils.c b/main/utils.c index 2bb4fb2bb..e03cbbfae 100644 --- a/main/utils.c +++ b/main/utils.c @@ -736,46 +736,48 @@ static int handle_show_locks(int fd, int argc, char *argv[]) pthread_mutex_lock(&lock_infos_lock.mutex); AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) { int i; - ast_dynamic_str_append(&str, 0, "=== Thread ID: %u (%s)\n", (int) lock_info->thread_id, - lock_info->thread_name); - pthread_mutex_lock(&lock_info->lock); - for (i = 0; str && i < lock_info->num_locks; i++) { - int j; - ast_mutex_t *lock; - - ast_dynamic_str_append(&str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d)\n", - lock_info->locks[i].pending > 0 ? "Waiting for " : - lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i, - lock_info->locks[i].file, - locktype2str(lock_info->locks[i].type), - lock_info->locks[i].line_num, - lock_info->locks[i].func, lock_info->locks[i].lock_name, - lock_info->locks[i].lock_addr, - lock_info->locks[i].times_locked); - - if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1) - continue; - - /* We only have further details for mutexes right now */ - if (lock_info->locks[i].type != AST_MUTEX) - continue; - - lock = lock_info->locks[i].lock_addr; - - ast_reentrancy_lock(lock); - for (j = 0; str && j < lock->reentrancy; j++) { - ast_dynamic_str_append(&str, 0, "=== --- ---> Locked Here: %s line %d (%s)\n", - lock->file[j], lock->lineno[j], lock->func[j]); + if (lock_info->num_locks) { + ast_dynamic_str_append(&str, 0, "=== Thread ID: %u (%s)\n", (int) lock_info->thread_id, + lock_info->thread_name); + pthread_mutex_lock(&lock_info->lock); + for (i = 0; str && i < lock_info->num_locks; i++) { + int j; + ast_mutex_t *lock; + + ast_dynamic_str_append(&str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d)\n", + lock_info->locks[i].pending > 0 ? "Waiting for " : + lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i, + lock_info->locks[i].file, + locktype2str(lock_info->locks[i].type), + lock_info->locks[i].line_num, + lock_info->locks[i].func, lock_info->locks[i].lock_name, + lock_info->locks[i].lock_addr, + lock_info->locks[i].times_locked); + + if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1) + continue; + + /* We only have further details for mutexes right now */ + if (lock_info->locks[i].type != AST_MUTEX) + continue; + + lock = lock_info->locks[i].lock_addr; + + ast_reentrancy_lock(lock); + for (j = 0; str && j < lock->reentrancy; j++) { + ast_dynamic_str_append(&str, 0, "=== --- ---> Locked Here: %s line %d (%s)\n", + lock->file[j], lock->lineno[j], lock->func[j]); + } + ast_reentrancy_unlock(lock); } - ast_reentrancy_unlock(lock); + pthread_mutex_unlock(&lock_info->lock); + if (!str) + break; + ast_dynamic_str_append(&str, 0, "=== -------------------------------------------------------------------\n" + "===\n"); + if (!str) + break; } - pthread_mutex_unlock(&lock_info->lock); - if (!str) - break; - ast_dynamic_str_append(&str, 0, "=== -------------------------------------------------------------------\n" - "===\n"); - if (!str) - break; } pthread_mutex_unlock(&lock_infos_lock.mutex); |