diff options
author | Russell Bryant <russell@russellbryant.com> | 2012-01-17 01:48:12 +0000 |
---|---|---|
committer | Russell Bryant <russell@russellbryant.com> | 2012-01-17 01:48:12 +0000 |
commit | 141dd18848277e2f49c466b057edef20824331aa (patch) | |
tree | 8b88a97ac04e375bfba78b6c5632c7a8fc984100 /channels/chan_sip.c | |
parent | aacc158072bbbc609363404cc4689284a1b6ce8f (diff) |
Merged revisions 351183 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/10
................
r351183 | russell | 2012-01-16 20:43:19 -0500 (Mon, 16 Jan 2012) | 29 lines
Merged revisions 351182 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r351182 | russell | 2012-01-16 20:37:03 -0500 (Mon, 16 Jan 2012) | 22 lines
Add some missing locking in chan_sip.
This patch adds some missing locking to the function
send_provisional_keepalive_full(). This function is called from the scheduler,
which is processed in the SIP monitor thread. The associated channel (or pbx)
thread will also be using the same sip_pvt and ast_channel so locking must be
used. The sip_pvt_lock_full() function is used to ensure proper locking order
in a safe manner.
In passing, document a suspected reference counting error in this function.
The "fix" is left commented out because when the "fix" is present, crashes
occur. My theory is that fixing it is exposing a reference counting error
elsewhere, but I don't know where. (Or my analysis of this being a problem
could have been completely wrong in the first place). Leave the comment in
the code for so that someone may investigate it again in the future.
Also add a bit of doxygen to transmit_provisional_response().
(closes issue ASTERISK-18979)
Review: https://reviewboard.asterisk.org/r/1648
........
................
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@351184 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/chan_sip.c')
-rw-r--r-- | channels/chan_sip.c | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 548199fe0..347b2901e 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -4099,6 +4099,10 @@ static void add_blank(struct sip_request *req) static int send_provisional_keepalive_full(struct sip_pvt *pvt, int with_sdp) { const char *msg = NULL; + struct ast_channel *chan; + int res = 0; + + chan = sip_pvt_lock_full(pvt); if (!pvt->last_provisional || !strncasecmp(pvt->last_provisional, "100", 3)) { msg = "183 Session Progress"; @@ -4110,10 +4114,35 @@ static int send_provisional_keepalive_full(struct sip_pvt *pvt, int with_sdp) } else { transmit_response(pvt, S_OR(msg, pvt->last_provisional), &pvt->initreq); } - return PROVIS_KEEPALIVE_TIMEOUT; + res = PROVIS_KEEPALIVE_TIMEOUT; } - return 0; + if (chan) { + ast_channel_unlock(chan); + chan = ast_channel_unref(chan); + } + + if (!res) { + pvt->provisional_keepalive_sched_id = -1; + } + + sip_pvt_unlock(pvt); + +#if 0 + /* + * XXX BUG TODO + * + * Without this code, it appears as if this function is leaking its + * reference to the sip_pvt. However, adding it introduces a crash. + * This points to some sort of reference count imbalance elsewhere, + * but I'm not sure where ... + */ + if (!res) { + dialog_unref(pvt, "dialog ref for provisional keepalive"); + } +#endif + + return res; } static int send_provisional_keepalive(const void *data) @@ -10916,7 +10945,13 @@ static void get_realm(struct sip_pvt *p, const struct sip_request *req) ast_string_field_set(p, realm, sip_cfg.realm); } -/* Only use a static string for the msg, here! */ +/*! + * \internal + * + * \arg msg Only use a string constant for the msg, here, it is shallow copied + * + * \note assumes the sip_pvt is locked. + */ static int transmit_provisional_response(struct sip_pvt *p, const char *msg, const struct sip_request *req, int with_sdp) { int res; |