-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Description
The GODEBUG environment variable has grown to become the lynchpin of Go's approach to making subtle breaking changes, and at the time I'm writing these there are 50 possible such settings that each causes some part of the Go standard library to behave in a slightly different way than it would by default.
Being able to change these settings dynamically at runtime based on an environment variable is presumably useful for the case where an organization is building a Go program purely for their own internal use, such as running a service that others access over a network, since I imagine this provides some desirable operational flexibility for responding quickly to regressions in production without having to completely rebuild and redeploy.
However, runtime control of these divergent behaviors is less ideal for those building programs that are shipped to third parties to run on their own computers. In that case, the maintainers of the software tend to receive bug reports about behaviors they cannot directly observe and so must attempt to reproduce in a separate environment. The more potential variations in the runtime context, the harder it can be to successfully recreate a similar enough environment to reproduce a reported problem.
Having 50 different settings that can each subtly change the runtime behavior is therefore quite concerning. Even if each of those settings were only binary flags that are either on or off (which is not the case), that represents roughly a million billion possible variations in addition to all of the unavoidable variations of current operating system version, position in the network, etc, etc. Exactly what each of these settings actually does is also not immediately intuitive without studying the associated code carefully, which makes it hard to know that it's even worth trying to enable one to see if that varies the behavior.
For example, running software in an environment where GODEBUG=fips140=on is set can apparently cause subtle interop problems. Of course, I happen to have seen that issue and so now that's something I have on my radar when I'm thinking about how to reproduce a TLS-related bug report, but if I were not aware of it and someone reported that the software I maintain cannot connect to some specific server then it's less likely I would think to try reproducing that with different fips140 settings just to see if that makes it more or less reproducible.
Proposal
I'd love to have an opt-in way to specify that a particular Go program should have a fixed set of "godebug" settings decided entirely at compile time, with no support for overriding them on program startup using an environment variable.
I'm not particularly set on any specific way to represent that, but one possibility would be to add a special new permanent godebug setting that effectively disables the runtime handling of godebug settings, and so can be specified only in the godebug directive in the go.mod of the application's main module:
godebug (
runtimegodebug=off
)If any other settings are included in the godebug directive then those would still be compiled into the program, so that the application developer (rather than the end-user) can still use this to disable any behavior changes that the application has not yet been updated to handle.
In the implementation details, I think that what I'm asking for is for the second parsegodebug call here to be skipped if the first one has caused runtimegodebug to be set to off:
Lines 430 to 434 in d50a571
| // apply compile-time GODEBUG settings | |
| parsegodebug(godebugDefault, nil) | |
| // apply environment settings | |
| parsegodebug(godebug, nil) |
...though of course exactly how this is implemented is not my main concern; I'm sharing this just in the hope it clarifies what behavior I'm hoping for.
My motivation here is focused on constraining the number of possible runtime behaviors that can vary outside of my program's control, and so it's not important to me for this to make the runtime handling of godebug settings any faster just because they were fixed at compile time, or for this to disable any of the various hooks the runtime has for if the GODEBUG environment variable is changed or unset by the program itself at runtime.
I just want to be able to run automated tests for a specific fixed configuration in our build environment and ensure that everyone using the resulting executables is running the same codepaths we tested against, and thus also the same codepaths I'd be running if I attempted to reproduce a problem using the same executables on my own system.