Skip to content

Fix ANCM server process dispatch lifetime - #69349

Draft
javiercn wants to merge 1 commit into
mainfrom
javiercn/iis-getprocess-ownership
Draft

javiercn wants to merge 1 commit into
mainfrom
javiercn/iis-getprocess-ownership

Conversation

@javiercn

Copy link
Copy Markdown
Member

Summary

  • take a caller-owned SERVER_PROCESS reference on every successful PROCESS_MANAGER::GetProcess path while the process-manager lock still protects the selected slot
  • release that reference with RAII after synchronous WinHTTP request setup completes
  • remove the unlocked process-list read after a shared-lock miss and re-evaluate the slot only under the exclusive lock

Related to #68366.

Rationale

GetProcess currently returns a borrowed pointer after dropping the process-manager lock. If the backend exits before ExecuteRequestHandler finishes reading the process object, the process-exit callback can remove the list reference, release the wait reference, and delete both SERVER_PROCESS and its FORWARDER_CONNECTION while request dispatch is still using them.

The forwarding handler does not retain the raw SERVER_PROCESS* across asynchronous completion, so this proposal deliberately holds the new reference only through the synchronous setup and initial WinHttpSendRequest call. It does not keep a dead backend or its parent WinHTTP connection alive for the full HTTP/WebSocket lifetime.

The existing fast-path miss also inspects the process-list slot without a lock before deciding to acquire the exclusive lock. This proposal acquires the exclusive lock unconditionally after a fast-path miss and performs the second readiness check there.

Compatibility

This changes only private implementation inside aspnetcorev2_outofprocess.dll; the module exports only CreateApplication, so there is no native ABI or public API change. The shim/handler contract and handler version-selection behavior are unchanged.

The acquisition and release ship together in the same request-handler DLL. Older pinned handlers remain unchanged; supported shim/handler combinations do not mix the internal GetProcess implementation with a caller from another binary.

Validation

Passed:

  • x64 Debug native build of OutOfProcessRequestHandler.vcxproj
  • x64 Release native build of OutOfProcessRequestHandler.vcxproj
  • x64 Debug native build with RunCodeAnalysis=true

The repository does not currently expose a deterministic test seam between GetProcess releasing its lock and the forwarding handler's first process access. Before this is considered ready to merge or service, it should gain a barrier-based red/green stress test that:

  1. pauses dispatch after acquiring the returned reference;
  2. terminates the selected backend and lets the process-exit callback remove its list/wait references;
  3. verifies the process object remains alive until dispatch releases its reference;
  4. repeats under Application Verifier/page heap while requests race repeated backend exits and restarts.

The adjacent parent-launcher/child-listener wait-reference imbalance identified during investigation is intentionally excluded from this focused proposal.

Fixes: #68366

@github-actions github-actions Bot added the area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions label Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IIS OutOfProcess ANCM: GetProcess() hands out SERVER_PROCESS* without a caller-owned reference

1 participant