From 0e09ca68a5493b51aa0ecc4fac64fffab2fb33bf Mon Sep 17 00:00:00 2001 From: Mark Spencer <markster@digium.com> Date: Tue, 22 Apr 2003 18:47:49 +0000 Subject: [PATCH] Fix race in DISCONNECT vs RELEASE git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@881 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_zap.c | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/channels/chan_zap.c b/channels/chan_zap.c index d4192d8c68..770f173cef 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -295,18 +295,6 @@ static int pritype = PRI_CPE; #define DEFAULT_PRI_DEBUG 0 #endif -static inline int pri_grab(struct zt_pri *pri) -{ - int res; - /* Grab the lock first */ - res = ast_pthread_mutex_lock(&pri->lock); - if (res) - return res; - /* Then break the select */ - pthread_kill(pri->master, SIGURG); - return 0; -} - static inline void pri_rel(struct zt_pri *pri) { ast_pthread_mutex_unlock(&pri->lock); @@ -459,6 +447,26 @@ static struct zt_pvt { #endif } *iflist = NULL; +#ifdef ZAPATA_PRI +static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri) +{ + int res; + /* Grab the lock first */ + do { + res = pthread_mutex_trylock(&pri->lock); + if (res) { + ast_pthread_mutex_unlock(&pvt->lock); + /* Release the lock and try again */ + usleep(1); + ast_pthread_mutex_lock(&pvt->lock); + } + } while(res); + /* Then break the select */ + pthread_kill(pri->master, SIGURG); + return 0; +} +#endif + static struct zt_ring_cadence cadences[] = { { { 125, 125, 2000, 4000 } }, /* Quick chirp followed by normal ring */ { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /* British style ring */ @@ -1578,7 +1586,7 @@ static int zt_hangup(struct ast_channel *ast) #ifdef ZAPATA_PRI if (p->sig == SIG_PRI) { if (p->call) { - if (!pri_grab(p->pri)) { + if (!pri_grab(p, p->pri)) { res = pri_disconnect(p->pri->pri, p->call, PRI_CAUSE_NORMAL_CLEARING); if (p->alreadyhungup) { p->call = NULL; @@ -1688,12 +1696,15 @@ static int zt_answer(struct ast_channel *ast) int index; int oldstate = ast->_state; ast_setstate(ast, AST_STATE_UP); + ast_pthread_mutex_lock(&p->lock); index = zt_get_index(ast, p, 0); if (index < 0) index = SUB_REAL; /* nothing to do if a radio channel */ - if (p->radio) + if (p->radio) { + ast_pthread_mutex_unlock(&p->lock); return 0; + } switch(p->sig) { case SIG_FXSLS: case SIG_FXSGS: @@ -1730,7 +1741,7 @@ static int zt_answer(struct ast_channel *ast) #ifdef ZAPATA_PRI case SIG_PRI: /* Send a pri acknowledge */ - if (!pri_grab(p->pri)) { + if (!pri_grab(p, p->pri)) { res = pri_answer(p->pri->pri, p->call, 0, 1); pri_rel(p->pri); } else { @@ -1750,8 +1761,9 @@ static int zt_answer(struct ast_channel *ast) return 0; default: ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); - return -1; + res = -1; } + ast_pthread_mutex_unlock(&p->lock); return res; } -- GitLab