From ea04aadb331c046d2e6334f89d2b829cfbeb650d Mon Sep 17 00:00:00 2001 From: Tinet-mucw Date: Wed, 26 Aug 2026 18:13:41 -0700 Subject: [PATCH] apps/app_chanspy: don't delay spyee Hangup when spy channel has no reverse media channel_spy() waited indefinitely on the spy channel, so after the spyee hung up the spy audiohook leaving RUNNING was not noticed until waitfor timed out. That kept an autochan reference on the spyee and delayed its destructor / Hangup. Poll with a short timeout instead. On timeout, only re-check hook status; call ast_read() only when the spy channel is readable. Resolves: #2123 --- apps/app_chanspy.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index adcd72df20..b9a9f39b3c 100644 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -811,14 +811,23 @@ static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_auto channel has gone away. */ - /* Note: it is very important that the ast_waitfor() be the first - condition in this expression, so that if we wait for some period - of time before receiving a frame from our spying channel, we check - for hangup on the spied-on channel _after_ knowing that a frame - has arrived, since the spied-on channel could have gone away while - we were waiting + /* Use a short waitfor timeout so we notice the spy audiohook leaving + RUNNING promptly. An indefinite wait holds an autochan ref on the + spyee until waitfor times out, delaying destructor / Hangup when + the spy channel is not readable. */ - while (ast_waitfor(chan, -1) > -1 && csth.spy_audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) { + while (csth.spy_audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) { + int waitres = ast_waitfor(chan, 100); + + if (waitres < 0) { + running = -1; + break; + } + if (waitres == 0) { + /* Timeout: re-check hook status without reading. */ + continue; + } + if (!(f = ast_read(chan)) || ast_check_hangup(chan)) { running = -1; if (f) {