channel.c: Don't lock the channel in ast_softhangup while setting rtp instance vars

ast_softhangup() was locking the channel before calling ast_rtp_instance_set_stats_vars()
which, if the channel was in a bridge, then locked the bridge peer channel.  If another
thread attempted to set bridge variables on the peer, it would lock that channel first,
then this channel causing a lock inversion.  ast_softhangup() now holds the channel lock
while retrieving the rtp instance, then unlocks it before calling
ast_rtp_instance_set_stats_vars(), then locks it again after it returns.

Resolves: #1907
This commit is contained in:
George Joseph
2026-05-06 12:29:42 +00:00
committed by github-actions[bot]
parent f616affc2a
commit 3e52d75281
4 changed files with 53 additions and 7 deletions
+8 -1
View File
@@ -1654,7 +1654,14 @@ void ast_softhangup_all(void);
* (use this if you are trying to
* safely hangup a channel managed by another thread.
*
* \note The channel passed to this function does not need to be locked.
* \warning The channel passed to this function must NOT be locked.
* ast_softhangup() calls ast_rtp_instance_set_stats_vars() to set RTP QOS variables.
* If this channel is in a bridge, ast_rtp_instance_set_stats_vars() will
* attempt to lock the bridge peer as well as this channel. This can cause
* a lock inversion if we already have this channel locked and another
* thread tries to set bridge variables on the peer because it will have
* locked the peer first, then this channel. For this reason, we must
* NOT have the channel locked when we call ast_softhangup().
*
* \return Returns 0 regardless
*/
+7 -1
View File
@@ -2447,7 +2447,13 @@ int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp
* \param chan Channel to set the statistics on
* \param instance The RTP instance that statistics will be retrieved from
*
* \note Absolutely _NO_ channel locks should be held before calling this function.
* \warning Absolutely _NO_ channel locks should be held before calling this function.
* If this channel is in a bridge, ast_rtp_instance_set_stats_vars() will
* attempt to lock the bridge peer as well as this channel. This can cause
* a lock inversion if we already have this channel locked and another
* thread tries to set bridge variables on the peer because it will have
* locked the peer first, then this channel. For this reason, we must
* NOT have the channel locked when we call ast_rtp_instance_set_stats_vars().
*
* Example usage:
*