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

Windows: Move temp files to Temp directory. #184

Merged
merged 2 commits into from
Jan 9, 2023

Conversation

dawid-sabat
Copy link
Contributor

For Windows compilations of OpenDCDiag, temp files were created in directory where the .exe is placed. The application doesn't always have access rights to do that.

Changes here move all temp files to Windows designated area: C:\Users%username\AppData\Local\Temp

Signed-off-by: dawid-sabat dawid.sabat@intel.com

framework/sysdeps/windows/tmpfile.c Outdated Show resolved Hide resolved
@dawid-sabat
Copy link
Contributor Author

I noticed that this change breaks selftests in a way I don't completely understand. I suspect there might something wrong with wine configuration but I'm not sure.

not ok 1 Verify that the python yaml module can import regular output
# (from function `run_sandstone_yaml' in file bats/sanity-check/../testenv.bash, line 87,
#  in test file bats/sanity-check/[10](https://github.com/opendcdiag/opendcdiag/actions/runs/3657877805/jobs/6181966319#step:10:11)-yaml-validate.bats, line 9)
#   `run_sandstone_yaml --retest-on-failure=0 --selftest --timeout=60s --quick -e @positive' failed
# + wine builddir-windows-cross/opendcdiag.exe --on-crash=core --on-hang=kill -Y -o - --retest-on-failure=0 --selftest --timeout=60s --quick -e @positive
# internal error creating temporary file: File too large

Any ideas?

Copy link
Contributor

@thiagomacieira thiagomacieira left a comment

Choose a reason for hiding this comment

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

Hadn't seen this before I wrote #186

for (int i = 0; hFile == INVALID_HANDLE_VALUE && i < 16; ++i) {
wcscat(_ultow(next_random(), tmpname, 36), L".tmp"); // yes, base 36
DWORD access = GENERIC_READ | GENERIC_WRITE;
DWORD sharemode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
DWORD creation = CREATE_NEW;
DWORD flags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE;
hFile = CreateFileW(tmpname, access, sharemode, &sa, creation, flags, NULL);

if ((wcslen(tmppath) + wcslen(tmpname)) >= MAX_PATH)
Copy link
Contributor

Choose a reason for hiding this comment

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

That doesn't happen for all file names. The shortest file name we'll generate is "0.tmp" and the longest is "1z141z4.tmp". So there's a possibility that some paths will work.

Either way, either we handle GetTempPathW returning too long a string before the loop or we simply continue here. Or both.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should be done now

@dawid-sabat
Copy link
Contributor Author

@lukasz-tuz and I made some experiments about opendcdiag selftests failing:

  • tried to recreate the same conditions as CI (the compiller, libs etc) locally
  • from my end I noticed that selftests and opendcdiag.exe works with wine outside the docker container.
  • Lukasz has been debugging on his end and he's going to describe his effort.

@thiagomacieira
Copy link
Contributor

@lukasz-tuz and I made some experiments about opendcdiag selftests failing:

  • tried to recreate the same conditions as CI (the compiller, libs etc) locally
  • from my end I noticed that selftests and opendcdiag.exe works with wine outside the docker container.
  • Lukasz has been debugging on his end and he's going to describe his effort.

I recreated the conditions on Wine by simply doing a cd / before launching it. For the BATS testing, we need to check that the output log file (if not stdout) has a full path). We should do that for Unix too.

@lukasz-tuz
Copy link
Contributor

Lack of full path to output log file is only part of this (albeit needs to be fixed). However:

  • default Wine prefix doesn't seem to have %TEMP% or %TMP% variables; they need to be added manually, and need to be added to the registry file in the Wine prefix being used. Passing them as shell environment variables is not sufficient (see Wine User Guide).
  • Need to ensure that directory pointed to by %TEMP% has write permissions set
  • even with the steps above completed, opendcdiag.exe would still fail when trying to truncate the temp file with ftruncate. As @dawid-sabat observed, this does not happen with more up-to-date version of Wine (I used 7.22 in my tests). Older version (7.2) fails with EFBIG error, although length passed to ftruncate is just 65 kB.

Going to run a targeted test, where previously failing environment gets a Wine update (and just Wine, to rule out any other dependencies).

@thiagomacieira
Copy link
Contributor

I don't know where the environment came from in my ~/.wine/user.reg, but it does show:

[Environment] 1632151948
#time=1d7ae34b87983e8
"PATH"="C:\\windows\\system32;C:\\windows;C:\\windows\\system32\\wbem;C:\\windows\\system32\\WindowsPowershell\\v1.0;C:\\MinGW\\bin;C:\\Qt\\qtbase\\bin"
"QT_FORCE_STDERR_LOGGING"="1"
"TEMP"="C:\\users\\tjmaciei\\Temp"
"TMP"="C:\\users\\tjmaciei\\Temp"

I don't remember setting them and I probably wouldn't have set them to the path that is shown there (I'd choose "Z:\tmp"), but the other two variables are definitely me.

Another thing is that tracing its execution shows just how Wine executes GetTempPathW:

1515859.354:00dc:00e0:Call KERNEL32.GetTempPathW(000000f9,0081e6a0) ret=140020632
1515859.354:00dc:00e0:trace:process:GetEnvironmentVariableW (L"TMP" 000000000081E350 260)
1515859.354:00dc:00e0:Call ntdll.RtlInitUnicodeString(0081e2d0,7b08bd14 L"TMP") ret=7b05c2d7
1515859.354:00dc:00e0:Ret  ntdll.RtlInitUnicodeString() retval=00000008 ret=7b05c2d7
1515859.354:00dc:00e0:Call ntdll.RtlQueryEnvironmentVariable_U(00000000,0081e2d0,0081e2e0) ret=7b05c305
1515859.354:00dc:00e0:trace:environ:RtlQueryEnvironmentVariable_U 0000000000000000 L"TMP" 000000000081E2E0
1515859.354:00dc:00e0:Ret  ntdll.RtlQueryEnvironmentVariable_U() retval=00000000 ret=7b05c305
1515859.354:00dc:00e0:Call ntdll.RtlGetFullPathName_U(0081e350 L"C:\\users\\tjmaciei\\Temp",00000208,0081e350,00000000) ret=7b01d1e4
1515859.354:00dc:00e0:trace:file:RtlGetFullPathName_U (L"C:\\users\\tjmaciei\\Temp" 520 000000000081E350 0000000000000000)
1515859.354:00dc:00e0:Ret  ntdll.RtlGetFullPathName_U() retval=0000002c ret=7b01d1e4
1515859.354:00dc:00e0:Call ntdll.memset(0081e6d0,00000000,000001c2) ret=7b01d390
1515859.354:00dc:00e0:Ret  ntdll.memset() retval=0081e6d0 ret=7b01d390
1515859.354:00dc:00e0:trace:file:GetTempPathW returning 23, L"C:\\users\\tjmaciei\\Temp\\"

That is, the darned thing does a GetEnvironmentVariableW! I don't know what real Windows does, but we can assume it's maybe smarter than this.

@thiagomacieira
Copy link
Contributor

I've just tested this patch with Wine 7.22 on Arch Linux, with and without WINE_ROOT set. The selftests launch and (mostly) pass. I get a BATS failure on selftest_fastfail but that seems unrelated (it's expecting code 0xC0000005 but getting 0xc0000409).

@lukasz-tuz
Copy link
Contributor

the darned thing does a GetEnvironmentVariableW! I don't know what real Windows does, but we can assume it's maybe smarter than this.

Well, it probably isn't. Quoting the documentation for GetTempPathW:

The GetTempPath function checks for the existence of environment variables in the following order and uses the first path found:

  1. The path specified by the TMP environment variable.
  2. The path specified by the TEMP environment variable.
  3. The path specified by the USERPROFILE environment variable.
  4. The Windows directory.

Note that the function does not verify that the path exists, nor does it test to see if the current process has any kind of access rights to the path.

The last one probably just looks for %WINDIR%.

get a BATS failure on selftest_fastfail but that seems unrelated (it's expecting code 0xC0000005 but getting 0xc0000409)

Same result here.

@lukasz-tuz
Copy link
Contributor

Ah, the problem was right there, staring me in the face:

// MinGW's ftruncate64 tries to check free disk space and that fails on Wine,
// so use the the 32-bit offset version (which calls _chsize)

And the following typo:

#    undef fruncate

After changing to

#    undef ftruncate

opendcdiag stops failing when trying to truncate the temp file with ftruncate.

@lukasz-tuz lukasz-tuz force-pushed the temp-files-on-windows branch 3 times, most recently from a5f7942 to 0eca7aa Compare December 20, 2022 15:21
thiagomacieira
thiagomacieira previously approved these changes Jan 7, 2023
Copy link
Contributor

@thiagomacieira thiagomacieira left a comment

Choose a reason for hiding this comment

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

Approving to unblock, but my comment on tmpfile.c is unaddressed.

dawid-sabat and others added 2 commits January 9, 2023 12:04
For Windows compilations of OpenDCDiag, temp files were created in directory where the .exe is placed.
The application doesn't always have access rights to do that.

Changes here move all temp files to Windows designated area:
C:\Users\%username\AppData\Local\Temp

Signed-off-by: dawid-sabat <dawid.sabat@intel.com>
Signed-off-by: Lukasz Tuz <lukasz.tuz@intel.com>
Copy link
Contributor

@busykai busykai left a comment

Choose a reason for hiding this comment

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

LGTM.

@busykai busykai dismissed lukasz-tuz’s stale review January 9, 2023 15:58

The concern was addressed.

@busykai busykai merged commit fc9cd16 into opendcdiag:main Jan 9, 2023
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.

5 participants