app_mixmonitor: Fix crashes caused by unloading app_mixmonitor

Unloading app_mixmonitor while active mixmonitors were running would
cause a segfault. This patch fixes that by making it impossible to
unload app_mixmonitor while mixmonitors are active.

Review: https://reviewboard.asterisk.org/r/2624/


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@391778 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Jonathan Rose
2013-06-14 16:14:48 +00:00
parent f13bd7d90f
commit 0630ac71c2

View File

@@ -381,6 +381,8 @@ static void *mixmonitor_thread(void *obj)
ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name); ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name);
mixmonitor_free(mixmonitor); mixmonitor_free(mixmonitor);
ast_module_unref(ast_module_info->self);
return NULL; return NULL;
} }
@@ -414,7 +416,7 @@ static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel
return 0; return 0;
} }
static void launch_monitor_thread(struct ast_channel *chan, const char *filename, unsigned int flags, static int launch_monitor_thread(struct ast_channel *chan, const char *filename, unsigned int flags,
int readvol, int writevol, const char *post_process) int readvol, int writevol, const char *post_process)
{ {
pthread_t thread; pthread_t thread;
@@ -442,26 +444,26 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
/* Pre-allocate mixmonitor structure and spy */ /* Pre-allocate mixmonitor structure and spy */
if (!(mixmonitor = ast_calloc(1, len))) { if (!(mixmonitor = ast_calloc(1, len))) {
return; return -1;
} }
/* Setup the actual spy before creating our thread */ /* Setup the actual spy before creating our thread */
if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type)) { if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type)) {
mixmonitor_free(mixmonitor); mixmonitor_free(mixmonitor);
return; return -1;
} }
/* Copy over flags and channel name */ /* Copy over flags and channel name */
mixmonitor->flags = flags; mixmonitor->flags = flags;
if (!(mixmonitor->autochan = ast_autochan_setup(chan))) { if (!(mixmonitor->autochan = ast_autochan_setup(chan))) {
mixmonitor_free(mixmonitor); mixmonitor_free(mixmonitor);
return; return -1;
} }
if (setup_mixmonitor_ds(mixmonitor, chan)) { if (setup_mixmonitor_ds(mixmonitor, chan)) {
ast_autochan_destroy(mixmonitor->autochan); ast_autochan_destroy(mixmonitor->autochan);
mixmonitor_free(mixmonitor); mixmonitor_free(mixmonitor);
return; return -1;
} }
mixmonitor->name = (char *) mixmonitor + sizeof(*mixmonitor); mixmonitor->name = (char *) mixmonitor + sizeof(*mixmonitor);
strcpy(mixmonitor->name, chan->name); strcpy(mixmonitor->name, chan->name);
@@ -485,10 +487,10 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
mixmonitor_spy_type, chan->name); mixmonitor_spy_type, chan->name);
ast_audiohook_destroy(&mixmonitor->audiohook); ast_audiohook_destroy(&mixmonitor->audiohook);
mixmonitor_free(mixmonitor); mixmonitor_free(mixmonitor);
return; return -1;
} }
ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor); return ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor);
} }
static int mixmonitor_exec(struct ast_channel *chan, const char *data) static int mixmonitor_exec(struct ast_channel *chan, const char *data)
@@ -567,7 +569,12 @@ static int mixmonitor_exec(struct ast_channel *chan, const char *data)
ast_mkdir(tmp, 0777); ast_mkdir(tmp, 0777);
pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename); pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process);
/* If launch_monitor_thread works, the module reference must not be released until it is finished. */
ast_module_ref(ast_module_info->self);
if (launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process)) {
ast_module_unref(ast_module_info->self);
}
return 0; return 0;
} }