[asterisk-scf-commits] asterisk-scf/release/sip.git branch "master" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Fri Jun 15 12:07:29 CDT 2012
branch "master" has been updated
via 447c46a76ebf4f537f302213e35195b3f04aef48 (commit)
from 58cc573539da83eb5bf2fc45c404fdfbf88560ec (commit)
Summary of changes:
src/SIPSession.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 85 insertions(+), 2 deletions(-)
- Log -----------------------------------------------------------------
commit 447c46a76ebf4f537f302213e35195b3f04aef48
Author: Brent Eagles <beagles at digium.com>
Date: Fri Jun 15 14:29:42 2012 -0230
Add a fix to get around a race condition resulting in pjsip flip/flopping
SDP session related pools while we are using them in another thread. The
fix involves creating a separate SDP pool in SIPSession for its own use and
managing it in sync with its own requirements.
diff --git a/src/SIPSession.cpp b/src/SIPSession.cpp
index aabfde6..a963e9a 100755
--- a/src/SIPSession.cpp
+++ b/src/SIPSession.cpp
@@ -145,11 +145,20 @@ public:
mAdapter(adapter), mDialog(0), mInviteSession(0), mEndpoint(endpoint), mDestination(destination),
mManager(manager), mServiceLocator(serviceLocator), mReplicationContext(replicationContext),
mNatOptions(natOptions), mSDP(0),
- mOperationContextCache(OperationContextCache::create(180))
+ mOperationContextCache(OperationContextCache::create(180)),
+ mSDPPool(0)
{
}
+ ~SIPSessionPriv()
+ {
+ if (mSDPPool)
+ {
+ pj_pool_release(mSDPPool);
+ }
+ }
+
void removeListener(const AsteriskSCF::SessionCommunications::V1::SessionListenerPrx& listener)
{
@@ -353,9 +362,78 @@ public:
AsteriskSCF::Operations::OperationContextCachePtr mOperationContextCache;
+ /**
+ * Get our pjsip memory pool for the current SDP negotiation session. Using an
+ * independent pool prevents memory growth for long running sessions as the pool
+ * is reset whenever starting a new SDP session. Of course, this means you should
+ * not cache pointers to memory in the pool outside the context of an SDP
+ * negotiation session.
+ *
+ * WARNING: All of SIPSession's operations that appear to be related to SDP
+ * negotiation are not necessarily called during an SDP negotiation session
+ * (they are called before). This pool is not (and probably should not) be
+ * used in these places at the moment. If the code changes in the future to
+ * break the "in process" SDP negotation related code out of the standard
+ * initialization code, then this could be used there as well if necessary.
+ */
+ pj_pool_t* getSDPPool()
+ {
+ //
+ // We should not be looking at SDP pool if we are not within and invite.
+ //
+ if (!mInviteSession || !mInviteSession->dlg)
+ {
+ return 0;
+ }
+
+ if (!mSDPPool)
+ {
+ string sdpPoolName = mEndpoint->getName() + ".sdp.pool";
+ mSDPPool = pjsip_endpt_create_pool(
+ mInviteSession->dlg->endpt,
+ sdpPoolName.c_str(),
+ 256,
+ 256);
+ }
+ return mSDPPool;
+ }
+
+ /**
+ * Reset our internal SDP pool. Should be called when starting SDP
+ * negotiation. So far, the only place where we use it is in responding to
+ * an offer.
+ *
+ * WARNING: All of SIPSession's operations that appear to be related to SDP
+ * negotiation are not necessarily called during an SDP negotiation session
+ * (they are called before). This pool is not (and probably should not) be
+ * used in these places at the moment. If the code changes in the future to
+ * break the "in process" SDP negotation related code out of the standard
+ * initialization code, then this could be used there as well if necessary.
+ */
+ void resetSDPPool()
+ {
+ pj_pool_t* t = getSDPPool();
+ if (t)
+ {
+ pj_pool_reset(t);
+ }
+ }
+
private:
static ReadOnlyCookieTypes mReadOnlyCookieTypes;
+ //
+ // There is race condition in pjsip with the memory pool flip/flopping
+ // before and after negotiation. It is not safe when a separate worker thread
+ // handles the SDP negotiation operations (as it does here). The really
+ // safe thing to do is to have our own memory pool for SDP related stuff
+ // and reset it whenever we enter and SDP call flow. These calls cannot (or
+ // should not) be made recursively for a given session, so contention and
+ // races should not be an issue. The data member is accessed through
+ // accessors to prevent repetition of boilerplate.
+ //
+ pj_pool_t* mSDPPool;
+
}; // class SIPSessionPriv
typedef boost::shared_ptr<SIPSessionPriv> SIPSessionPrivPtr;
@@ -3789,6 +3867,11 @@ pjmedia_sdp_session *SIPSession::createSDPAnswer(
const pjmedia_sdp_session* offer,
AsteriskSCF::Media::V1::StreamInformationDict& newStreams)
{
+ //
+ // Entering a new SDP negotiation, restart our pool.
+ //
+ mImplPriv->resetSDPPool();
+
// Create the most common part of the SDP if not already done
if (!mImplPriv->mSDP)
{
@@ -3878,7 +3961,7 @@ pjmedia_sdp_session *SIPSession::createSDPAnswer(
&offer->media[stream]->desc.fmt[format])))
{
pjmedia_sdp_rtpmap *rtpmap;
- if ((pjmedia_sdp_attr_to_rtpmap(mImplPriv->mInviteSession->pool_active, attr, &rtpmap)) == PJ_SUCCESS)
+ if ((pjmedia_sdp_attr_to_rtpmap(mImplPriv->getSDPPool(), attr, &rtpmap)) == PJ_SUCCESS)
{
descriptor->subtype = std::string(pj_strbuf(&rtpmap->enc_name), pj_strlen(&rtpmap->enc_name));
descriptor->samplerate = rtpmap->clock_rate;
-----------------------------------------------------------------------
--
asterisk-scf/release/sip.git
More information about the asterisk-scf-commits
mailing list