[Bug 60316] New: WinHTTP unload leaves an auto-proxy NotifyAddrChange request targeting unloaded module storage
http://bugs.winehq.org/show_bug.cgi?id=60316 Bug ID: 60316 Summary: WinHTTP unload leaves an auto-proxy NotifyAddrChange request targeting unloaded module storage Product: Wine Version: 11.17 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: winhttp Assignee: wine-bugs@list.winehq.org Reporter: steve.kontakt@outlook.de Target Milestone: --- Distribution: --- Created attachment 82075 --> http://bugs.winehq.org/attachment.cgi?id=82075 Experimental WinHTTP auto-proxy watcher rundown rule (unified diff; not signed off or merge-ready) WinHttpDetectAutoProxyConfigUrl() arms a process-static asynchronous NotifyAddrChange() request used to invalidate the auto-proxy cache. An explicit WinHTTP unload can return while that request is still outstanding. A later IPv4 address change can then complete into storage which belonged to the unloaded WinHTTP module. This is reproducible on Wine 11.0 and on Wine master commit 490f6d5dcbb2a5047345b8af88d114bbcaad69a8 (reported by that build as Wine 11.17), in both x86 and x64. Steam is not required for the reproducer. Reproduction contract --------------------- 1. Dynamically load WinHTTP. 2. Call WinHttpDetectAutoProxyConfigUrl() to arm the auto-proxy cache watcher. 3. Explicitly unload WinHTTP and confirm that the module is absent. 4. Reserve the former module image range as PAGE_NOACCESS. 5. Publish a TRIGGER_READY marker. 6. Only then add a unique IPv4 address to the isolated container loopback interface. 7. Require the test process to survive and publish POST_TRIGGER_SURVIVED. Isolated Wine A/B evidence -------------------------- Both variants used the same Wine server containing the independently isolated terminal-completion correction described in Bug 60315. Only WinHTTP differed between the variants: https://bugs.winehq.org/show_bug.cgi?id=60315 Variant x86 x64 Total Corrected server + stock WinHTTP failed round 1 failed round 1 incomplete Corrected server + experimental WinHTTP rundown 8/8 8/8 16/16 The stock-WinHTTP process ended abruptly after confirmed module unload, former-range protection, and the post-unload address-change trigger. It never published POST_TRIGGER_SURVIVED. The experimental downstream rule gave the static request a private event, explicitly canceled it during WinHTTP teardown, and waited until its caller-visible status became non-pending before releasing the event and module storage. The required behavioral invariant is that WinHTTP must cancel and fully drain its process-static auto-proxy address-change request before unloading the storage containing its OVERLAPPED state. The exact upstream implementation is deliberately left to a Wine developer. Prototype scope and open engineering questions ---------------------------------------------- The experimental diff demonstrates that invariant by waiting with GetOverlappedResult(..., TRUE) during explicit DLL_PROCESS_DETACH (lpv == NULL). It is not claimed as a final loader-lock-safe upstream design. Whether rundown should instead belong to an existing queue object and complete before DllMain teardown remains an explicit reviewer question. The decisive A/B reproducer uses one auto-proxy caller at a time. It does not exercise WinHttpDetectAutoProxyConfigUrl() racing with explicit WinHTTP unload, so concurrent teardown is not claimed as covered. A final upstream implementation needs suitable serialization and a dedicated concurrent regression test. Both questions are listed in the attached independent implementation brief. Real application impact ----------------------- This defect was discovered while reducing a SteamCMD self-update hang. On the same pinned master build, a fresh SteamCMD bootstrap timed out after 244 seconds with stock Wine. The otherwise identical build containing both experimental lifecycle rules completed both self-update handoffs and teardown in 12 seconds. The patched Wine 11.0 product candidate also completed a fresh PufferPanel ARK server installation, launch, Steam initialization, and clean shutdown. A separate server-side defect in terminal APC completion delivery is reported as Bug 60315. Both defects were reproduced independently, but both lifecycle corrections were required for the complete SteamCMD hang: https://bugs.winehq.org/show_bug.cgi?id=60315 Related reports checked ----------------------- Bug 45116 concerns the historical absence of a working NotifyAddrChange() implementation. It does not report a WinHTTP-owned asynchronous request surviving module teardown: https://bugs.winehq.org/show_bug.cgi?id=45116 Bug 48592 mentions SteamCMD and the historical NotifyAddrChange stub, but its diagnosed failure was the Linux virtual-memory mapping limit: https://bugs.winehq.org/show_bug.cgi?id=48592 Bug 37962 concerns ws2_32 being unloaded while an asynchronous DNS callback remains pending, resulting in a crash. It is related module-lifetime precedent, but does not cover WinHTTP's process-static auto-proxy watcher, its rundown, or the measured post-unload completion path reported here: https://bugs.winehq.org/show_bug.cgi?id=37962 Bug 60245 concerns threadpool worker retirement while ordinary overlapped I/O remains pending. It addresses worker retention and ThreadIsIoPending, not teardown of a WinHTTP-owned process-static network-change request: https://bugs.winehq.org/show_bug.cgi?id=60245 A direct Wine Bugzilla search, including closed reports, found no exact duplicate for the measured post-unload completion failure. Test controls ------------- - x86 and x64 were tested. - Wine 11.0 and pinned Wine master were tested. - Fresh prefixes and isolated containers were used. - The trigger occurred only after confirmed WinHTTP unload and an explicit TRIGGER_READY state. - The decisive runtime section used no ptrace, strace, inotify, diagnostic logging, process polling, or fixed sleep as a repair. - The common Wine server and all non-WinHTTP runtime files were identity- checked between variants. Provenance and request ---------------------- This investigation, its diagnostic programs, and the experimental downstream patch were developed through substantial collaboration between me and OpenAI Codex. I directed the investigation, ran the tests, challenged hypotheses, and checked the resulting behavior. Codex materially assisted with source analysis, test construction, and construction of the experimental patch. The exact experimental unified diff is attached for technical inspection. It is not presented as a signed-off or merge-ready Wine contribution, and it has no Signed-off-by line. A Wine developer is invited to review it and decide whether to adapt it, reimplement the rule independently, or take another approach. To the best of my knowledge, no external implementation was copied; the work was based on public Wine source and the measured behavior described here. The diff contains only the implementation changes. Its added TRACE and WARN strings describe runtime operations and errors using Wine's existing debug conventions; they contain no provenance statements. Provenance is disclosed here in the accompanying text. The complete raw A/B output, exact source identities, and a prose description of the required lifecycle invariant are available as attachments. No Microsoft binaries were disassembled and no Microsoft source code was examined during this investigation. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=60316 --- Comment #1 from Steve <steve.kontakt@outlook.de> --- Created attachment 82076 --> http://bugs.winehq.org/attachment.cgi?id=82076 Technical evidence summary -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=60316 --- Comment #2 from Steve <steve.kontakt@outlook.de> --- Created attachment 82077 --> http://bugs.winehq.org/attachment.cgi?id=82077 Implementation-independent lifecycle requirements -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=60316 --- Comment #3 from Steve <steve.kontakt@outlook.de> --- Created attachment 82078 --> http://bugs.winehq.org/attachment.cgi?id=82078 Decisive Wine master stock-vs-patched WinHTTP unload A/B raw output -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=60316 --- Comment #4 from Steve <steve.kontakt@outlook.de> --- Created attachment 82079 --> http://bugs.winehq.org/attachment.cgi?id=82079 Wine master SteamCMD lifecycle A/B raw output -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=60316 Zeb Figura <z.figura12@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |z.figura12@gmail.com --- Comment #5 from Zeb Figura <z.figura12@gmail.com> --- Please don't use AI to file bug reports; it usually gets things wrong and makes the report way too verbose and hard to read. This one is valid but really didn't need to be more than a single sentence. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
participants (1)
-
WineHQ Bugzilla