summaryrefslogtreecommitdiff
path: root/res/res_pjsip_pubsub.c
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2013-12-24 02:20:18 +0000
committerJoshua Colp <jcolp@digium.com>2013-12-24 02:20:18 +0000
commitc3d5c41dae0b192a4967bc3b462de6c2bede8766 (patch)
tree4d4f1815cafef35bce141c620b62211a8eb551e5 /res/res_pjsip_pubsub.c
parent82eb03b915ccfc26ae453695f3de1296de7c7390 (diff)
res_pjsip_pubsub: Ensure dialog manipulation happens on proper thread.
When destroying a subscription we remove the serializer from its dialog and decrease its reference count. Depending on which thread dropped the subscription reference count to 0 it was possible for this to occur in a thread where it is not possible. (closes issue ASTERISK-22952) Reported by: Matt Jordan ........ Merged revisions 404553 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404554 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/res_pjsip_pubsub.c')
-rw-r--r--res/res_pjsip_pubsub.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index 5bcfd07ce..2dcfaf68a 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -303,6 +303,25 @@ static int datastore_cmp(void *obj, void *arg, int flags)
return strcmp(datastore1->uid, uid2) ? 0 : CMP_MATCH | CMP_STOP;
}
+static int subscription_remove_serializer(void *obj)
+{
+ struct ast_sip_subscription *sub = obj;
+
+ /* This is why we keep the dialog on the subscription. When the subscription
+ * is destroyed, there is no guarantee that the underlying dialog is ready
+ * to be destroyed. Furthermore, there's no guarantee in the opposite direction
+ * either. The dialog could be destroyed before our subscription is. We fix
+ * this problem by keeping a reference to the dialog until it is time to
+ * destroy the subscription. We need to have the dialog available when the
+ * subscription is destroyed so that we can guarantee that our attempt to
+ * remove the serializer will be successful.
+ */
+ ast_sip_dialog_set_serializer(sub->dlg, NULL);
+ pjsip_dlg_dec_session(sub->dlg, &pubsub_module);
+
+ return 0;
+}
+
static void subscription_destructor(void *obj)
{
struct ast_sip_subscription *sub = obj;
@@ -314,17 +333,7 @@ static void subscription_destructor(void *obj)
ao2_cleanup(sub->endpoint);
if (sub->dlg) {
- /* This is why we keep the dialog on the subscription. When the subscription
- * is destroyed, there is no guarantee that the underlying dialog is ready
- * to be destroyed. Furthermore, there's no guarantee in the opposite direction
- * either. The dialog could be destroyed before our subscription is. We fix
- * this problem by keeping a reference to the dialog until it is time to
- * destroy the subscription. We need to have the dialog available when the
- * subscription is destroyed so that we can guarantee that our attempt to
- * remove the serializer will be successful.
- */
- ast_sip_dialog_set_serializer(sub->dlg, NULL);
- pjsip_dlg_dec_session(sub->dlg, &pubsub_module);
+ ast_sip_push_task_synchronous(NULL, subscription_remove_serializer, sub);
}
ast_taskprocessor_unreference(sub->serializer);
}