mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	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/branches/1.8@351182 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -4074,6 +4074,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"; | ||||
| @@ -4085,10 +4089,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) { | ||||
| @@ -10681,7 +10710,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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user