Fix Could not chdir in tw.exe for long runfiles paths on Windows - #30610
Fix Could not chdir in tw.exe for long runfiles paths on Windows#30610rdesgroppes wants to merge 1 commit into
Could not chdir in tw.exe for long runfiles paths on Windows#30610Conversation
9f38717 to
2386018
Compare
| # Long enough that both the runfiles chdir target and the executable's | ||
| # own path exceed MAX_PATH, exercising ChdirToRunfiles's longPathAware | ||
| # manifest and StartSubprocess's explicit-cwd fix. | ||
| long_name = 'x' * 150 |
There was a problem hiding this comment.
| long_name = 'x' * 150 | |
| long_name = 'x' * 256 |
would make it more obvious that this is long enough.
There was a problem hiding this comment.
Tried 'x' * 256 first, but it breaks the build for an unrelated reason: bisecting, 233 still passes but 234 fails with ERROR_INVALID_NAME, because Bazel writes a <name>.exe.runfiles_manifest file for each test target.
It turns out individual path components are capped at 255 characters, per Naming and referencing shares, directories, files, and metadata and What are file path length limits?.
At 234, <name>.exe.runfiles_manifest is 234 + 22 = 256 characters, one over the limit (233 lands exactly on the 255 boundary).
In short, that's a different limit than the MAX_PATH one this test targets.
=> landed on splitting the length across both the package directory and the target name instead (_130_chars, to make the length self-explanatory in the spirit of your suggestion), so the overall runfiles path still exceeds MAX_PATH while each individual path component stays comfortably under the 255-char ceiling.
|
@bazel-io fork 9.3.0 |
On Windows, `bazel test` fails for tests run through the native test wrapper (`tw.exe`) whose runfiles directory path exceeds `MAX_PATH` (260 characters), with `ERROR_FILENAME_EXCED_RANGE` (206) from `ChdirToRunfiles`'s call to `SetCurrentDirectoryW`. The `\\?\` extended-length prefix used by bazelbuild#29921 for `CreateProcessW`'s `lpApplicationName` would not help here: `SetCurrentDirectoryW` ignores that prefix regardless of length, as stated by MicrosoftDocs/feedback#1441. => declare `longPathAware` in `tw.exe`'s manifest (`tw_manifest.xml`, embedded via `tw_resources.rc` and `windows_resources` in `tools/test/BUILD`), which Windows 10 1607+ honors for `SetCurrentDirectoryW` once paired with the `LongPathsEnabled` registry opt-in. Once `ChdirToRunfiles` succeeds into a long directory, `StartSubprocess`'s `CreateProcessW` call also needs its current directory passed explicitly: implicit inheritance (`lpCurrentDirectory=nullptr`) otherwise fails with `ERROR_INVALID_PARAMETER` once `cwd` exceeds `MAX_PATH`, _even from a `longPathAware` process_. => populate it so that `windows::WaitableProcess::Create` can shorten it internally (through `AsShortPath`), like it does for the executable's own path. The new `testChdirToRunfilesWithPathLongerThanMaxPath` in `test_wrapper_test.py` exercises both fixes: the cwd fix always fails in `StartSubprocess` when missing, while a missing manifest can surface as either `ChdirToRunfiles`'s error or `rules_cc`'s `Runfiles::Create` (`FindTestBinary`) failing first, depending on path length.
2386018 to
4859368
Compare
Description
On Windows,
bazel testfails for tests run through the native test wrapper (tw.exe) whose runfiles directory path exceedsMAX_PATH(260 characters), withERROR_FILENAME_EXCED_RANGE(206) fromChdirToRunfiles's call toSetCurrentDirectoryW.The
\\?\extended-length prefix used by #29921 forCreateProcessW'slpApplicationNamewould not help here:SetCurrentDirectoryWignores that prefix regardless of length, as stated by MicrosoftDocs/feedback#1441.=> declare
longPathAwareintw.exe's manifest (tw_manifest.xml, embedded viatw_resources.rcandwindows_resourcesintools/test/BUILD), which Windows 10 1607+ honors forSetCurrentDirectoryWonce paired with theLongPathsEnabledregistry opt-in.Once
ChdirToRunfilessucceeds into a long directory,StartSubprocess'sCreateProcessWcall also needs its current directory passed explicitly: implicit inheritance (lpCurrentDirectory=nullptr) otherwise fails withERROR_INVALID_PARAMETERoncecwdexceedsMAX_PATH, even from alongPathAwareprocess.=> populate it so that
windows::WaitableProcess::Createcan shorten it internally (throughAsShortPath), like it does for the executable's own path.The new
testLongRunfilesPathChdirintest_wrapper_test.pyexercises both fixes: the cwd fix always fails inStartSubprocesswhen missing, while a missing manifest can surface as eitherChdirToRunfiles's error orrules_cc'sRunfiles::Create(FindTestBinary) failing first, depending on path length.Motivation
Fixes #30609
Build API Changes
No
Checklist
Release Notes
RELNOTES: Fix
Could not chdirintw.exefor long runfiles paths on Windows.