mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	Lock the channel before calling the setoption callback
The channel needs to be locked before calling these callback functions. Also, sip_setoption needs to lock the pvt and a check p->rtp is non-null before using it. Review: https://reviewboard.asterisk.org/r/1220/ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@324048 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -218,6 +218,7 @@ static void awesome_locking(struct local_pvt *p, struct ast_channel **outchan, s | ||||
| 	*outchan = p->chan; | ||||
| } | ||||
|  | ||||
| /* Called with ast locked */ | ||||
| static int local_setoption(struct ast_channel *ast, int option, void * data, int datalen) | ||||
| { | ||||
| 	int res = 0; | ||||
| @@ -226,27 +227,22 @@ static int local_setoption(struct ast_channel *ast, int option, void * data, int | ||||
| 	ast_chan_write_info_t *write_info; | ||||
|  | ||||
| 	if (option != AST_OPTION_CHANNEL_WRITE) { | ||||
| 		res = -1; | ||||
| 		goto setoption_cleanup; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	write_info = data; | ||||
|  | ||||
| 	if (write_info->version != AST_CHAN_WRITE_INFO_T_VERSION) { | ||||
| 		ast_log(LOG_ERROR, "The chan_write_info_t type has changed, and this channel hasn't been updated!\n"); | ||||
| 		res = -1; | ||||
| 		goto setoption_cleanup; | ||||
| 		return -1 | ||||
| 	} | ||||
|  | ||||
| 	/* get the tech pvt */ | ||||
| 	ast_channel_lock(ast); | ||||
| 	if (!(p = ast->tech_pvt)) { | ||||
| 		ast_channel_unlock(ast); | ||||
| 		res = -1; | ||||
| 		goto setoption_cleanup; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	ao2_ref(p, 1); | ||||
| 	ast_channel_unlock(ast); | ||||
| 	ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */ | ||||
|  | ||||
| 	/* get the channel we are supposed to write to */ | ||||
| 	ao2_lock(p); | ||||
| @@ -273,6 +269,7 @@ setoption_cleanup: | ||||
| 	if (otherchan) { | ||||
| 		ast_channel_unref(otherchan); | ||||
| 	} | ||||
| 	ast_channel_lock(ast); /* Lock back before we leave */ | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| @@ -349,6 +346,7 @@ static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct | ||||
| 	return bridged; | ||||
| } | ||||
|  | ||||
| /* Called with ast locked */ | ||||
| static int local_queryoption(struct ast_channel *ast, int option, void *data, int *datalen) | ||||
| { | ||||
| 	struct local_pvt *p; | ||||
| @@ -362,21 +360,18 @@ static int local_queryoption(struct ast_channel *ast, int option, void *data, in | ||||
| 	} | ||||
|  | ||||
| 	/* for some reason the channel is not locked in channel.c when this function is called */ | ||||
| 	ast_channel_lock(ast); | ||||
| 	if (!(p = ast->tech_pvt)) { | ||||
| 		ast_channel_unlock(ast); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	ao2_lock(p); | ||||
| 	if (!(tmp = IS_OUTBOUND(ast, p) ? p->owner : p->chan)) { | ||||
| 		ao2_unlock(p); | ||||
| 		ast_channel_unlock(ast); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	ast_channel_ref(tmp); | ||||
| 	ao2_unlock(p); | ||||
| 	ast_channel_unlock(ast); | ||||
| 	ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */ | ||||
|  | ||||
| 	ast_channel_lock(tmp); | ||||
| 	if (!(bridged = ast_bridged_channel(tmp))) { | ||||
| @@ -395,6 +390,7 @@ query_cleanup: | ||||
| 	if (tmp) { | ||||
| 		tmp = ast_channel_unref(tmp); | ||||
| 	} | ||||
| 	ast_channel_lock(ast); /* Lock back before we leave */ | ||||
|  | ||||
| 	return res; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user