From 982a3ac4245f0e6678370ffd9cc6ee3163eba010 Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Mon, 13 Aug 2007 20:06:19 +0000 Subject: Merged revisions 79274 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r79274 | russell | 2007-08-13 15:02:57 -0500 (Mon, 13 Aug 2007) | 3 lines Don't call find_peer within update_registry with a pvt lock held. This can cause a deadlock as the code will eventually call find_callno. ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@79275 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_iax2.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 228e6ca41..8cabad2cf 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -1184,6 +1184,10 @@ static int uncompress_subclass(unsigned char csub) return csub; } +/*! + * \note This funtion calls realtime_peer -> reg_source_db -> iax2_poke_peer -> find_callno, + * so do not call it with a pvt lock held. + */ static struct iax2_peer *find_peer(const char *name, int realtime) { struct iax2_peer *peer = NULL; @@ -5988,7 +5992,7 @@ static void reg_source_db(struct iax2_peer *p) } } -static int update_registry(const char *name, struct sockaddr_in *sin, int callno, char *devtype, int fd, unsigned short refresh) +static int update_registry(struct sockaddr_in *sin, int callno, char *devtype, int fd, unsigned short refresh) { /* Called from IAX thread only, with proper iaxsl lock */ struct iax_ie_data ied; @@ -5996,22 +6000,30 @@ static int update_registry(const char *name, struct sockaddr_in *sin, int callno int msgcount; char data[80]; int version; + const char *peer_name; memset(&ied, 0, sizeof(ied)); + peer_name = ast_strdupa(iaxs[callno]->peer); + /* SLD: Another find_peer call during registration - this time when we are really updating our registration */ - if (!(p = find_peer(name, 1))) { - ast_log(LOG_WARNING, "No such peer '%s'\n", name); + ast_mutex_unlock(&iaxsl[callno]); + if (!(p = find_peer(peer_name, 1))) { + ast_mutex_lock(&iaxsl[callno]); + ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name); return -1; } + ast_mutex_lock(&iaxsl[callno]); + if (!iaxs[callno]) + return -1; if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS))) { if (sin->sin_addr.s_addr) { time_t nowtime; time(&nowtime); - realtime_update_peer(name, sin, nowtime); + realtime_update_peer(peer_name, sin, nowtime); } else { - realtime_update_peer(name, sin, 0); + realtime_update_peer(peer_name, sin, 0); } } if (inaddrcmp(&p->addr, sin)) { @@ -8139,8 +8151,12 @@ retryowner2: ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED)) { if (f.subclass == IAX_COMMAND_REGREL) memset(&sin, 0, sizeof(sin)); - if (update_registry(iaxs[fr->callno]->peer, &sin, fr->callno, ies.devicetype, fd, ies.refresh)) + if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh)) ast_log(LOG_WARNING, "Registry error\n"); + if (!iaxs[fr->callno]) { + ast_mutex_unlock(&iaxsl[fr->callno]); + return 1; + } if (ies.provverpres && ies.serviceident && sin.sin_addr.s_addr) { ast_mutex_unlock(&iaxsl[fr->callno]); check_provisioning(&sin, fd, ies.serviceident, ies.provver); -- cgit v1.2.3