summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2015-08-31 16:11:34 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2015-08-31 16:11:35 -0500
commit4e3b3f25f67c2ee82447a22c347af397ee502c3e (patch)
treecadad6d2e6628fe6d2094da4b916f16ffe246fbb
parent45b06a648beb8f12066e80ead0169e5fd8ecf5da (diff)
parent03fe79f29eae42be24589b323a5ef3fa9259158d (diff)
Merge "Fix deadlock on presence state changes." into 13
-rw-r--r--main/pbx.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/main/pbx.c b/main/pbx.c
index f23dff7d2..b34a060ba 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -11978,10 +11978,11 @@ static void presence_state_cb(void *unused, struct stasis_subscription *sub, str
struct ast_state_cb *state_cb;
const char *app;
char *parse;
- SCOPED_AO2LOCK(lock, hint);
+ ao2_lock(hint);
if (!hint->exten) {
/* The extension has already been destroyed */
+ ao2_unlock(hint);
continue;
}
@@ -11989,16 +11990,19 @@ static void presence_state_cb(void *unused, struct stasis_subscription *sub, str
app = ast_get_extension_app(hint->exten);
if (ast_strlen_zero(app)) {
/* The hint does not monitor presence at all. */
+ ao2_unlock(hint);
continue;
}
ast_str_set(&hint_app, 0, "%s", app);
parse = parse_hint_presence(hint_app);
if (ast_strlen_zero(parse)) {
+ ao2_unlock(hint);
continue;
}
if (strcasecmp(parse, presence_state->provider)) {
/* The hint does not monitor the presence provider. */
+ ao2_unlock(hint);
continue;
}
@@ -12019,6 +12023,7 @@ static void presence_state_cb(void *unused, struct stasis_subscription *sub, str
((hint->last_presence_message && presence_state->message && !strcmp(hint->last_presence_message, presence_state->message)) || (!hint->last_presence_message && !presence_state->message))) {
/* this update is the same as the last, do nothing */
+ ao2_unlock(hint);
continue;
}
@@ -12028,6 +12033,14 @@ static void presence_state_cb(void *unused, struct stasis_subscription *sub, str
hint->last_presence_state = presence_state->state;
hint->last_presence_subtype = presence_state->subtype ? ast_strdup(presence_state->subtype) : NULL;
hint->last_presence_message = presence_state->message ? ast_strdup(presence_state->message) : NULL;
+ /*
+ * (Copied from device_state_cb)
+ *
+ * NOTE: We cannot hold any locks while notifying
+ * the watchers without causing a deadlock.
+ * (conlock, hints, and hint)
+ */
+ ao2_unlock(hint);
/* For general callbacks */
cb_iter = ao2_iterator_init(statecbs, 0);