mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	Merged revisions 230508 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r230508 | dvossel | 2009-11-19 15:22:46 -0600 (Thu, 19 Nov 2009) | 10 lines fixes MixMonitor thread not exiting when StopMixMonitor is used (closes issue #16152) Reported by: AlexMS Patches: stopmixmonitor_1.4.diff uploaded by dvossel (license 671) Tested by: dvossel, AlexMS Review: https://reviewboard.asterisk.org/r/424/ ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@230509 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -177,19 +177,21 @@ struct mixmonitor_ds { | ||||
| 	 * immediately during stop_mixmonitor or channel destruction. */ | ||||
| 	int fs_quit; | ||||
| 	struct ast_filestream *fs; | ||||
|  | ||||
| 	struct ast_audiohook *audiohook; | ||||
| }; | ||||
|  | ||||
| /*! | ||||
|  * \internal | ||||
|  * \pre mixmonitor_ds must be locked before calling this function | ||||
|  */ | ||||
| static void mixmonitor_ds_close_fs(struct mixmonitor_ds *mixmonitor_ds) | ||||
| { | ||||
| 	ast_mutex_lock(&mixmonitor_ds->lock); | ||||
| 	if (mixmonitor_ds->fs) { | ||||
| 		ast_closestream(mixmonitor_ds->fs); | ||||
| 		mixmonitor_ds->fs = NULL; | ||||
| 		mixmonitor_ds->fs_quit = 1; | ||||
| 		ast_verb(2, "MixMonitor close filestream\n"); | ||||
| 	} | ||||
| 	ast_mutex_unlock(&mixmonitor_ds->lock); | ||||
| } | ||||
|  | ||||
| static void mixmonitor_ds_destroy(void *data) | ||||
| @@ -197,6 +199,7 @@ static void mixmonitor_ds_destroy(void *data) | ||||
| 	struct mixmonitor_ds *mixmonitor_ds = data; | ||||
|  | ||||
| 	ast_mutex_lock(&mixmonitor_ds->lock); | ||||
| 	mixmonitor_ds->audiohook = NULL; | ||||
| 	mixmonitor_ds->destruction_ok = 1; | ||||
| 	ast_cond_signal(&mixmonitor_ds->destruction_condition); | ||||
| 	ast_mutex_unlock(&mixmonitor_ds->lock); | ||||
| @@ -207,6 +210,20 @@ static struct ast_datastore_info mixmonitor_ds_info = { | ||||
| 	.destroy = mixmonitor_ds_destroy, | ||||
| }; | ||||
|  | ||||
| static void destroy_monitor_audiohook(struct mixmonitor *mixmonitor) | ||||
| { | ||||
| 	if (mixmonitor->mixmonitor_ds) { | ||||
| 		ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); | ||||
| 		mixmonitor->mixmonitor_ds->audiohook = NULL; | ||||
| 		ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); | ||||
| 	} | ||||
| 	/* kill the audiohook.*/ | ||||
| 	ast_audiohook_lock(&mixmonitor->audiohook); | ||||
| 	ast_audiohook_detach(&mixmonitor->audiohook); | ||||
| 	ast_audiohook_unlock(&mixmonitor->audiohook); | ||||
| 	ast_audiohook_destroy(&mixmonitor->audiohook); | ||||
| } | ||||
|  | ||||
| static int startmon(struct ast_channel *chan, struct ast_audiohook *audiohook)  | ||||
| { | ||||
| 	struct ast_channel *peer = NULL; | ||||
| @@ -246,10 +263,10 @@ static void *mixmonitor_thread(void *obj) | ||||
|  | ||||
| 	ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name); | ||||
|  | ||||
| 	ast_audiohook_lock(&mixmonitor->audiohook); | ||||
|  | ||||
| 	fs = &mixmonitor->mixmonitor_ds->fs; | ||||
|  | ||||
| 	/* The audiohook must enter and exit the loop locked */ | ||||
| 	ast_audiohook_lock(&mixmonitor->audiohook); | ||||
| 	while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) { | ||||
| 		struct ast_frame *fr = NULL; | ||||
|  | ||||
| @@ -261,6 +278,10 @@ static void *mixmonitor_thread(void *obj) | ||||
| 		if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR))) | ||||
| 			continue; | ||||
|  | ||||
| 		/* audiohook lock is not required for the next block. | ||||
| 		 * Unlock it, but remember to lock it before looping or exiting */ | ||||
| 		ast_audiohook_unlock(&mixmonitor->audiohook); | ||||
|  | ||||
| 		if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->autochan->chan && ast_bridged_channel(mixmonitor->autochan->chan))) { | ||||
| 			ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); | ||||
| 			/* Initialize the file if not already done so */ | ||||
| @@ -292,28 +313,27 @@ static void *mixmonitor_thread(void *obj) | ||||
| 		/* All done! free it. */ | ||||
| 		ast_frame_free(fr, 0); | ||||
|  | ||||
| 		ast_audiohook_lock(&mixmonitor->audiohook); | ||||
| 	} | ||||
|  | ||||
| 	ast_audiohook_detach(&mixmonitor->audiohook); | ||||
| 	ast_audiohook_unlock(&mixmonitor->audiohook); | ||||
| 	ast_audiohook_destroy(&mixmonitor->audiohook); | ||||
|  | ||||
| 	mixmonitor_ds_close_fs(mixmonitor->mixmonitor_ds); | ||||
|  | ||||
|  | ||||
| 	if (mixmonitor->post_process) { | ||||
| 		ast_verb(2, "Executing [%s]\n", mixmonitor->post_process); | ||||
| 		ast_safe_system(mixmonitor->post_process); | ||||
| 	} | ||||
|  | ||||
| 	ast_autochan_destroy(mixmonitor->autochan); | ||||
|  | ||||
| 	/* Datastore cleanup.  close the filestream and wait for ds destruction */ | ||||
| 	ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); | ||||
| 	mixmonitor_ds_close_fs(mixmonitor->mixmonitor_ds); | ||||
| 	if (!mixmonitor->mixmonitor_ds->destruction_ok) { | ||||
| 		ast_cond_wait(&mixmonitor->mixmonitor_ds->destruction_condition, &mixmonitor->mixmonitor_ds->lock); | ||||
| 	} | ||||
| 	ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); | ||||
|  | ||||
| 	/* kill the audiohook */ | ||||
| 	destroy_monitor_audiohook(mixmonitor); | ||||
|  | ||||
| 	if (mixmonitor->post_process) { | ||||
| 		ast_verb(2, "Executing [%s]\n", mixmonitor->post_process); | ||||
| 		ast_safe_system(mixmonitor->post_process); | ||||
| 	} | ||||
|  | ||||
| 	ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name); | ||||
| 	mixmonitor_free(mixmonitor); | ||||
| @@ -339,6 +359,7 @@ static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	mixmonitor_ds->audiohook = &mixmonitor->audiohook; | ||||
| 	datastore->data = mixmonitor_ds; | ||||
|  | ||||
| 	ast_channel_lock(chan); | ||||
| @@ -380,6 +401,12 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	/* Setup the actual spy before creating our thread */ | ||||
| 	if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type)) { | ||||
| 		mixmonitor_free(mixmonitor); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	/* Copy over flags and channel name */ | ||||
| 	mixmonitor->flags = flags; | ||||
| 	if (!(mixmonitor->autochan = ast_autochan_setup(chan))) { | ||||
| @@ -402,12 +429,6 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename | ||||
| 	mixmonitor->filename = (char *) mixmonitor + sizeof(*mixmonitor) + strlen(chan->name) + 1; | ||||
| 	strcpy(mixmonitor->filename, filename); | ||||
|  | ||||
| 	/* Setup the actual spy before creating our thread */ | ||||
| 	if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type)) { | ||||
| 		mixmonitor_free(mixmonitor); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC); | ||||
|  | ||||
| 	if (readvol) | ||||
| @@ -511,13 +532,36 @@ static int stop_mixmonitor_exec(struct ast_channel *chan, const char *data) | ||||
| { | ||||
| 	struct ast_datastore *datastore = NULL; | ||||
|  | ||||
| 	/* closing the filestream here guarantees the file is avaliable to the dialplan | ||||
| 	 * after calling StopMixMonitor */ | ||||
| 	if ((datastore = ast_channel_datastore_find(chan, &mixmonitor_ds_info, NULL))) { | ||||
| 		mixmonitor_ds_close_fs(datastore->data); | ||||
| 	} | ||||
|  | ||||
| 	ast_channel_lock(chan); | ||||
| 	ast_audiohook_detach_source(chan, mixmonitor_spy_type); | ||||
| 	if ((datastore = ast_channel_datastore_find(chan, &mixmonitor_ds_info, NULL))) { | ||||
| 		struct mixmonitor_ds *mixmonitor_ds = datastore->data; | ||||
|  | ||||
| 		ast_mutex_lock(&mixmonitor_ds->lock); | ||||
|  | ||||
| 		/* closing the filestream here guarantees the file is avaliable to the dialplan | ||||
| 	 	 * after calling StopMixMonitor */ | ||||
| 		mixmonitor_ds_close_fs(mixmonitor_ds); | ||||
|  | ||||
| 		/* The mixmonitor thread may be waiting on the audiohook trigger. | ||||
| 		 * In order to exit from the mixmonitor loop before waiting on channel | ||||
| 		 * destruction, poke the audiohook trigger. */ | ||||
| 		if (mixmonitor_ds->audiohook) { | ||||
| 			ast_audiohook_lock(mixmonitor_ds->audiohook); | ||||
| 			ast_cond_signal(&mixmonitor_ds->audiohook->trigger); | ||||
| 			ast_audiohook_unlock(mixmonitor_ds->audiohook); | ||||
| 			mixmonitor_ds->audiohook = NULL; | ||||
| 		} | ||||
|  | ||||
| 		ast_mutex_unlock(&mixmonitor_ds->lock); | ||||
|  | ||||
| 		/* Remove the datastore so the monitor thread can exit */ | ||||
| 		if (!ast_channel_datastore_remove(chan, datastore)) { | ||||
| 			ast_datastore_free(datastore); | ||||
| 		} | ||||
| 	} | ||||
| 	ast_channel_unlock(chan); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user