From c3d5c41dae0b192a4967bc3b462de6c2bede8766 Mon Sep 17 00:00:00 2001 From: Joshua Colp <jcolp@digium.com> Date: Tue, 24 Dec 2013 02:20:18 +0000 Subject: [PATCH] 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 --- res/res_pjsip_pubsub.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c index 5bcfd07cec..2dcfaf68a8 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); } -- GitLab