On Tue, 29 Sep 2026 03:44:27 GMT, Dean Long <[email protected]> wrote:
> But since these pages would still be PAGE_NOACCESS, when we resume and > reexecute the trapped instruction, shouldn't we get a > EXCEPTION_ACCESS_VIOLATION as desired? Unfortunately, although this expectation is perfectly reasonable, Windows doesn't seem to behave this way. I wrote a couple of standalone C programs to validate this (and additional exploration continues). The first program doesn't call `SetThreadStackGuarantee()` and it creates the following layout: Page 5: reserved (i.e. not committed) Page 4: reserved (i.e. not committed) Page 3: PAGE_NOACCESS, committed (mimics yellow page) Page 2: PAGE_NOACCESS, committed (mimics yellow page) Page 1: PAGE_NOACCESS, committed (mimics yellow page) Page 0: PAGE_NOACCESS, committed (mimics red page) After accessing pages from the current stack page (return value of `_alloca(1)` aligned to page boundary) one page at a time, the first exception that is delivered is `EXCEPTION_STACK_OVERFLOW` for access to page 3. What's even more interesting (and my apologies if this adds to our list of problems) is that when I probe the page status upon receiving `EXCEPTION_STACK_OVERFLOW`, I see the following: Page 5: PAGE_READWRITE, committed Page 4: PAGE_READWRITE, committed Page 3: PAGE_READWRITE, committed (page whose access raised the stack overflow exception) So Windows seems to open up the pages that we had marked `PAGE_NOACCESS`. This isn't _really_ a problem because the `handle_recoverable_stack_overflow()` function (in this patch) calls `overflow_state->disable_stack_yellow_reserved_zone()`, which opens up the yellow pages anyway. Now, if there were more than one red pages, we might run into problems since some of the red pages would be made writeable. Yet another reason to avoid `EXCEPTION_STACK_OVERFLOW`, like David suggested. In any case, Windows raises the stack overflow exception for access to page 3. If I continue probing more pages, the next exception (`EXCEPTION_ACCESS_VIOLATION`) is at page 0 because the `PAGE_NOACCESS` attribute was retained. In the second program, I call `SetThreadStackGuarantee()` with different sizes like 1, 4096, 8192, 12288, and 16384 and for each case, I query the size to see what it set it to. On my machine, I see: requested=1 current=8192 requested=4096 current=8192 requested=8192 current=8192 requested=12288 current=12288 requested=16384 current=16384 So it looks like no matter what, there are at least two pages that become the guarantee. This is generally fine, since the minimum red page count + minimum yellow page count exceeds two, but it does mean that we can't set just one page as the stack guarantee. I am consulting some folks who work on Windows and inspecting some source code to better understand the conditions behind the delivery of these exceptions. I'll report back soon, but I appreciate y'all patience. This is indeed convoluted, but I think I have a much better understanding now, and I hope you do as well. ------------- PR Comment: https://git.openjdk.org/jdk/pull/32365#issuecomment-5885482325
