[GH-ISSUE #2938] Windows: stack overflow while resolving a large site split-tunneling list #1342

Closed
opened 2026-10-13 20:40:35 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @romanio427 on GitHub (Aug 4, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/2938

This was generated by AI during triage.

Environment

  • Windows 11, build 26100.8655
  • AmneziaVPN 5.0.0.5
  • Xray connection using tun2socks
  • Site split tunneling enabled with a large site list

Problem

While connecting with a large site split-tunneling list, AmneziaVPN.exe exits with Windows exception 0xc00000fd (stack overflow) as hostnames are re-resolved.

Reproduction

  1. Enable site split tunneling with a large site list. In the observed incident, it produced more than 9,000 route entries.
  2. Connect an Xray configuration.
  3. Wait while the configured hostnames are resolved.
  4. Observe AmneziaVPN.exe terminate with 0xc00000fd.

Root cause

Each QHostInfo::lookupHost() completion enters the callback in VpnConnection::addSitesRoutes(). That callback synchronously waits for flushDns() through QRemoteObjectPendingCall::waitForFinished().

The synchronous wait processes a nested Qt event loop, which can dispatch the next queued hostname callback before the current callback returns. The observed crash dump contained this logical cycle approximately 66 times:

addSitesRoutes QHostInfo callback
  -> flushDns
  -> QRemoteObjectPendingCall::waitForFinished
  -> nested QEventLoop::exec
  -> next QHostInfo callback

The original dump is no longer available, so this is a transcription of the inspected call pattern rather than a raw debugger export.

Expected behavior

Resolving a large site list must not create nested synchronous event loops or exhaust the GUI thread stack. Resolved IPv4 routes should still be installed, and DNS should be flushed after resolution completes.

Proposed fix

PR #2930 removes the synchronous wait from the hostname callback, installs each resolved route as its lookup completes, and performs one asynchronous DNS flush after all lookups finish.

Acceptance criteria

  • Connecting with a large site list does not enter a nested waitForFinished() loop in addSitesRoutes().
  • Each newly resolved IPv4 address is still added to the selected route gateway.
  • DNS is flushed once asynchronously after all hostname lookups complete.
  • Failures from the asynchronous DNS flush are still logged.

Out of scope

Recovering or cleaning an orphaned VPN session after any unexpected GUI exit is tracked separately in #2931. This issue covers only the stack-overflow trigger fixed by #2930.

#2748 contains the same Windows exception code and reports a remaining interface with broken DNS after the GUI exits, but its primary AmneziaDNS/reinstallation problem is broader and is not claimed to be fixed here.

Originally created by @romanio427 on GitHub (Aug 4, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amnezia-client/issues/2938 > *This was generated by AI during triage.* ## Environment - Windows 11, build 26100.8655 - AmneziaVPN 5.0.0.5 - Xray connection using `tun2socks` - Site split tunneling enabled with a large site list ## Problem While connecting with a large site split-tunneling list, `AmneziaVPN.exe` exits with Windows exception `0xc00000fd` (stack overflow) as hostnames are re-resolved. ## Reproduction 1. Enable site split tunneling with a large site list. In the observed incident, it produced more than 9,000 route entries. 2. Connect an Xray configuration. 3. Wait while the configured hostnames are resolved. 4. Observe `AmneziaVPN.exe` terminate with `0xc00000fd`. ## Root cause Each `QHostInfo::lookupHost()` completion enters the callback in `VpnConnection::addSitesRoutes()`. That callback synchronously waits for `flushDns()` through `QRemoteObjectPendingCall::waitForFinished()`. The synchronous wait processes a nested Qt event loop, which can dispatch the next queued hostname callback before the current callback returns. The observed crash dump contained this logical cycle approximately 66 times: ```text addSitesRoutes QHostInfo callback -> flushDns -> QRemoteObjectPendingCall::waitForFinished -> nested QEventLoop::exec -> next QHostInfo callback ``` The original dump is no longer available, so this is a transcription of the inspected call pattern rather than a raw debugger export. ## Expected behavior Resolving a large site list must not create nested synchronous event loops or exhaust the GUI thread stack. Resolved IPv4 routes should still be installed, and DNS should be flushed after resolution completes. ## Proposed fix PR #2930 removes the synchronous wait from the hostname callback, installs each resolved route as its lookup completes, and performs one asynchronous DNS flush after all lookups finish. ## Acceptance criteria - Connecting with a large site list does not enter a nested `waitForFinished()` loop in `addSitesRoutes()`. - Each newly resolved IPv4 address is still added to the selected route gateway. - DNS is flushed once asynchronously after all hostname lookups complete. - Failures from the asynchronous DNS flush are still logged. ## Out of scope Recovering or cleaning an orphaned VPN session after any unexpected GUI exit is tracked separately in #2931. This issue covers only the stack-overflow trigger fixed by #2930. ## Related report #2748 contains the same Windows exception code and reports a remaining interface with broken DNS after the GUI exits, but its primary AmneziaDNS/reinstallation problem is broader and is not claimed to be fixed here.
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amnezia-client#1342
No description provided.