#! /bin/sh /usr/share/dpatch/dpatch-run ## local_queue_frame_livelock.dpatch by Philipp Berndt ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Prevent system lock-up by limiting number of locking attempts @DPATCH@ diff -urNad asterisk-1.2.13~dfsg~/channels/chan_local.c asterisk-1.2.13~dfsg/channels/chan_local.c --- asterisk-1.2.13~dfsg~/channels/chan_local.c 2006-09-08 06:37:07.000000000 +0200 +++ asterisk-1.2.13~dfsg/channels/chan_local.c 2008-02-11 13:03:08.000000000 +0100 @@ -117,6 +117,11 @@ static int local_queue_frame(struct local_pvt *p, int isoutbound, struct ast_frame *f, struct ast_channel *us) { struct ast_channel *other; + int retrycnt = 0; + struct timeval t1, t2; + int diff; + t1 = ast_tvnow(); + retrylock: /* Recalculate outbound channel */ if (isoutbound) { @@ -139,6 +144,11 @@ return 0; } if (ast_mutex_trylock(&other->lock)) { + if (other->_softhangup) { + ast_log(LOG_DEBUG, "local_queue_frame() us=%s giving up waiting for lock on other since it has _softhangup set\n", us?us->name:"null"); + p->glaredetect = 0; + return 0; + } /* Failed to lock. Release main lock and try again */ ast_mutex_unlock(&p->lock); if (us) { @@ -154,8 +164,17 @@ if (us) ast_mutex_lock(&us->lock); ast_mutex_lock(&p->lock); + if (++retrycnt > 1000) + { + ast_log(LOG_WARNING, "local_queue_frame() us=%s giving up waiting for lock on other\n", us?us->name:"null"); + p->glaredetect = 0; + return 0; + } goto retrylock; } + t2 = ast_tvnow(); + if ( (diff = ast_tvdiff_ms(t2, t1)) > 20 ) + ast_log( LOG_WARNING, "local_queue_frame() aquire lock took %d ms in %d attempts\n", diff, retrycnt); ast_queue_frame(other, f); ast_mutex_unlock(&other->lock); p->glaredetect = 0;