]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip_refer: Move the progress dlg release to a serializer
authorGeorge Joseph <gjoseph@digium.com>
Tue, 2 Mar 2021 18:55:38 +0000 (11:55 -0700)
committerGeorge Joseph <gjoseph@digium.com>
Fri, 5 Mar 2021 14:18:55 +0000 (08:18 -0600)
Although the dlg session count was incremented in a pjsip servant
thread, there's no guarantee that the last thread to unref this
progress object was one.  Before we decrement, we need to make
sure that this is either a servant thread or that we push the
decrement to a serializer that is one.

Because pjsip_dlg_dec_session requires the dialog lock, we don't
want to wait on the task to complete if we had to push it to a
serializer.

Change-Id: I8ff2d5d94be3ff04298394070434e22a7d3cbc41

res/res_pjsip_refer.c

index 07fe23d78de6bd667c0b0880aa29e7466391e010..8890d235b5689416eb405b1301071e03ffce8c52 100644 (file)
@@ -340,6 +340,11 @@ static pjsip_evsub_user refer_progress_evsub_cb = {
        .on_evsub_state = refer_progress_on_evsub_state,
 };
 
+static int dlg_releaser_task(void *data) {
+       pjsip_dlg_dec_session((pjsip_dialog *)data, &refer_progress_module);
+       return 0;
+}
+
 /*! \brief Destructor for REFER progress sutrcture */
 static void refer_progress_destroy(void *obj)
 {
@@ -350,7 +355,21 @@ static void refer_progress_destroy(void *obj)
        }
 
        if (progress->dlg) {
-               pjsip_dlg_dec_session(progress->dlg, &refer_progress_module);
+               /*
+                * Although the dlg session count was incremented in a pjsip servant
+                * thread, there's no guarantee that the last thread to unref this progress
+                * object was one.  Before we decrement, we need to make sure that this
+                * is either a servant thread or that we push the decrement to a
+                * serializer that is one.
+                *
+                * Because pjsip_dlg_dec_session requires the dialog lock, we don't want
+                * to wait on the task to complete if we had to push it to a serializer.
+                */
+               if (ast_sip_thread_is_servant()) {
+                       pjsip_dlg_dec_session(progress->dlg, &refer_progress_module);
+               } else {
+                       ast_sip_push_task(NULL, dlg_releaser_task, progress->dlg);
+               }
        }
 
        ao2_cleanup(progress->transfer_data);