diff options
author | George Joseph <gjoseph@digium.com> | 2017-09-01 04:17:02 -0600 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2017-09-06 12:41:25 -0500 |
commit | 186ef1a657f21029705144dc30dcbe0bebb2d5d7 (patch) | |
tree | 062a6fc3881f9762a61e946cd0f25f589c9242c2 /main/bridge_after.c | |
parent | 9a366d24242a0fc1e7d04b8859ac5773193aa932 (diff) |
stasis/control: Fix possible deadlock with swap channel
If an error occurs during a bridge impart it's possible that
the "bridge_after" callback might try to run before
control_swap_channel_in_bridge has been signalled to continue.
Since control_swap_channel_in_bridge is holding the control lock
and the callback needs it, a deadlock will occur.
* control_swap_channel_in_bridge now only holds the control
lock while it's actually modifying the control structure and
releases it while the bridge impart is running.
* bridge_after_cb is now tolerant of impart failures.
Change-Id: Ifd239aa93955b3eb475521f61e284fcb0da2c3b3
Diffstat (limited to 'main/bridge_after.c')
-rw-r--r-- | main/bridge_after.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/main/bridge_after.c b/main/bridge_after.c index 1208b57b8..813510528 100644 --- a/main/bridge_after.c +++ b/main/bridge_after.c @@ -295,23 +295,23 @@ int ast_bridge_set_after_callback(struct ast_channel *chan, ast_bridge_after_cb return 0; } -const char *reason_strings[] = { - [AST_BRIDGE_AFTER_CB_REASON_DESTROY] = "Channel destroyed (hungup)", - [AST_BRIDGE_AFTER_CB_REASON_REPLACED] = "Callback was replaced", - [AST_BRIDGE_AFTER_CB_REASON_MASQUERADE] = "Channel masqueraded", - [AST_BRIDGE_AFTER_CB_REASON_DEPART] = "Channel was departed from bridge", - [AST_BRIDGE_AFTER_CB_REASON_REMOVED] = "Callback was removed", -}; - const char *ast_bridge_after_cb_reason_string(enum ast_bridge_after_cb_reason reason) { - if (reason < AST_BRIDGE_AFTER_CB_REASON_DESTROY - || AST_BRIDGE_AFTER_CB_REASON_REMOVED < reason - || !reason_strings[reason]) { - return "Unknown"; - } - - return reason_strings[reason]; + switch (reason) { + case AST_BRIDGE_AFTER_CB_REASON_DESTROY: + return "Channel destroyed (hungup)"; + case AST_BRIDGE_AFTER_CB_REASON_REPLACED: + return "Callback was replaced"; + case AST_BRIDGE_AFTER_CB_REASON_MASQUERADE: + return "Channel masqueraded"; + case AST_BRIDGE_AFTER_CB_REASON_DEPART: + return "Channel was departed from bridge"; + case AST_BRIDGE_AFTER_CB_REASON_REMOVED: + return "Callback was removed"; + case AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED: + return "Channel failed joining the bridge"; + } + return "Unknown"; } struct after_bridge_goto_ds { |