forked from gitea/gitea
1
0
Fork 0

Prevent intermittent race in attribute reader close (#19537) (#19539)

Backport #19537

There is a potential rare race possible whereby the c.running channel could
be closed twice. Looking at the code I do not see a need for this c.running
channel and therefore I think we can remove this. (I think the c.running
might have been some attempt to prevent a hang but the use of os.Pipes should
prevent that.)

Signed-off-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
zeripath 2022-04-28 16:00:01 +01:00 committed by GitHub
parent 1465e0cbb2
commit 74602bb487
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 2 additions and 16 deletions

View File

@ -119,12 +119,10 @@ type CheckAttributeReader struct {
env []string env []string
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
running chan struct{}
} }
// Init initializes the cmd // Init initializes the cmd
func (c *CheckAttributeReader) Init(ctx context.Context) error { func (c *CheckAttributeReader) Init(ctx context.Context) error {
c.running = make(chan struct{})
cmdArgs := []string{"check-attr", "--stdin", "-z"} cmdArgs := []string{"check-attr", "--stdin", "-z"}
if len(c.IndexFile) > 0 && CheckGitVersionAtLeast("1.7.8") == nil { if len(c.IndexFile) > 0 && CheckGitVersionAtLeast("1.7.8") == nil {
@ -183,14 +181,7 @@ func (c *CheckAttributeReader) Run() error {
_ = c.stdOut.Close() _ = c.stdOut.Close()
}() }()
stdErr := new(bytes.Buffer) stdErr := new(bytes.Buffer)
err := c.cmd.RunInDirTimeoutEnvFullPipelineFunc(c.env, -1, c.Repo.Path, c.stdOut, stdErr, c.stdinReader, func(_ context.Context, _ context.CancelFunc) error { err := c.cmd.RunInDirTimeoutEnvFullPipeline(c.env, -1, c.Repo.Path, c.stdOut, stdErr, c.stdinReader)
select {
case <-c.running:
default:
close(c.running)
}
return nil
})
if err != nil && // If there is an error we need to return but: if err != nil && // If there is an error we need to return but:
c.ctx.Err() != err && // 1. Ignore the context error if the context is cancelled or exceeds the deadline (RunWithContext could return c.ctx.Err() which is Canceled or DeadlineExceeded) c.ctx.Err() != err && // 1. Ignore the context error if the context is cancelled or exceeds the deadline (RunWithContext could return c.ctx.Err() which is Canceled or DeadlineExceeded)
err.Error() != "signal: killed" { // 2. We should not pass up errors due to the program being killed err.Error() != "signal: killed" { // 2. We should not pass up errors due to the program being killed
@ -210,7 +201,7 @@ func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err
select { select {
case <-c.ctx.Done(): case <-c.ctx.Done():
return nil, c.ctx.Err() return nil, c.ctx.Err()
case <-c.running: default:
} }
if _, err = c.stdinWriter.Write([]byte(path + "\x00")); err != nil { if _, err = c.stdinWriter.Write([]byte(path + "\x00")); err != nil {
@ -237,11 +228,6 @@ func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err
func (c *CheckAttributeReader) Close() error { func (c *CheckAttributeReader) Close() error {
c.cancel() c.cancel()
err := c.stdinWriter.Close() err := c.stdinWriter.Close()
select {
case <-c.running:
default:
close(c.running)
}
return err return err
} }