diff options
author | Kevin Harwell <kharwell@digium.com> | 2013-02-18 22:23:52 +0000 |
---|---|---|
committer | Kevin Harwell <kharwell@digium.com> | 2013-02-18 22:23:52 +0000 |
commit | 4c76dbc8b29089af496e8c6677dd53386b81fca7 (patch) | |
tree | 77900aaa08db793d7b5bbb04b0e97b00853df9bc /apps/app_confbridge.c | |
parent | d4d1d10307c317bbe36ac33ef6b5836ca27776f3 (diff) |
Fixed Confbridge file recording deadlock and appending.
A deadlock occurred after starting/stopping and then restarting a confbridge
recording. Upon starting a recording a record thread is created that holds a
lock until just before exiting. Stopping the recording does not stop/exit the
thread or release the lock. The thread waits until recording begins again.
Starting a stopped recording signals the thread to continue and start recording
again. However restarting the recording also created another record thread
resulting in a deadlock. The fix was to make sure the record thread was only
created once.
Also it was noted that filenames for the recordings were being concatenated for
each start/stop. This was fixed by creating a new file for each conference
session and appending the actual recorded data within the file (e.g. passing
the 'a' option to MixMonitor).
(issue AST-1088)
Reported by: John Bigelow
Review: http://reviewboard.digium.internal/r/374/
........
Merged revisions 381702 from http://svn.asterisk.org/svn/asterisk/branches/11
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@381703 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'apps/app_confbridge.c')
-rw-r--r-- | apps/app_confbridge.c | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index 4190b9fd5..5bc1c5d48 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -596,6 +596,34 @@ static struct ast_channel *rec_request(const char *type, struct ast_format_cap * return tmp; } +static void set_rec_filename(struct conference_bridge *bridge, struct ast_str **filename) +{ + char *rec_file = bridge->b_profile.rec_file; + time_t now; + char *ext; + + if (ast_str_strlen(*filename)) { + return; + } + + time(&now); + + ast_str_reset(*filename); + if (ast_strlen_zero(rec_file)) { + ast_str_set(filename, 0, "confbridge-%s-%u.wav", bridge->name, (unsigned int)now); + } else { + /* insert time before file extension */ + ext = strrchr(rec_file, '.'); + if (ext) { + ast_str_set_substr(filename, 0, rec_file, ext - rec_file); + ast_str_append(filename, 0, "-%u%s", (unsigned int)now, ext); + } else { + ast_str_set(filename, 0, "%s-%u", rec_file, (unsigned int)now); + } + } + ast_str_append(filename, 0, ",a"); +} + static void *record_thread(void *obj) { struct conference_bridge *conference_bridge = obj; @@ -614,16 +642,7 @@ static void *record_thread(void *obj) /* XXX If we get an EXIT right here, START will essentially be a no-op */ while (conference_bridge->record_state != CONF_RECORD_EXIT) { - if (!(ast_strlen_zero(conference_bridge->b_profile.rec_file))) { - ast_str_append(&filename, 0, "%s", conference_bridge->b_profile.rec_file); - } else { - time_t now; - time(&now); - ast_str_append(&filename, 0, "confbridge-%s-%u.wav", - conference_bridge->name, - (unsigned int) now); - } - + set_rec_filename(conference_bridge, &filename); chan = ast_channel_ref(conference_bridge->record_chan); ast_answer(chan); pbx_exec(chan, mixmonapp, ast_str_buffer(filename)); @@ -757,6 +776,13 @@ static int start_conf_record_thread(struct conference_bridge *conference_bridge) conf_start_record(conference_bridge); + /* + * if the thread has already been started, don't start another + */ + if (conference_bridge->record_thread != AST_PTHREADT_NULL) { + return 0; + } + if (ast_pthread_create_background(&conference_bridge->record_thread, NULL, record_thread, conference_bridge)) { ast_log(LOG_WARNING, "Failed to create recording channel for conference %s\n", conference_bridge->name); ao2_ref(conference_bridge, -1); /* error so remove ref */ |