Skip to content

dns: support AbortSignal in dns.lookup() and dns.promises.lookup()#62528

Draft
orgads wants to merge 1 commit intonodejs:mainfrom
orgads:dns-lookup-abort-signal
Draft

dns: support AbortSignal in dns.lookup() and dns.promises.lookup()#62528
orgads wants to merge 1 commit intonodejs:mainfrom
orgads:dns-lookup-abort-signal

Conversation

@orgads
Copy link
Copy Markdown
Contributor

@orgads orgads commented Mar 31, 2026

Add a signal option to both dns.lookup() and dns.promises.lookup() that accepts an AbortSignal, allowing callers to cancel pending lookups.

When getaddrinfo blocks a libuv thread for an extended period (e.g. ~10s on EAI_AGAIN), new lookups queue behind the blocked threads and the number of unresolved promises grows without bound. Each pending promise holds references to the calling closure, preventing GC and causing a memory leak in long-running servers under sustained DNS failure.

With this change, callers can abort stale lookups:

  const ac = new AbortController();
  setTimeout(() => ac.abort(), 5000);
  await dns.promises.lookup(host, { signal: ac.signal });

If the signal is already aborted, the call rejects/calls back immediately without dispatching to libuv. If aborted while pending, the promise is rejected (or callback called) with an AbortError and the late oncomplete from libuv is silently ignored.

Fixes: #62503

@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/net

@nodejs-github-bot nodejs-github-bot added dns Issues and PRs related to the dns subsystem. needs-ci PRs that need a full CI run. labels Mar 31, 2026
Add a `signal` option to both `dns.lookup()` and `dns.promises.lookup()`
that accepts an AbortSignal, allowing callers to cancel pending lookups.

When `getaddrinfo` blocks a libuv thread for an extended period (e.g. ~10s
on EAI_AGAIN), new lookups queue behind the blocked threads and the number
of unresolved promises grows without bound. Each pending promise holds
references to the calling closure, preventing GC and causing a memory leak
in long-running servers under sustained DNS failure.

With this change, callers can abort stale lookups:

  const ac = new AbortController();
  setTimeout(() => ac.abort(), 5000);
  await dns.promises.lookup(host, { signal: ac.signal });

If the signal is already aborted, the call rejects/calls back immediately
without dispatching to libuv. If aborted while pending, the promise is
rejected (or callback called) with an AbortError and the late oncomplete
from libuv is silently ignored.

Fixes: nodejs#62503
PR-URL: nodejs#62528
@orgads orgads force-pushed the dns-lookup-abort-signal branch from 197608e to 67e8f47 Compare March 31, 2026 20:23
@orgads orgads marked this pull request as draft March 31, 2026 20:28
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 31, 2026

Codecov Report

❌ Patch coverage is 97.53086% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.71%. Comparing base (1ccae7c) to head (67e8f47).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
lib/dns.js 96.96% 1 Missing ⚠️
lib/internal/dns/promises.js 97.91% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #62528      +/-   ##
==========================================
- Coverage   89.72%   89.71%   -0.01%     
==========================================
  Files         695      695              
  Lines      214106   214175      +69     
  Branches    41002    41020      +18     
==========================================
+ Hits       192096   192157      +61     
+ Misses      14077    14070       -7     
- Partials     7933     7948      +15     
Files with missing lines Coverage Δ
lib/dns.js 98.50% <96.96%> (-0.14%) ⬇️
lib/internal/dns/promises.js 98.20% <97.91%> (-0.09%) ⬇️

... and 47 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dns Issues and PRs related to the dns subsystem. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dns.lookup: pending promises grow unboundedly under sustained EAI_AGAIN load

2 participants