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/
........

Merged revisions 391778 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 391794 from http://svn.asterisk.org/svn/asterisk/branches/11


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@391828 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/78/78/1
Jonathan Rose 12 years ago
parent 0abc78dcfd
commit bfdff342b4

@ -744,6 +744,8 @@ static void *mixmonitor_thread(void *obj)
} }
mixmonitor_free(mixmonitor); mixmonitor_free(mixmonitor);
ast_module_unref(ast_module_info->self);
return NULL; return NULL;
} }
@ -783,7 +785,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, static int launch_monitor_thread(struct ast_channel *chan, const char *filename,
unsigned int flags, int readvol, int writevol, unsigned int flags, int readvol, int writevol,
const char *post_process, const char *filename_write, const char *post_process, const char *filename_write,
char *filename_read, const char *uid_channel_var, char *filename_read, const char *uid_channel_var,
@ -810,33 +812,33 @@ 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, sizeof(*mixmonitor)))) { if (!(mixmonitor = ast_calloc(1, sizeof(*mixmonitor)))) {
return; return -1;
} }
/* Now that the struct has been calloced, go ahead and initialize the string fields. */ /* Now that the struct has been calloced, go ahead and initialize the string fields. */
if (ast_string_field_init(mixmonitor, 512)) { if (ast_string_field_init(mixmonitor, 512)) {
mixmonitor_free(mixmonitor); mixmonitor_free(mixmonitor);
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, 0)) { if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type, 0)) {
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, &datastore_id)) { if (setup_mixmonitor_ds(mixmonitor, chan, &datastore_id)) {
ast_autochan_destroy(mixmonitor->autochan); ast_autochan_destroy(mixmonitor->autochan);
mixmonitor_free(mixmonitor); mixmonitor_free(mixmonitor);
ast_free(datastore_id); ast_free(datastore_id);
return; return -1;
} }
if (!ast_strlen_zero(uid_channel_var)) { if (!ast_strlen_zero(uid_channel_var)) {
@ -905,13 +907,13 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
mixmonitor_spy_type, ast_channel_name(chan)); mixmonitor_spy_type, ast_channel_name(chan));
ast_audiohook_destroy(&mixmonitor->audiohook); ast_audiohook_destroy(&mixmonitor->audiohook);
mixmonitor_free(mixmonitor); mixmonitor_free(mixmonitor);
return; return -1;
} }
/* reference be released at mixmonitor destruction */ /* reference be released at mixmonitor destruction */
mixmonitor->callid = ast_read_threadstorage_callid(); mixmonitor->callid = ast_read_threadstorage_callid();
ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor); return ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor);
} }
/* a note on filename_parse: creates directory structure and assigns absolute path from relative paths for filenames */ /* a note on filename_parse: creates directory structure and assigns absolute path from relative paths for filenames */
@ -1032,7 +1034,10 @@ static int mixmonitor_exec(struct ast_channel *chan, const char *data)
} }
pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename); pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
launch_monitor_thread(chan,
/* 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, args.filename,
flags.flags, flags.flags,
readvol, readvol,
@ -1041,7 +1046,9 @@ static int mixmonitor_exec(struct ast_channel *chan, const char *data)
filename_write, filename_write,
filename_read, filename_read,
uid_channel_var, uid_channel_var,
recipients); recipients)) {
ast_module_unref(ast_module_info->self);
}
return 0; return 0;
} }

Loading…
Cancel
Save