pbx: Fix hints deadlock between reload and ExtensionState.
When the ExtensionState AMI action is executed on a pattern matched hint it can end up adding a new hint if one does not already exist. This results in a locking order of contexts -> hints -> contexts. If at the same time a reload is occurring and adding its own hint it will have a locking order of hints -> contexts. This results in a deadlock as one thread wants a lock on contexts that the other has, and the other thread wants a lock on hints that the other has. This change enforces a hints -> contexts locking order by explicitly locking hints in the places where a hint is added when queried for. This matches the order seen through normal adding of hints. ASTERISK-29046 Change-Id: I49f027f4aab5d2d50855ae937bcf5e2fd8bfc504
This commit is contained in:
parent
5a8cacb93d
commit
6d50d152d8
11
main/pbx.c
11
main/pbx.c
|
@ -3148,10 +3148,15 @@ static int internal_extension_state_extended(struct ast_channel *c, const char *
|
|||
}
|
||||
|
||||
if (e->exten[0] == '_') {
|
||||
/* Create this hint on-the-fly */
|
||||
/* Create this hint on-the-fly, we explicitly lock hints here to ensure the
|
||||
* same locking order as if this were done through configuration file - that is
|
||||
* hints is locked first and then (if needed) contexts is locked
|
||||
*/
|
||||
ao2_lock(hints);
|
||||
ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
|
||||
e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
|
||||
e->registrar);
|
||||
ao2_unlock(hints);
|
||||
if (!(e = ast_hint_extension(c, context, exten))) {
|
||||
/* Improbable, but not impossible */
|
||||
return -1;
|
||||
|
@ -3228,9 +3233,11 @@ int ast_hint_presence_state(struct ast_channel *c, const char *context, const ch
|
|||
|
||||
if (e->exten[0] == '_') {
|
||||
/* Create this hint on-the-fly */
|
||||
ao2_lock(hints);
|
||||
ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
|
||||
e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
|
||||
e->registrar);
|
||||
ao2_unlock(hints);
|
||||
if (!(e = ast_hint_extension(c, context, exten))) {
|
||||
/* Improbable, but not impossible */
|
||||
return -1;
|
||||
|
@ -3766,9 +3773,11 @@ static int extension_state_add_destroy(const char *context, const char *exten,
|
|||
* individual extension, because the pattern will no longer match first.
|
||||
*/
|
||||
if (e->exten[0] == '_') {
|
||||
ao2_lock(hints);
|
||||
ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
|
||||
e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
|
||||
e->registrar);
|
||||
ao2_unlock(hints);
|
||||
e = ast_hint_extension(NULL, context, exten);
|
||||
if (!e || e->exten[0] == '_') {
|
||||
return -1;
|
||||
|
|
Loading…
Reference in New Issue