From: Olle Johansson Date: Mon, 12 Sep 2011 13:47:13 +0000 (+0000) Subject: Merged revisions 335319 via svnmerge from X-Git-Tag: 10.0.0-beta2~64 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7c7e697c3a9c310495301aae2e14402af092c7b7;p=thirdparty%2Fasterisk.git Merged revisions 335319 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r335319 | oej | 2011-09-12 15:25:30 +0200 (Mån, 12 Sep 2011) | 12 lines Lock the peer->mvipvt to avoid crashes with SIP history enabled After the launch of 1.6 event-based MWI we have two threads handling the peer->mwipvt, which cause issues with SIP history additions in combination with the max limit for number of history entries. Review: https://reviewboard.asterisk.org/r/1373/ (closes issue ASTERISK-18288) Thanks to irrot for peer review. Work with this bug funded by IPvision AS ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/10@335323 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/channels/chan_sip.c b/channels/chan_sip.c index a0e53cfa2d..7054efeb28 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -14341,9 +14341,7 @@ static void mwi_event_cb(const struct ast_event *event, void *userdata) { struct sip_peer *peer = userdata; - ao2_lock(peer); sip_send_mwi_to_peer(peer, 0); - ao2_unlock(peer); } static void network_change_event_subscribe(void) @@ -24909,9 +24907,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); transmit_response(p, "200 OK", req); if (p->relatedpeer) { /* Send first notification */ - ao2_lock(p->relatedpeer); /* was WRLOCK */ sip_send_mwi_to_peer(p->relatedpeer, 0); - ao2_unlock(p->relatedpeer); } } else if (p->subscribed != CALL_COMPLETION) { @@ -25649,14 +25645,18 @@ static int sip_send_mwi_to_peer(struct sip_peer *peer, int cache_only) } ast_app_inboxcount(mailbox_str->str, &newmsgs, &oldmsgs); } + ao2_lock(peer); if (peer->mwipvt) { /* Base message on subscription */ p = dialog_ref(peer->mwipvt, "sip_send_mwi_to_peer: Setting dialog ptr p from peer->mwipvt-- should this be done?"); } else { /* Build temporary dialog for this message */ - if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) + if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) { + ao2_unlock(peer); return -1; + } + /* If we don't set the socket type to 0, then create_addr_from_peer will fail immediately if the peer * uses any transport other than UDP. We set the type to 0 here and then let create_addr_from_peer copy * the peer's socket information to the sip_pvt we just allocated @@ -25684,11 +25684,17 @@ static int sip_send_mwi_to_peer(struct sip_peer *peer, int cache_only) sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); } + /* We have multiple threads (mwi events and monitor retransmits) working with this PVT and as we modify the sip history if that's turned on, + we really need to have a lock on it */ + sip_pvt_lock(p); + /* Send MWI */ ast_set_flag(&p->flags[0], SIP_OUTGOING); /* the following will decrement the refcount on p as it finishes */ transmit_notify_with_mwi(p, newmsgs, oldmsgs, peer->vmexten); + sip_pvt_unlock(p); dialog_unref(p, "unref dialog ptr p just before it goes out of scope at the end of sip_send_mwi_to_peer."); + ao2_unlock(peer); return 0; }