-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Ignore Sync errors on pipes when doing CheckAttributeReader.CheckPath
, fix the hang of git cat-file
#17096
Conversation
This comment has been minimized.
This comment has been minimized.
This was my worry when we added the error check here in the first place. But I couldn't force it to happen myself - Did you actually get this error reported? If you didn't - it's possible something else is actually happening: I added the Now if you're experiencing some block then the |
Looking again at the code - I think you're likely suffering from the problem I was experiencing earlier. Can you repeatedly replicate this issue? |
diff --git a/modules/git/repo_attribute.go b/modules/git/repo_attribute.go
index 0bd7d7e49..f001e65e3 100644
--- a/modules/git/repo_attribute.go
+++ b/modules/git/repo_attribute.go
@@ -112,13 +112,15 @@ func (c *CheckAttributeReader) Init(ctx context.Context) error {
if len(c.IndexFile) > 0 && CheckGitVersionAtLeast("1.7.8") == nil {
cmdArgs = append(cmdArgs, "--cached")
- c.env = []string{"GIT_INDEX_FILE=" + c.IndexFile}
+ c.env = append(c.env, "GIT_INDEX_FILE="+c.IndexFile)
}
if len(c.WorkTree) > 0 && CheckGitVersionAtLeast("1.7.8") == nil {
- c.env = []string{"GIT_WORK_TREE=" + c.WorkTree}
+ c.env = append(c.env, "GIT_WORK_TREE="+c.WorkTree)
}
+ c.env = append(c.env, "GIT_FLUSH=1")
+
if len(c.Attributes) > 0 {
cmdArgs = append(cmdArgs, c.Attributes...)
cmdArgs = append(cmdArgs, "--") Could you check if this helps? |
Your patch is good, but it doesn't help about this problem. They are different problems. Linux document has said that a pipe should NOT be So I think my patch makes the problem better than before. On you side, the On my side, the If one day we have enough confidence about the pipe's behavior on all platforms, we can optimize this logic again. ps: I have written a test program to test
It's obviously wrong to call Test Program: package main
import (
"log"
"os"
"os/exec"
"runtime"
)
func main() {
log.Printf("GOOS=%v\n", runtime.GOOS)
var err error
pipeReader, pipeWriter, err := os.Pipe()
if err != nil {
log.Fatalf("os.Pipe error: %v", err)
}
cmd := exec.Command("/bin/cat")
cmd.Stdin = pipeReader
err = cmd.Start()
if err != nil {
log.Fatalf("cmd.Start error: %v", err)
}
_, err = pipeWriter.WriteString("test")
if err != nil {
log.Fatalf("pipeWriter.Write error: %v", err)
}
err = pipeWriter.Sync()
if err != nil {
log.Fatalf("pipeWriter.Sync error: %v", err)
}
} |
Both yes, I added many debug logs and I am sure that ignore the And you can refer the test program to test |
I too am running on Linux but didn't get the sync error you do - otherwise I'd have never put it in. I even tested in a Windows virtual machine. Hmm, are you building with go 1.17? I know that at some point go moved to use pipe2 - maybe that doesn't error on sync. Or maybe it's a kernel difference. I also don't understand how an err at the Sync causes a hang. The logic there should abort and cancel the reader before a hang was possible at Read - at least that was how I intended it - so if there's a hang despite the error then that logic is failing somehow. So I'm doubly confused and that makes me concerned that I've got the channel logic wrong somewhere in there - but I just can't see it. Anyway if GIT_FLUSH env reliably prevents this hang along with ignoring the error on sync then I am happy. But if the actual slow down/hang is not occurring because of the sync but at read - then you're likely suffering the same issue that the original native git implementation of commit info was suffering. That is, that although the write has been sent it's not reaching the git program or the git program's output is not reaching the read. If GIT_FLUSH prevents this then that was due to git buffering, if not then... Perhaps placing a runtime.Gosched() in between the write and the read is needed? Another is changing the code to make things non-synchronous - that is push all of the paths in to git attribute channel, closing the writer at the end and reading them all. This would both fill the buffer and force go to schedule the other goroutines. |
About environmentI have tested the
I believe that since Linux document says that Why there is a hangIt seems that there are other flaws when running Because there may be unknown bugs, when |
Signed-off-by: Andrew Thornton <[email protected]>
Signed-off-by: Andrew Thornton <[email protected]>
Signed-off-by: Andrew Thornton <[email protected]>
Co-authored-by: Lauris BH <[email protected]>
It is not necessary to call Sync on pipes. And the
Sync
usually results in error: "sync |1: invalid argument".Ref: https://man7.org/linux/man-pages/man2/fdatasync.2.html :
If we return early from
CheckPath
whenSync
returns error, theGetLanguageStats
will hang forever (because the stdin's buffer will be fully filled, thenWrite
inCheckPath
blocks)But I can not confirm the
Sync
behaviors on different platforms, so I think it's OK to keep it while ignore the returned error.Related issues:
Bug report:
Add caller to cat-file batch calls for debug: