Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows: Dynamically loaded functions may not be loaded before user pre-main initializers #97814

Closed
ChrisDenton opened this issue Jun 7, 2022 · 3 comments
Labels
O-windows Operating system: Windows T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@ChrisDenton
Copy link
Member

first reported at estk/log4rs#263 and mmastrac/rust-ctor#219

The Problem

On Windows, code can run functions before main by using special link sections. Placing function pointers in .CRT$XCU allows the runtime to find and call the functions before it calls main(). More info.

User code can take advantage of this to do pre-main initializations. However, the standard library also uses this mechanism to dynamically load some essential functions on startup. This can be a problem because there is no guaranteed order to functions placed in .CRT$XCU. So initializers in the std may be run before, after or in between those created by user code. If a user's initializer happens to be run before the initializer that loads an essential function, it will act as though that function failed to load. This can cause errors or a panic.

Possible solutions

  • Load delayed imports using C initializers instead of C++ initializers. These C initializers will be run first.
  • Use the .CRT$XCT section as this will ensure functions run before those in the .CRT$XCU section. However, "the names .CRT$XCT and .CRT$XCV aren't used by either the compiler or the CRT library right now, but there's no guarantee that they'll remain unused in the future". Source. I'm not sure it would matter if they were used for something as we don't rely on any features of the C or C++ runtimes when dynamically loading functions.
@ChrisDenton ChrisDenton added O-windows Operating system: Windows T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jun 7, 2022
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Jun 17, 2022
Windows: No panic if function not (yet) available

In some situations (e.g. rust-lang#97814) it is possible for required functions to be called before they've had a chance to be loaded. Therefore, we make it possible to recover from this situation simply by looking at error codes.

`@rustbot` label +O-windows
@CodesInChaos
Copy link

Doesn't such user code violate the "no life before main" principle and is thus unsupported?

@thomcc
Copy link
Member

thomcc commented Jul 19, 2022

I think it's not really supported, but a problem here is that it's not equally unsupported on all targets -- It's easy for someone to write code that works fine before main on non-windows, but is broken on windows because of this. That seems unfortunate for portability (portability of naively written code, admittedly), if nothing else.

@ChrisDenton
Copy link
Member Author

This has now been implemented. The init function is now placed in $XCT which will run before user code in $XCU. There is also appropriate documentation to explain this.

Furthermore, most functions are now loaded lazily instead of pre-main, only WaitOnAddress and WakeByAddress remain. Once we have a target that has Windows 8 as its minimum requirement then we could turn these into normal imports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-windows Operating system: Windows T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants