summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Michelson <mmichelson@digium.com>2016-02-04 11:39:10 -0600
committerMark Michelson <mmichelson@digium.com>2016-02-04 11:39:10 -0600
commit23829b325377ae32f78cef81a48cc4318a7206b9 (patch)
treec475b0fc60b18ed5fdb87884baa24b65a7a2342a
parentf55f79edbaa9066f2ffb36c9a7c2433357698615 (diff)
res_stasis_device_state: Fix refcounting error.
Device state subscription lifetimes were governed by when the subscription was established and unsubscribed from. However, it is possible that at the time of unsubscription, there could be device state events still in flight. When those device state events occur, the device state callback could attempt to dereference a freed pointer. Crash. This change ensures that the lifetime of the device state subscription does not end until the underlying stasis subscription has confirmed that its final message has been sent. Change-Id: I25a0f1472894c1a562252fb7129671478e25e9b2
-rw-r--r--res/res_stasis_device_state.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/res/res_stasis_device_state.c b/res/res_stasis_device_state.c
index c0b6859ca..be082dcc8 100644
--- a/res/res_stasis_device_state.c
+++ b/res/res_stasis_device_state.c
@@ -303,6 +303,12 @@ static void device_state_cb(void *data, struct stasis_subscription *sub,
{
struct ast_device_state_message *device_state;
+ if (stasis_subscription_final_message(sub, msg)) {
+ /* Remove stasis subscription's reference to device_state_subscription */
+ ao2_ref(data, -1);
+ return;
+ }
+
if (ast_device_state_message_type() != stasis_message_type(msg)) {
return;
}
@@ -365,10 +371,12 @@ static int subscribe_device_state(struct stasis_app *app, void *obj)
ast_debug(3, "Subscribing to device %s\n", sub->device_name);
- sub->sub = stasis_subscribe_pool(topic, device_state_cb, sub);
+ sub->sub = stasis_subscribe_pool(topic, device_state_cb, ao2_bump(sub));
if (!sub->sub) {
ast_log(LOG_ERROR, "Unable to subscribe to device %s\n",
sub->device_name);
+ /* Reference we added when attempting to stasis_subscribe_pool */
+ ao2_ref(sub, -1);
return -1;
}