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

TSCBasic: avoid using C library functions for environment #452

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

compnerd
Copy link
Member

Prefer to use the Win32 APIs for environment management. Note that this is going to break any user of libc on Windows. Setting environment variables through this function will not be reflected in the C library only the Win32 APIs. Furthermore, we use the unicode variants always as the unicode and ANSI environment may diverge as not all unicode (UTF-16) is translatable to ANSI, which is documented at [1].

[1] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getenv-wgetenv?view=msvc-170&viewFallbackFrom=vs-2019.

@compnerd
Copy link
Member Author

@swift-ci please test

@compnerd compnerd enabled auto-merge (rebase) December 18, 2023 17:10
@neonichu
Copy link
Contributor

Would it be possible to keep the old code in addition to the new? Or will that cause interaction issues? Basically just wondering if we can avoid breaking possible assumptions of existing clients.

@compnerd
Copy link
Member Author

I don't know what the assumptions are around this, but this brings it inline with Foundation which uses the Win32 copy. I don't think that we could ever guarantee the synchronisation since a user can call either function themselves and we are then out of sync.

Copy link
Contributor

@MaxDesiatov MaxDesiatov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I understand correctly that one way to test this could be to modify env vars from Foundation and see if those changes are reflected when querying from ProcessEnv? If so, can such test be added to the test suite?

@compnerd
Copy link
Member Author

I mean, yes, I can add that but not run it. The TSC test suite is not windows friendly and doesn't run ever (not even locally like the driver or SPM).

@MaxDesiatov
Copy link
Contributor

I understand, but probably easier to add that test now in an anticipation of the test suite being enabled eventually, than to hope we'll remember to cover it later.

Windows is case insensitive for the environment control block, which we
did not honour. This causes issues when Swift is used with programs
which are incorrectly cased (e.g. emacs). Introduce an explicit wrapper
type for Windows to make the lookup case insensitive, canonicalising the
name to lowercase. This allows us to treat Path and PATH identically
(along with any other environment variable and case matching) which
respects the Windows behaviour. Additionally, migrate away from the
POSIX variants which do not handle the case properly to the Windows
version which does.

The introduced type `ProcessEnvironmentBlock` is just a typealias,
allowing access to the dictionary itself which is important to preserve
the behaviour for the clients.  The `CaseInsensitiveString` is a case
insensitive, case preserving string representation that allows us to
recreate the environment on Windows as the environment is case
insensitive, so it should not be possible to have conflicts when reading
the Process Environment Block from the Process Execution Block.

This is a partial resolution to environment variable handling as the
tools need subsequent changes to adopt the new API.

Fixes: swiftlang#446

Co-authored-by: Max Desiatov <[email protected]>
@compnerd
Copy link
Member Author

Ugh, okay, so this doesn't work as intended because Foundation actually is calling into CoreFoundation which is using getenv, which means that it separates out from actual Win32 applications 🤦‍♂️. Let me change the behaviour of ProcessEnv.vars to use GetEnvironmentStringsW.

Prefer to use the Win32 APIs for environment management.  Note that this
is going to break any user of libc on Windows.  Setting environment
variables through this function will not be reflected in the C library
only the Win32 APIs.  Furthermore, we use the unicode variants always as
the unicode and ANSI environment may diverge as not all unicode (UTF-16)
is translatable to ANSI, which is documented at [1].

[1] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getenv-wgetenv?view=msvc-170&viewFallbackFrom=vs-2019.
@compnerd
Copy link
Member Author

@MaxDesiatov added a test, but to do this properly, we now need to do the storage change first otherwise we will have to change this again with the that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants