[PATCH] D14231: [Support] Use GetTempDir to get the temporary dir path on Windows.

Aaron Ballman via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 5 09:50:00 PST 2015


aaron.ballman added inline comments.

================
Comment at: unittests/Support/Path.cpp:366
@@ +365,3 @@
+
+  _wputenv_s(L"TMP", L"C:\\OtherFolder");
+  path::system_temp_directory(true, TempDir);
----------------
chfast wrote:
> aaron.ballman wrote:
> > chfast wrote:
> > > aaron.ballman wrote:
> > > > I am slightly worried about this for systems that don't mount a C drive, but I suspect those are passingly rare. ;-)
> > > > 
> > > > What has me way more worried is that failing these tests will not restore the TMP (and TEMP, below) environment variables. So if any of these tests fail, we leave the user's machine in a broken state. This can be solved with some RAII wrappers.
> > > > 
> > > > Further, changing the temp directory out from under the user affects *every* application on their machine. This means there's a non-zero chance that temp files start going to incorrect locations for other applications. I don't think there's a way to solve this, and I'm really not comfortable with that because it can lead to hard-to-trace problems for developers. Ideas most certainly welcome.
> > > https://msdn.microsoft.com/en-us/library/83zh4e6k.aspx
> > > > _putenv and _wputenv affect only the environment that is local to the current process; you cannot use them to modify the command-level environment
> > > 
> > > So, changing env vars can affect unit tests running in other threads. RAII for restoring original values is worth considering.
> > That is awesome, and also something I totally did not know. Thank you for pointing that out!
> > 
> > However, a simple test shows there's still a problem -- we have ExecuteAndWait (and other functions) that create subprocesses (possibly in parallel to these tests), almost all of which pass nullptr as the environment variable. When CreateProcess is eventually called with no environment, it inherits the changes made by _wputenv_s(). So this has the possibility to change the environment out from under our own tests, and those tests may in turn try to create temporary files in the wrong place. :-(
> > 
> > My very simple test code was:
> > ```
> > #include <iostream>
> > #include <Windows.h>
> > 
> > void f(const wchar_t *M) {
> >   wchar_t B[MAX_PATH + 2];
> >   ::GetTempPathW(MAX_PATH + 2, B);
> >   std::wcout << M << B << std::endl;
> > }
> > 
> > int main(int argc, const char *argv[]) {
> >   if (argc == 1) {
> >     f(L"Original: ");
> >     _wputenv_s(L"TMP", L"C:\\OtherFolder");
> >     STARTUPINFOA si = { 0 };
> >     si.cb = sizeof(si);
> >     PROCESS_INFORMATION pi = { 0 };
> >     ::CreateProcessA(argv[0], "test test test", nullptr, nullptr, TRUE,
> >                      CREATE_UNICODE_ENVIRONMENT, nullptr, nullptr, &si, &pi);
> >   } else {
> >     f(L"Subprocess: ");
> >   }
> > }
> > ```
> > While this is hopefully not really an issue in reality, I still worry about giving ourselves head-scratching debugging problems that are nondeterministic, as well as cluttering up someone's hard drive with temp files in the wrong locations.
> > 
> > Do these tests currently run serially with regards to other tests (even from lit)? If so, then I think it's a risk we should document (probably around these new tests as well as Execute() in Program.inc for Win32) and just move on despite my discomfort. This seems about as good as we're going to be able to get for testing. If we run in parallel, then I'm a bit more worried.
> I have an idea how to better solve the env modification issue. If the process can only modify env of itself and its child processes, we should run this test in a separated process.
> 
> I've just checked that GTest supports something called Death Tests, that spans a new process to run the test. It is not ideal as combining parallel testing with Death Tests has some issues, but at least GTest will try to inform about such case if detected.
> https://code.google.com/p/googletest/wiki/AdvancedGuide#Death_Tests
That sounds like a great approach to me!

================
Comment at: unittests/Support/Path.cpp:386
@@ +385,3 @@
+  _putenv_s("TMP", Expected.c_str());
+  path::system_temp_directory(true, TempDir);
+  EXPECT_EQ(Expected, TempDir);
----------------
chfast wrote:
> aaron.ballman wrote:
> > chfast wrote:
> > > Here is the test that checks system_temp_directory() in case $TMP is 260 chars long.
> > Does this test pass on Windows 7 (if possible, with no service packs installed)?
> I'm not 100% sure, but I think I tested that on Windows 8. However, I have Windows 7 at home so I will test that there to be sure.
> 
> If I get https://msdn.microsoft.com/pl-pl/library/windows/desktop/aa383745(v=vs.85).aspx right, there was no API change from Windows 7 to Windows 7 SP1.
If you only have access to SP1, I'm not too worried. I only ask about the base version in case there were changes to the API behavior introduced in a service pack or KB update. If SP1 works, I'm totally fine saying we support Windows 7 with the latest service packs installed for this functionality.


Repository:
  rL LLVM

http://reviews.llvm.org/D14231





More information about the llvm-commits mailing list