Skip to content

sip: buffer the ACK channel instead of parking a goroutine - #364

Closed
fridokus wants to merge 1 commit into
emiago:mainfrom
fridokus:ack-buffer
Closed

fridokus wants to merge 1 commit into
emiago:mainfrom
fridokus:ack-buffer

Conversation

@fridokus

@fridokus fridokus commented Sep 17, 2026 •

Copy link
Copy Markdown

ackSendAsync is reached only from actPassupAck, and only the Accepted state has an edge to it — so the only ACK ever offered to Acks() is the one to a 2xx. Nothing receives it: DialogServer reads Acks() on the non-2xx branch, and that ACK goes to actConfirm, which doesn't pass up.

So the non-blocking send always failed, a goroutine was spawned to hold the ACK, and at Timer L it logged ACK missed at WARN. A 2h soak produced 8939 of them — one per answered call.

A one-slot buffer holds the ACK without the goroutine, and lets a consumer that arrives after the transaction is done still read it. The send can no longer block, so default logs at Debug.

Also corrects the Acks() comment: the channel is created in NewServerTx, not on demand.

Two tests: an ACK sent before the receive is still delivered (so the buffer can't be dropped without the goroutine coming back), and nothing logs ACK missed when no one ever receives.

Separately, and not touched here: DialogServer waiting on Acks() in the non-2xx branch looks wrong, since only the 2xx ACK is ever passed up. Happy to open an issue if you want that changed.

ackSendAsync is reached only from actPassupAck, which only the Accepted
state has an edge to, so the sole ACK ever offered to Acks() is the one
to a 2xx. Nothing receives it: DialogServer reads Acks() on the non-2xx
branch, and that ACK goes to actConfirm, which does not pass up.

So the non-blocking send always failed, a goroutine was spawned to hold
the ACK, and at Timer L it logged "ACK missed" at WARN. A two hour soak
produced 8939 of them, one per answered call.

Buffering by one holds the ACK without the goroutine, and lets a
consumer that arrives after the transaction is done still read it. The
send can no longer block, so the default branch logs at Debug.

Also fixes the Acks() comment: the channel is created in NewServerTx,
not on demand.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@emiago

emiago commented Oct 11, 2026

Copy link
Copy Markdown
Owner

The chosen fix only moves the existing ACK missed log message from Warn to Debug. The ACK channel, delivery behavior, and transaction lifecycle remain unchanged. No larger architectural change is needed for this case, so closing this PR in favor of that minimal fix.

Committed locally as 6eba765: sip: lower unread ACK log to debug (#364).

@emiago emiago closed this Oct 11, 2026
emiago added a commit that referenced this pull request Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants