This is an archive of the discontinued LLVM Phabricator instance.

[flang] runtime: Read environment variables directly
ClosedPublic

Authored by rovka on Oct 14 2021, 2:45 AM.

Details

Summary

Add support for reading environment variables directly, via std::getenv.
This needs to allocate a C-style string to pass into std::getenv. If the
memory allocation for that fails, we terminate.

This also changes the interface for EnvVariableLength to receive the
source file and line so we can crash gracefully.

Note that we are now completely ignoring the envp pointer passed into
ProgramStart, since that could go stale if the environment is modified
during execution.

Diff Detail

Event Timeline

rovka created this revision.Oct 14 2021, 2:45 AM
rovka requested review of this revision.Oct 14 2021, 2:45 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 14 2021, 2:45 AM
klausler added inline comments.Oct 20 2021, 10:55 AM
flang/include/flang/Runtime/memory.h
39 ↗(On Diff #379640)

I'm not sure that this specialization is necessary. Does the code compile without it?

flang/runtime/environment.cpp
84

char can be used here instead of char] and would be more idiomatic.

This function might have use cases elsewhere; consider exposing it in tools.h or memory.h.

102

If GetEnvFromEnvp returns a null pointer, how do you know that it was due to a null envp pointer rather that an absent environment variable setting for the name? In the latter case, you should return a null pointer here as well, yes?

108

I think that it would be okay to crash when out of memory here. A null return from GetEnv() should signify only that the name was not found.

Another thing that you should consider: if the program adds or modifies its environment via the POSIX functions setenv(3) and unsetenv(3), your code may not notice the changes unless it uses std::getenv() exclusively -- the captured envp pointer may not reflect those changes and may not even still be valid.

rovka added a comment.Oct 22 2021, 4:06 AM

Another thing that you should consider: if the program adds or modifies its environment via the POSIX functions setenv(3) and unsetenv(3), your code may not notice the changes unless it uses std::getenv() exclusively -- the captured envp pointer may not reflect those changes and may not even still be valid.

Yeah, to be honest I'm a bit confused about the existence of envp in the first place. Why exactly are we storing it? I was thinking it would be kind of a "quick" path, so we could skip allocating a C-style string, but if there's a possibility for envp to become stale then maybe we shouldn't have it at all? Or is the idea that when we do have an envp, then the environment cannot be modified and envp has the final word?

flang/include/flang/Runtime/memory.h
39 ↗(On Diff #379640)

Nope. This is necessary for the [] operator, which I'm using to put the null at the end.

flang/runtime/environment.cpp
84

char can be used here instead of char] and would be more idiomatic.

But then we won't have operator[].

This function might have use cases elsewhere; consider exposing it in tools.h or memory.h.

Will do.

rovka updated this revision to Diff 381895.Oct 25 2021, 2:32 AM
rovka edited the summary of this revision. (Show Details)

Updated to crash if we fail to allocate the c-style string. Introducing the crash behavior made NullTerminatedString look pretty much the same as SaveDefaultCharacter, so I used that one instead and completely removed the former, along with the specialization of OwningPtr<char []>.

I haven't changed anything with regards to envp versus getenv. My thoughts are that if envp can become stale, we should remove it completely and use only getenv, but that should probably be a separate patch. What do you think?

Updated to crash if we fail to allocate the c-style string. Introducing the crash behavior made NullTerminatedString look pretty much the same as SaveDefaultCharacter, so I used that one instead and completely removed the former, along with the specialization of OwningPtr<char []>.

I haven't changed anything with regards to envp versus getenv. My thoughts are that if envp can become stale, we should remove it completely and use only getenv, but that should probably be a separate patch. What do you think?

I think ignoring envp is the right approach, and you might as well do it now.

flang/runtime/environment.cpp
84

char can be used here instead of char] and would be more idiomatic.

But then we won't have operator[].

Yes, it'll work. In C and C++, x[y] is defined to be *((x)+(y)) so you can offset a pointer like p[1] to get the following element.

rovka updated this revision to Diff 382266.Oct 26 2021, 4:42 AM
rovka edited the summary of this revision. (Show Details)
rovka marked an inline comment as not done.
rovka added inline comments.
flang/runtime/environment.cpp
84

Yes, on the pointer, but not on the OwningPtr. For that you'd have to call .get() first, which imo doesn't look as nice as using the [] operator directly (which is only possible for OwningPtr<A[]>).

klausler added inline comments.Oct 26 2021, 2:18 PM
flang/runtime/environment.cpp
84

Yes, on the pointer, but not on the OwningPtr. For that you'd have to call .get() first, which imo doesn't look as nice as using the [] operator directly (which is only possible for OwningPtr<A[]>).

If you insist on using [] and can't get yourself to call get(), then feel free to define operator= in OwningPtr<>.

rovka added inline comments.Oct 26 2021, 11:17 PM
flang/runtime/environment.cpp
84

It doesn't actually matter anymore, I removed NullTerminatedString and all other changes to memory.h.

klausler added inline comments.Oct 27 2021, 8:57 AM
flang/runtime/environment.cpp
75

Please use RUNTIME_CHECK instead of assert, here and below.

rovka updated this revision to Diff 382693.Oct 27 2021, 9:15 AM

Replaced assert with RUNTIME_CHECK.

klausler accepted this revision.Oct 27 2021, 9:16 AM
This revision is now accepted and ready to land.Oct 27 2021, 9:16 AM
This revision was automatically updated to reflect the committed changes.