Runtime environment variable changes ignored on Windows
Confirm by changing [ ] to [x] below to ensure that it's a bug:
- [x] I've gone though Developer Guide and API reference
- [x] I've searched for previous similar issues and didn't find any solution
Describe the bug
It seems that, under Windows, runtime changes (inside the running process) to environment variables (such as AWS_DEFAULT_REGION, AWS_EC2_METADATA_DISABLED, etc.) are ignored.
I suspect the reason is that the SDK uses the CRT's _dupenv_s function in its implementation of Aws::Environment::GetEnv. The CRT uses its own copy of the environment that is made at process startup. Any further changes to environment variables are not seen.
The fix is to use the Windows API GetEnvironmentVariable.
You can see a similar issue here: https://github.com/AcademySoftwareFoundation/OpenColorIO/issues/756
SDK version number 1.8.54.
Platform/OS/Hardware/Device Windows.
Hi @pitrou , ok so I've been trying to test this and for me it works, but it is kind of confusing how it actually happens so here let me show you how I tested it and so if I missed out something let me know.
#include <windows.h>
#include <aws/core/Aws.h>
#include <aws/core/platform/Environment.h>
#include <aws/s3/S3Client.h>
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
Aws::SDKOptions options;
//test with the windows api getenviroment
const char * getEnv(Aws::String varName){
const DWORD buffSize = 65535;
static char buffer[buffSize];
if (GetEnvironmentVariableA(varName.c_str(), buffer, buffSize))
{
return buffer;
}
else
{
return 0;
}
}
//set enviroment variable pragmatically
int setenv(const char *name, const char *value, int overwrite)
{
int errcode = 0;
if(!overwrite) {
size_t envsize = 0;
errcode = getenv_s(&envsize, NULL, 0, name);
if(errcode || envsize) return errcode;
}
return _putenv_s(name, value);
}
int main()
{
//get enviroment variable before any changes.
std::cout << getEnv("AWS_DEFAULT_REGION") <<std::endl;
options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace;
Aws::InitAPI(options);
{
//overwrite env variables
setenv("AWS_DEFAULT_REGION","fake-region-1",1);
setenv("AWS_EC2_METADATA_DISABLED","false",1);
Aws::Client::ClientConfiguration clientConfig;
std::cout<<clientConfig.region << std::endl; // here it prints the changed enviroment variable
std::cout << getEnv("AWS_DEFAULT_REGION") <<std::endl; // same result with the windows api call
}
Aws::ShutdownAPI(options);
}
Did I misunderstand something? I see no difference with the windows api or the sdk's getenviroment.
Your setenv function is using _putenv_s, so it modifies the CRT's copy of the environment.
In our use case, we're using the Windows API SetEnvironmentVariable.
Here is another similar issue reported to another project: https://github.com/ocaml/ocaml/pull/1479
And here is a relevant excerpt (though not very clear) from the Microsoft docs: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getenv-wgetenv?view=vs-2019
getenvand_putenvuse the copy of the environment pointed to by the global variable_environto access the environment.getenvoperates only on the data structures accessible to the run-time library and not on the environment "segment" created for the process by the operating system.
@pitrou are you still seeing this bug with environment variables?
Greetings! It looks like this issue hasn’t been active in longer than a week. We encourage you to check if this is still an issue in the latest release. Because it has been longer than a week since the last update on this, and in the absence of more information, we will be closing this issue soon. If you find that this is still a problem, please feel free to provide a comment or add an upvote to prevent automatic closure, or if the issue is already closed, please feel free to open a new one.