-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
build: use Go 1.23, require minimum 1.22 #9651
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
Conversation
Windows reparse point handling has changed, we need to check it out:
Possibly, as simple as just removing our reparse handling entirely for 1.23+, my reading is that mount points are now just followed and don't look like symlinks any more.
|
@calmh On a Windows 11 Pro amd64 box (10.0.22631.4037), the tests pass: >go version
go version go1.23.0 windows/amd64
>go test -v -run TestWalk
=== RUN TestWalkTraverseDirJunct
--- PASS: TestWalkTraverseDirJunct (0.02s)
=== RUN TestWalkInfiniteRecursion
--- PASS: TestWalkInfiniteRecursion (0.03s)
PASS
ok github.com/syncthing/syncthing/lib/fs 0.820s So perhaps these issues are specific to Windows Server 2022 10.0.20348? |
I spun up a Windows 10 Pro amd64 VM (10.0.19045.2965), and the errors appeared. I'll try a Windows 11 VM now... |
The tests pass on a Windows 11 VM Pro amd64 23H2 10.0.22631.2861. |
Well that's worrying. |
Fixes test failures: === RUN TestWalkTraverseDirJunct walkfs_test.go:85: Directory junction was not traversed --- FAIL: TestWalkTraverseDirJunct (0.03s) === RUN TestWalkInfiniteRecursion walkfs_test.go:132: Infinite recursion not detected correctly --- FAIL: TestWalkInfiniteRecursion (0.04s) raised at syncthing#9651 (comment) See syncthing#9651 for details.
I committed a change that fixed the test failures on my Windows 10 VM. I haven't tested the change otherwise. |
I don't like that fix. For one, if the symlink bit isn't set (which is indeed a documented change in Go 1.23), we shouldn't need to do the reparse handling, we should already traverse the directory as is. Additionally, this would mean we try to parse reparse points on every Lstat which would likely be a significant performance regression. |
@rasa can you break it down to a minimal reproducer? IMHO this is a go bug. |
@calmh Yes, I will replace that change with a proper one. It appears we can replace all or most of our readReparseTag, with using Stat().ReparseTag instead, which was introduced in go1.11, as Reserved0, then renamed to ReparseTag in go1.21rc1, but not mentioned in the release notes. I've assigned this to myself, and will test the code on both my VMs, as well as GitHub's windows-2022 and windows-2019 instances. @bt90 I guess your right that it's a go bug. Go should return consistent results regardless of what version of Windows its run on. |
A solution is forthcoming. Here's a preview: click herefunc (f *BasicFilesystem) underlyingLstat(name string) (os.FileInfo, error) { var fi, err = os.Lstat(name)
} func godebug(godebug string) uint64 {
} |
See syncthing#9651 for details.
See syncthing#9651 for details.
The below code works in go1.21, go1.22, and go1.23, on windows 10, 11, windows-latest (windows-2022) and windoes-2019, with or without func (f *BasicFilesystem) underlyingLstat(name string) (os.FileInfo, error) {
fi, err := os.Lstat(name)
if err == nil && f.junctionsAsDirs {
v := reflect.Indirect(reflect.ValueOf(fi))
y := v.FieldByName("ReparseTag")
if y.Interface() == uint32(windows.IO_REPARSE_TAG_MOUNT_POINT) {
return &dirJunctFileInfo{fi}, nil
}
}
return fi, err
} Is it acceptable to use reflect to access non-public members of a FileInfo? It sure makes things faster and simpler. |
Another solution that would work for at least two years would be to add //go:debug winsymlink=0 to the existing file. This would force the pre-go1.23 functionality. |
I would prefer we understand what's going on and do the minimal fix. We shouldn't need to change our reparse parsing stuff, only when to trigger it. In principle it seems to me this should be just adding a "if go1.22" to our existing symlink-to-reparse-point check and in go1.23+ do nothing at all as it should just look like a normal directory. |
This fixes the test failures: === RUN TestWalkTraverseDirJunct walkfs_test.go:85: Directory junction was not traversed --- FAIL: TestWalkTraverseDirJunct (0.03s) === RUN TestWalkInfiniteRecursion walkfs_test.go:132: Infinite recursion not detected correctly --- FAIL: TestWalkInfiniteRecursion (0.04s) documented in syncthing#9651. This also undoes syncthing#9168 by not checking if ModeIrregular files are dedups as golang/go@f26fa05 removed the ModeIrregular bit from dedup files.
// Workaround for #9120 till golang properly handles deduplicated files by | ||
// considering them regular files. | ||
if fi.Mode()&os.ModeIrregular != 0 { | ||
if reparseTag, reparseErr := readReparseTag(name); reparseErr == nil && isDeduplicatedFile(reparseTag) { | ||
return &dedupFileInfo{fi}, nil | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this fixed in 1.22 and earlier? I did a search but I don't find the fix for this documented
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was fixed in 1.21 in Nov 2023 in
golang/go@f26fa05
junctionPointModeMask = os.ModeSymlink | ||
if version.Compare(runtime.Version(), "go1.23") >= 0 { | ||
// if GODEBUG=winsymlink=0, then we are in g1.22 mode so let's check for | ||
// os.ModeSymlink as well, as it can't hurt. | ||
junctionPointModeMask |= os.ModeIrregular | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
* main: (46 commits) build: use Go 1.23, require minimum 1.22 (syncthing#9651) gui, man, authors: Update docs, translations, and contributors lib/fs: Put the caseFS as the outermost layer (syncthing#9648) gui: Add Irish (ga) translation template (syncthing#9646) gui, man, authors: Update docs, translations, and contributors lib/syncthing: Add wrapper for access to model (syncthing#9627) cli: Remove `go-shlex` dependency (syncthing#9644) lib/sha256: Remove it (syncthing#9643) build: Update dependencies (syncthing#9640) Chmod -x non-executable files (fixes syncthing#9629) (syncthing#9630) gui, man, authors: Update docs, translations, and contributors all: minimal set of changes for iOS app (syncthing#9619) gui, man, authors: Update docs, translations, and contributors gui, man, authors: Update docs, translations, and contributors etc: Remove restart on suspend systemd service (ref syncthing#8448) (syncthing#9611) gui, man, authors: Update docs, translations, and contributors lib/fs: Add missing locks to fakeFile methods (fixes syncthing#9499) (syncthing#9603) lib/api: Increase test request timeout (fixes syncthing#9455) (syncthing#9602) gui, man, authors: Update docs, translations, and contributors lib/ignore: Remove unused patterns in cache (syncthing#9601) ...
…-smaller * upstream/main: build: use Go 1.23, require minimum 1.22 (syncthing#9651) gui, man, authors: Update docs, translations, and contributors
🥳