diff --git a/channels/chan_sip.c b/channels/chan_sip.c index e9ef2d695..79e570b39 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -27966,7 +27966,20 @@ static int sip_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl) if (!p) { return -1; } + /* + * Lock both the pvt and it's owner safely. + */ sip_pvt_lock(p); + while (p->owner && ast_channel_trylock(p->owner)) { + sip_pvt_unlock(p); + usleep(1); + sip_pvt_lock(p); + } + + if (!p->owner) { + sip_pvt_unlock(p); + return 0; + } if (udptl) { ast_udptl_get_peer(udptl, &p->udptlredirip); } else { @@ -27985,6 +27998,7 @@ static int sip_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl) } /* Reset lastrtprx timer */ p->lastrtprx = p->lastrtptx = time(NULL); + ast_channel_unlock(p->owner); sip_pvt_unlock(p); return 0; } @@ -28102,12 +28116,25 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i return 0; } - ast_channel_lock(chan); + /* + * Lock both the pvt and it's owner safely. + */ sip_pvt_lock(p); + while (p->owner && ast_channel_trylock(p->owner)) { + sip_pvt_unlock(p); + usleep(1); + sip_pvt_lock(p); + } + + if (!p->owner) { + sip_pvt_unlock(p); + return 0; + } + if (p->alreadygone) { /* If we're destroyed, don't bother */ + ast_channel_unlock(p->owner); sip_pvt_unlock(p); - ast_channel_unlock(chan); return 0; } @@ -28115,8 +28142,8 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i that are known to be behind a NAT, then stop the process now */ if (nat_active && !ast_test_flag(&p->flags[0], SIP_DIRECT_MEDIA_NAT)) { + ast_channel_unlock(p->owner); sip_pvt_unlock(p); - ast_channel_unlock(chan); return 0; } @@ -28158,8 +28185,8 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *i } /* Reset lastrtprx timer */ p->lastrtprx = p->lastrtptx = time(NULL); + ast_channel_unlock(p->owner); sip_pvt_unlock(p); - ast_channel_unlock(chan); return 0; }