mirror of
https://github.com/asterisk/asterisk.git
synced 2025-12-03 11:41:49 +00:00
Merge "core_local: local channel data not being properly unref'ed and unlocked"
This commit is contained in:
@@ -42,36 +42,37 @@ struct stasis_message_type;
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
/*!
|
||||
* \brief Lock the "chan" and "owner" channels (and return them) on the base
|
||||
* private structure as well as the base private structure itself.
|
||||
* \brief Add a reference to the local channel's private tech, lock the local channel's
|
||||
* private base, and add references and lock both sides of the local channel.
|
||||
*
|
||||
* \note This also adds references to each of the above mentioned elements and
|
||||
* also the underlying private local structure.
|
||||
* \note None of these locks should be held prior to calling this function.
|
||||
* \note To undo this process call ast_local_unlock_all.
|
||||
* \note To undo this process call ast_local_unlock_all2.
|
||||
*
|
||||
* \since 13.8.0
|
||||
* \since 13.17.0, 14.6.0
|
||||
*
|
||||
* \param chan Must be a local channel
|
||||
* \param outchan The local channel's "chan" channel
|
||||
* \param outowner The local channel's "owner" channel
|
||||
* \param tech_pvt [out] channel's private tech (ref and lock added)
|
||||
* \param base_chan [out] One side of the local channel (ref and lock added)
|
||||
* \param base_owner [out] Other side of the local channel (ref and lock added)
|
||||
*/
|
||||
void ast_local_lock_all(struct ast_channel *chan, struct ast_channel **outchan,
|
||||
struct ast_channel **outowner);
|
||||
void ast_local_lock_all(struct ast_channel *chan, void **tech_pvt,
|
||||
struct ast_channel **base_chan, struct ast_channel **base_owner);
|
||||
|
||||
/*!
|
||||
* \brief Unlock the "chan" and "owner" channels on the base private structure
|
||||
* as well as the base private structure itself.
|
||||
* \brief Remove a reference to the given local channel's private tech, unlock the given
|
||||
* local channel's private base, and remove references and unlock both sides of
|
||||
* given the local channel.
|
||||
*
|
||||
* \note This also removes references to each of the above mentioned elements and
|
||||
* also the underlying private local structure.
|
||||
* \note This function should be used in conjunction with ast_local_lock_all.
|
||||
* \note This function should be used in conjunction with ast_local_lock_all2.
|
||||
*
|
||||
* \since 13.8.0
|
||||
* \since 13.17.0, 14.6.0
|
||||
*
|
||||
* \param chan Must be a local channel
|
||||
* \param tech_pvt channel's private tech (ref and lock removed)
|
||||
* \param base_chan One side of the local channel (ref and lock removed)
|
||||
* \param base_owner Other side of the local channel (ref and lock removed)
|
||||
*/
|
||||
void ast_local_unlock_all(struct ast_channel *chan);
|
||||
void ast_local_unlock_all(void *tech_pvt, struct ast_channel *base_chan,
|
||||
struct ast_channel *base_owner);
|
||||
|
||||
/*!
|
||||
* \brief Get the other local channel in the pair.
|
||||
|
||||
@@ -4276,14 +4276,15 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha
|
||||
BRIDGE_LOCK_ONE_OR_BOTH(bridge1, bridge2);
|
||||
|
||||
if (bridge2) {
|
||||
void *tech;
|
||||
struct ast_channel *locals[2];
|
||||
|
||||
/* Have to lock everything just in case a hangup comes in early */
|
||||
ast_local_lock_all(local_chan, &locals[0], &locals[1]);
|
||||
ast_local_lock_all(local_chan, &tech, &locals[0], &locals[1]);
|
||||
if (!locals[0] || !locals[1]) {
|
||||
ast_log(LOG_ERROR, "Transfer failed probably due to an early hangup - "
|
||||
"missing other half of '%s'\n", ast_channel_name(local_chan));
|
||||
ast_local_unlock_all(local_chan);
|
||||
ast_local_unlock_all(tech, locals[0], locals[1]);
|
||||
ao2_cleanup(local_chan);
|
||||
return AST_BRIDGE_TRANSFER_FAIL;
|
||||
}
|
||||
@@ -4294,7 +4295,7 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha
|
||||
}
|
||||
|
||||
ast_attended_transfer_message_add_link(transfer_msg, locals);
|
||||
ast_local_unlock_all(local_chan);
|
||||
ast_local_unlock_all(tech, locals[0], locals[1]);
|
||||
} else {
|
||||
ast_attended_transfer_message_add_app(transfer_msg, app, local_chan);
|
||||
}
|
||||
|
||||
@@ -233,43 +233,39 @@ struct local_pvt {
|
||||
char exten[AST_MAX_EXTENSION];
|
||||
};
|
||||
|
||||
void ast_local_lock_all(struct ast_channel *chan, struct ast_channel **outchan,
|
||||
struct ast_channel **outowner)
|
||||
void ast_local_lock_all(struct ast_channel *chan, void **tech_pvt,
|
||||
struct ast_channel **base_chan, struct ast_channel **base_owner)
|
||||
{
|
||||
struct local_pvt *p = ast_channel_tech_pvt(chan);
|
||||
|
||||
*outchan = NULL;
|
||||
*outowner = NULL;
|
||||
*tech_pvt = NULL;
|
||||
*base_chan = NULL;
|
||||
*base_owner = NULL;
|
||||
|
||||
if (p) {
|
||||
ao2_ref(p, 1);
|
||||
ast_unreal_lock_all(&p->base, outchan, outowner);
|
||||
*tech_pvt = ao2_bump(p);
|
||||
ast_unreal_lock_all(&p->base, base_chan, base_owner);
|
||||
}
|
||||
}
|
||||
|
||||
void ast_local_unlock_all(struct ast_channel *chan)
|
||||
void ast_local_unlock_all(void *tech_pvt, struct ast_channel *base_chan,
|
||||
struct ast_channel *base_owner)
|
||||
{
|
||||
struct local_pvt *p = ast_channel_tech_pvt(chan);
|
||||
struct ast_unreal_pvt *base;
|
||||
|
||||
if (!p) {
|
||||
return;
|
||||
if (base_chan) {
|
||||
ast_channel_unlock(base_chan);
|
||||
ast_channel_unref(base_chan);
|
||||
}
|
||||
|
||||
base = &p->base;
|
||||
|
||||
if (base->owner) {
|
||||
ast_channel_unlock(base->owner);
|
||||
ast_channel_unref(base->owner);
|
||||
if (base_owner) {
|
||||
ast_channel_unlock(base_owner);
|
||||
ast_channel_unref(base_owner);
|
||||
}
|
||||
|
||||
if (base->chan) {
|
||||
ast_channel_unlock(base->chan);
|
||||
ast_channel_unref(base->chan);
|
||||
if (tech_pvt) {
|
||||
struct local_pvt *p = tech_pvt;
|
||||
ao2_unlock(&p->base);
|
||||
ao2_ref(tech_pvt, -1);
|
||||
}
|
||||
|
||||
ao2_unlock(base);
|
||||
ao2_ref(p, -1);
|
||||
}
|
||||
|
||||
struct ast_channel *ast_local_get_peer(struct ast_channel *ast)
|
||||
|
||||
Reference in New Issue
Block a user