diff options
author | George Joseph <gjoseph@digium.com> | 2016-06-12 10:19:27 -0600 |
---|---|---|
committer | George Joseph <gjoseph@digium.com> | 2016-06-21 12:47:36 -0600 |
commit | 6a568bcc665714376d077b562ee819d864b2e520 (patch) | |
tree | 8c1952e7ec009294161c6a92fa3de82cda95917a /third-party/pjproject/patches | |
parent | 4d52b4c3e5fd726ee4006a1dcca082e778deb9a7 (diff) |
res_pjsip_pubsub: Address SEGV when attempting to terminate a subscription
Occasionally under load we'll attempt to send a final NOTIFY on a
subscription that's already been terminated and a SEGV will occur
down in pjproject's evsub_destroy function. This is a result of a
race condition between all the paths that can generate a notify
and/or destroy the underlying pjproject evsub object:
* The client can send a SUBSCRIBE with Expires: 0.
* The client can send a SUBSCRIBE/refresh.
* The subscription timer can expire.
* An extension state can change.
* An MWI event can be generated.
* The pjproject transaction timer (timer_b) can expire.
Normally when our pubsub_on_evsub_state is called with a terminate,
we push a task to the serializer and return at which point the dialog
is unlocked. This is usually not a problem because the task runs
immediately and locks the dialog again. When the system is heavily
loaded though, there may be a delay between the unlock and relock
during which another event may occur such as the subscription timer
or timer_b expiring, an extension state change, etc. These may also
cause a terminate to be processed and if so, we could cause pjproject
to try to destroy the evsub structure twice. There's no way for us to
tell that the evsub was already destroyed and the evsub's group lock
can't tolerate this and SEGVs.
The remedy is twofold.
* A patch has been submitted to Teluu and added to the bundled
pjproject which adds add/decrement operations on evsub's group lock.
* In res_pjsip_pubsub:
* configure.ac and pjproject-bundled's configure.m4 were updated
to check for the new evsub group lock APIs.
* We now add a reference to the evsub group lock when we create
the subscription and remove the reference when we clean up the
subscription. This prevents evsub from being destroyed before
we're done with it.
* A state has been added to the subscription tree structure so
termination progress can be tracked through the asyncronous tasks.
* The pubsub_on_evsub_state callback has been split so it's not doing
double duty. It now only handles the final cleanup of the
subscription tree. pubsub_on_rx_refresh now handles both client
refreshes and client terminates. It was always being called for
both anyway.
* The serialized_on_server_timeout task was removed since
serialized_pubsub_on_rx_refresh was almost identical.
* Missing state checks and ao2_cleanups were added.
* Some debug levels were adjusted to make seeing only off-nominal
things at level 1 and nominal or progress things at level 2+.
ASTERISK-26099 #close
Reported-by: Ross Beer.
Change-Id: I779d11802cf672a51392e62a74a1216596075ba1
Diffstat (limited to 'third-party/pjproject/patches')
-rw-r--r-- | third-party/pjproject/patches/0001-evsub-Add-APIs-to-add-decrement-an-event-subscriptio.patch | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/third-party/pjproject/patches/0001-evsub-Add-APIs-to-add-decrement-an-event-subscriptio.patch b/third-party/pjproject/patches/0001-evsub-Add-APIs-to-add-decrement-an-event-subscriptio.patch new file mode 100644 index 000000000..d2a47c6c5 --- /dev/null +++ b/third-party/pjproject/patches/0001-evsub-Add-APIs-to-add-decrement-an-event-subscriptio.patch @@ -0,0 +1,73 @@ +From a5030c9b33b2c936879fbacb1d2ea5edc2979181 Mon Sep 17 00:00:00 2001 +From: George Joseph <gjoseph@digium.com> +Date: Sat, 18 Jun 2016 10:14:34 -0600 +Subject: [PATCH] evsub: Add APIs to add/decrement an event subscription's + group lock + +These APIs can be used to ensure that the evsub isn't destroyed before +an application is finished using it. +--- + pjsip/include/pjsip-simple/evsub.h | 20 ++++++++++++++++++++ + pjsip/src/pjsip-simple/evsub.c | 14 ++++++++++++++ + 2 files changed, 34 insertions(+) + +diff --git a/pjsip/include/pjsip-simple/evsub.h b/pjsip/include/pjsip-simple/evsub.h +index 2dc4d69..31f85f8 100644 +--- a/pjsip/include/pjsip-simple/evsub.h ++++ b/pjsip/include/pjsip-simple/evsub.h +@@ -490,6 +490,26 @@ PJ_DECL(void) pjsip_evsub_set_mod_data( pjsip_evsub *sub, unsigned mod_id, + PJ_DECL(void*) pjsip_evsub_get_mod_data( pjsip_evsub *sub, unsigned mod_id ); + + ++/** ++ * Increment the event subscription's group lock. ++ * ++ * @param sub The server subscription instance. ++ * ++ * @return PJ_SUCCESS on success. ++ */ ++PJ_DEF(pj_status_t) pjsip_evsub_add_ref(pjsip_evsub *sub); ++ ++ ++/** ++ * Decrement the event subscription's group lock. ++ * ++ * @param sub The server subscription instance. ++ * ++ * @return PJ_SUCCESS on success. ++ */ ++PJ_DEF(pj_status_t) pjsip_evsub_dec_ref(pjsip_evsub *sub); ++ ++ + + PJ_END_DECL + +diff --git a/pjsip/src/pjsip-simple/evsub.c b/pjsip/src/pjsip-simple/evsub.c +index 7cd8859..68a9564 100644 +--- a/pjsip/src/pjsip-simple/evsub.c ++++ b/pjsip/src/pjsip-simple/evsub.c +@@ -831,7 +831,21 @@ static pj_status_t evsub_create( pjsip_dialog *dlg, + return PJ_SUCCESS; + } + ++/* ++ * Increment the event subscription's group lock. ++ */ ++PJ_DEF(pj_status_t) pjsip_evsub_add_ref(pjsip_evsub *sub) ++{ ++ return pj_grp_lock_add_ref(sub->grp_lock); ++} + ++/* ++ * Decrement the event subscription's group lock. ++ */ ++PJ_DEF(pj_status_t) pjsip_evsub_dec_ref(pjsip_evsub *sub) ++{ ++ return pj_grp_lock_dec_ref(sub->grp_lock); ++} + + /* + * Create client subscription session. +-- +2.5.5 + |