Skip to content

Windows split stack complications? #3445

Closed
@brson

Description

@brson
Contributor

This reddit thread suggests that there are extra precautions necessary for split stacks on Windows.

http://www.reddit.com/r/programming/comments/zk05a/a_trip_down_the_gcc_split_stack_rabbithole/c65bezg

Activity

brson

brson commented on Sep 10, 2012

@brson
ContributorAuthor

Full text of reddit comment:

If anyone's thinking of doing this on Windows, please make sure you do it correctly:

Use CreateFiber() and SwitchToFiber() to create and swap in new stack segments. Do not attempt to allocate stack space yourself. This is the only supported way to update the stack bounds in the thread environment block (TEB).

Maintain the singly-linked Structured Exception Handling (SEH) chain pointed to by FS:[0]. This must always consist of singly linked nodes at ascending addresses within the current OS stack. If you are copying out stack blocks, you must either add handlers to bridge across the segments or appropriately link and unlink nodes in each segment. Debugging this problem in Stackless Python was not fun.

Failure to handle either case will lead to hard termination of the process on an exception due to corrupted stack state. I'm not sure if Go handles this in its version, but I didn't see FS: updating code....

metajack

metajack commented on May 16, 2013

@metajack
Contributor

Nominating for production ready.

graydon

graydon commented on May 16, 2013

@graydon
Contributor

accepted for production-ready milestone

vadimcn

vadimcn commented on Jun 21, 2013

@vadimcn
Contributor

Fibers are designed for cooperative multitasking, not for segmented stacks, and will likely create too much overhead to be useful for implementing the latter. Specifically:

  • Fiber stack sizes will be rounded up to the nearest page boundary, so super-small stacks become impossible.
  • SwitchToFiber swaps out the entire CPU context (just like a thread switch would), whereas for segmented stacks you actually need to only switch the stack and keep the rest. You'd probably have to update thread context saved in the other fiber before switching to it (which isn't supported via Win32 API, BTW). Not to mention that it would be orders of magnitude slower than the current morestack() implementation.
pnkfelix

pnkfelix commented on Aug 14, 2013

@pnkfelix
Member

visiting for bug triage, email 2013-08-05.

I don't have anything to add beyond what's written on the bug currently, though there certainly seem to be a lot of interesting nitty gritty details here.

graydon

graydon commented on Aug 15, 2013

@graydon
Contributor

Page boundaries may well be a requirement anyways. I believe they were in the last version of segmented stacks we had. Beyond that, the original poster seems to be trying to help us write non-crashy code when handling exception not fast code. If it's truly the only way to live through an SEH call, we'll have to do something like the recommended thing. Maybe not exactly it, but something that preserves the SEH chain.

klutzy

klutzy commented on Oct 11, 2013

@klutzy
Contributor

The comment says we must be aware of stack info at TEB (TIB) which is only officially available by using fiber functions.
However, the internal is well-known (wikipedia link) and the structure is defined at winnt.h (both mingw and msvc).
In the header, struct NT_TIB has two members named StackBase and StackLimit. They indicates the stack range (StackLimit~StackBase) and Windows internally uses them for page check.
Also msvcrt functions (e.g. puts or MessageBoxW) may buzz if ESP is below StackLimit (I got it on win64).

When I did mingw-w64 work (#8488), I added management code for them.
However we lack of TIB support on 32-bit Windows. I'm not totally sure why it even works well :-/ Maybe msvcrt does not use TIB for stack checking.

Factor and Go do similar to what I did. Factor developer left a blog post which is great source for this issue. Here is relevant Factor code I guess.
Go does somewhat tricky: they just sets StacLimit = 0; StackBase = 0xffffffffffff. (sys_windows_amd64.s, setstacklimits routine) This is simple but there may be some issues regarding ffi (e.g. what if Go routine calls C function then it exceeds the stack limit?)

alexcrichton

alexcrichton commented on Oct 29, 2013

@alexcrichton
Member

In today's meeting we have decided to jettison segmented stacks. Additionally, we are currently managing custom stack bounds in the TEB/TIB on win64 (as pointed out by @klutzy), so I believe that this is closed.

If this should stay open though, then feel free to reopen!

added a commit that references this issue on Jun 9, 2024

Auto merge of rust-lang#3650 - tiif:feat/eventfd, r=oli-obk

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-runtimeArea: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflowsE-hardCall for participation: Hard difficulty. Experience needed to fix: A lot.O-windowsOperating system: Windows

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @graydon@metajack@alexcrichton@brson@pnkfelix

        Issue actions

          Windows split stack complications? · Issue #3445 · rust-lang/rust