summaryrefslogtreecommitdiff
path: root/res/stasis
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2016-01-21 10:58:02 -0600
committerMark Michelson <mmichelson@digium.com>2016-01-22 14:58:02 -0600
commita45eacebf326741821e7c954ac48e72c4c1b1274 (patch)
treedf58c4c6b935475766f3a5a4cafa0c12e5cd4137 /res/stasis
parent7866806fc3bbb716064fb9e4e0a1436e3325a637 (diff)
Stasis: Use control queue to prevent crash.
A crash occurred when attempting to set a channel variable on a channel that had already been hung up. This is because there is a small window between when a control is grabbed and when the channel variable is set that the channel can be hung up. The fix here is to queue the setting of the channel variable onto the control queue. This way, the manipulation of the channel happens in a thread where it is safe to be done. In this change, I also noticed that the setting of bridge roles on channels was being done outside of the control queue, so I also changed those operations to be done in the control queue. ASTERISK-25709 #close Reported by Mark Michelson Change-Id: I2a0a4d51bce6fba6f1d9954e40935e42f366ea78
Diffstat (limited to 'res/stasis')
-rw-r--r--res/stasis/control.c50
1 files changed, 47 insertions, 3 deletions
diff --git a/res/stasis/control.c b/res/stasis/control.c
index 99407dfab..030ea8fb4 100644
--- a/res/stasis/control.c
+++ b/res/stasis/control.c
@@ -355,14 +355,39 @@ int stasis_app_control_dial(struct stasis_app_control *control, const char *endp
return 0;
}
+static int app_control_add_role(struct stasis_app_control *control,
+ struct ast_channel *chan, void *data)
+{
+ char *role = data;
+
+ return ast_channel_add_bridge_role(chan, role);
+}
+
int stasis_app_control_add_role(struct stasis_app_control *control, const char *role)
{
- return ast_channel_add_bridge_role(control->channel, role);
+ char *role_dup;
+
+ role_dup = ast_strdup(role);
+ if (!role_dup) {
+ return -1;
+ }
+
+ stasis_app_send_command_async(control, app_control_add_role, role_dup, ast_free_ptr);
+
+ return 0;
+}
+
+static int app_control_clear_roles(struct stasis_app_control *control,
+ struct ast_channel *chan, void *data)
+{
+ ast_channel_clear_bridge_roles(chan);
+
+ return 0;
}
void stasis_app_control_clear_roles(struct stasis_app_control *control)
{
- ast_channel_clear_bridge_roles(control->channel);
+ stasis_app_send_command_async(control, app_control_clear_roles, NULL, NULL);
}
int control_command_count(struct stasis_app_control *control)
@@ -598,9 +623,28 @@ int stasis_app_control_unmute(struct stasis_app_control *control, unsigned int d
return 0;
}
+static int app_control_set_channel_var(struct stasis_app_control *control,
+ struct ast_channel *chan, void *data)
+{
+ struct ast_variable *var = data;
+
+ pbx_builtin_setvar_helper(control->channel, var->name, var->value);
+
+ return 0;
+}
+
int stasis_app_control_set_channel_var(struct stasis_app_control *control, const char *variable, const char *value)
{
- return pbx_builtin_setvar_helper(control->channel, variable, value);
+ struct ast_variable *var;
+
+ var = ast_variable_new(variable, value, "ARI");
+ if (!var) {
+ return -1;
+ }
+
+ stasis_app_send_command_async(control, app_control_set_channel_var, var, ast_free_ptr);
+
+ return 0;
}
static int app_control_hold(struct stasis_app_control *control,