Commit d2cf322856 for asterisk.org
commit d2cf32285669b18cfcba0edcf3efbf8f91e4a63d
Author: Naveen Albert <asterisk@phreaknet.org>
Date: Sun Oct 4 14:58:09 2026 -0400
app_mixmonitor: Abort MixMonitor if ast_writefile fails
An error flag is set if ast_writefile fails, but this flag
is never used later. If the flag is set, clean up the MixMonitor
invocation and abort.
This complements #2149, which causes ast_writefile to fail
if attempting to record to a file already being written to.
Resolves: #2198
UserNote: If MixMonitor fails to open a file for writing
audio, it will now abort, rather than silently failing.
diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c
index ef2caaad68..4ec689b6ec 100644
--- a/apps/app_mixmonitor.c
+++ b/apps/app_mixmonitor.c
@@ -521,6 +521,7 @@ struct mixmonitor_ds {
struct ast_filestream *fs_write;
struct ast_audiohook *audiohook;
+ char *datastore_id;
unsigned int samp_rate;
char *filename;
@@ -570,6 +571,7 @@ static void mixmonitor_ds_destroy(void *data)
mixmonitor_ds->destruction_ok = 1;
ast_free(mixmonitor_ds->filename);
ast_free(mixmonitor_ds->beep_id);
+ ast_free(mixmonitor_ds->datastore_id);
ast_cond_signal(&mixmonitor_ds->destruction_condition);
ast_mutex_unlock(&mixmonitor_ds->lock);
}
@@ -848,6 +850,9 @@ static int mixmonitor_autochan_is_bridged(struct ast_autochan *autochan)
return is_bridged;
}
+/* Forward declaration */
+static void mixmonitor_ds_remove_and_free(struct ast_channel *chan, const char *datastore_id);
+
static void *mixmonitor_thread(void *obj)
{
struct mixmonitor *mixmonitor = obj;
@@ -875,8 +880,6 @@ static void *mixmonitor_thread(void *obj)
ast_callid_threadassoc_add(mixmonitor->callid);
}
- ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name);
-
fs = &mixmonitor->mixmonitor_ds->fs;
fs_read = &mixmonitor->mixmonitor_ds->fs_read;
fs_write = &mixmonitor->mixmonitor_ds->fs_write;
@@ -888,6 +891,35 @@ static void *mixmonitor_thread(void *obj)
format_slin = ast_format_cache_get_slin_by_rate(mixmonitor->mixmonitor_ds->samp_rate);
+ if (errflag) {
+ /* Tear everything down and exit. */
+ mixmonitor_ds_close_fs(mixmonitor->mixmonitor_ds);
+ mixmonitor->mixmonitor_ds->audiohook = NULL;
+
+ ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
+
+ ast_autochan_channel_lock(mixmonitor->autochan);
+ ast_audiohook_remove(mixmonitor->autochan->chan, &mixmonitor->audiohook);
+
+ mixmonitor_ds_remove_and_free(mixmonitor->autochan->chan, mixmonitor->mixmonitor_ds->datastore_id);
+ ast_autochan_channel_unlock(mixmonitor->autochan);
+ ast_autochan_destroy(mixmonitor->autochan);
+
+ ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
+ 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);
+
+ ast_audiohook_destroy(&mixmonitor->audiohook);
+ mixmonitor_free(mixmonitor);
+
+ ast_module_unref(ast_module_info->self);
+ return NULL;
+ }
+
+ ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name);
+
ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
if (mixmonitor->skip_seconds > 0.0) {
@@ -1042,6 +1074,7 @@ frame_cleanup:
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);
/* Free the translate paths */
@@ -1316,7 +1349,7 @@ static int launch_monitor_thread(struct ast_channel *chan, const char *filename,
return -1;
}
- ast_free(datastore_id);
+ mixmonitor->mixmonitor_ds->datastore_id = datastore_id; /* Steal the reference */
/* reference be released at mixmonitor destruction */
mixmonitor->callid = ast_read_threadstorage_callid();