]> git.ipfire.org Git - thirdparty/bind9.git/commit
Prevent garbage-collecting ignored TCP connections
authorMichał Kępień <michal@isc.org>
Sun, 21 Dec 2025 05:25:56 +0000 (06:25 +0100)
committerMichał Kępień (GitLab job 6657129) <michal@isc.org>
Sun, 21 Dec 2025 06:49:13 +0000 (06:49 +0000)
commit5ec598aec71a50f8264688d65e2cf99f0b4fdfed
treeb82650a05706f56848a75c93dc8a1cfe16ffb266
parentf2b8863691d9c28cb08efcb4dadceb3d09fc1efb
Prevent garbage-collecting ignored TCP connections

Due to the way various asyncio-related objects (tasks, streams,
transports, selectors) are referencing each other, pausing reads for a
TCP transport (which in practice means removing the client socket from
the set of descriptors monitored by a selector) can cause the client
task (AsyncDnsServer._handle_tcp()) to be prematurely garbage-collected,
causing asyncio code to raise a "Task was destroyed but it is pending!"
exception.  Who knew that solutions as elegant as the one introduced by
e4078885073a6c5b59729f4313108e3e7637efdb could cause unexpected trouble?

Fix by making a horrible hack even more horrible, specifically by
keeping a reference to each incoming TCP connection to protect its
related asyncio objects from getting garbage-collected.  This prevents
AsyncDnsServer from closing any of the ignored TCP connections
indefinitely, which is obviously a pretty brain-dead idea for a
production-grade DNS server, but AsyncDnsServer was never meant to be
one and this hack reliably solves the problem at hand.

Only apply this change for the IgnoreAllConnections handler as the
ConnectionReset handler triggers a connection reset immediately after
pausing reads for an incoming TCP connection.

As pointed out in e4078885073a6c5b59729f4313108e3e7637efdb, the proper
solution would require implementing a custom asyncio transport from
scratch and that is still deemed to be too much work for the purpose at
hand.  Let's see how much longer we can limp along with the existing
approach.

(cherry picked from commit 1acde358ea13b4a07ba3a3df8a625cb15646217c)
bin/tests/system/isctest/asyncserver.py