mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 19:38:23 +00:00 
			
		
		
		
	Backport #33901
This commit is contained in:
		| @@ -9,6 +9,8 @@ import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"time" | ||||
|  | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| ) | ||||
| @@ -102,7 +104,7 @@ type CheckAttributeReader struct { | ||||
|  | ||||
| 	stdinReader io.ReadCloser | ||||
| 	stdinWriter *os.File | ||||
| 	stdOut      attributeWriter | ||||
| 	stdOut      *nulSeparatedAttributeWriter | ||||
| 	cmd         *Command | ||||
| 	env         []string | ||||
| 	ctx         context.Context | ||||
| @@ -152,7 +154,6 @@ func (c *CheckAttributeReader) Init(ctx context.Context) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Run run cmd | ||||
| func (c *CheckAttributeReader) Run() error { | ||||
| 	defer func() { | ||||
| 		_ = c.stdinReader.Close() | ||||
| @@ -176,7 +177,7 @@ func (c *CheckAttributeReader) Run() error { | ||||
| func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err error) { | ||||
| 	defer func() { | ||||
| 		if err != nil && err != c.ctx.Err() { | ||||
| 			log.Error("Unexpected error when checking path %s in %s. Error: %v", path, c.Repo.Path, err) | ||||
| 			log.Error("Unexpected error when checking path %s in %s, error: %v", path, filepath.Base(c.Repo.Path), err) | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| @@ -191,9 +192,31 @@ func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	reportTimeout := func() error { | ||||
| 		stdOutClosed := false | ||||
| 		select { | ||||
| 		case <-c.stdOut.closed: | ||||
| 			stdOutClosed = true | ||||
| 		default: | ||||
| 		} | ||||
| 		debugMsg := fmt.Sprintf("check path %q in repo %q", path, filepath.Base(c.Repo.Path)) | ||||
| 		debugMsg += fmt.Sprintf(", stdOut: tmp=%q, pos=%d, closed=%v", string(c.stdOut.tmp), c.stdOut.pos, stdOutClosed) | ||||
| 		if c.cmd.cmd != nil { | ||||
| 			debugMsg += fmt.Sprintf(", process state: %q", c.cmd.cmd.ProcessState.String()) | ||||
| 		} | ||||
| 		_ = c.Close() | ||||
| 		return fmt.Errorf("CheckPath timeout: %s", debugMsg) | ||||
| 	} | ||||
|  | ||||
| 	rs = make(map[string]string) | ||||
| 	for range c.Attributes { | ||||
| 		select { | ||||
| 		case <-time.After(5 * time.Second): | ||||
| 			// There is a strange "hang" problem in gitdiff.GetDiff -> CheckPath | ||||
| 			// So add a timeout here to mitigate the problem, and output more logs for debug purpose | ||||
| 			// In real world, if CheckPath runs long than seconds, it blocks the end user's operation, | ||||
| 			// and at the moment the CheckPath result is not so important, so we can just ignore it. | ||||
| 			return nil, reportTimeout() | ||||
| 		case attr, ok := <-c.stdOut.ReadAttribute(): | ||||
| 			if !ok { | ||||
| 				return nil, c.ctx.Err() | ||||
| @@ -206,18 +229,12 @@ func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err | ||||
| 	return rs, nil | ||||
| } | ||||
|  | ||||
| // Close close pip after use | ||||
| func (c *CheckAttributeReader) Close() error { | ||||
| 	c.cancel() | ||||
| 	err := c.stdinWriter.Close() | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| type attributeWriter interface { | ||||
| 	io.WriteCloser | ||||
| 	ReadAttribute() <-chan attributeTriple | ||||
| } | ||||
|  | ||||
| type attributeTriple struct { | ||||
| 	Filename  string | ||||
| 	Attribute string | ||||
| @@ -281,7 +298,7 @@ func (wr *nulSeparatedAttributeWriter) Close() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Create a check attribute reader for the current repository and provided commit ID | ||||
| // CheckAttributeReader creates a check attribute reader for the current repository and provided commit ID | ||||
| func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeReader, context.CancelFunc) { | ||||
| 	indexFilename, worktree, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID) | ||||
| 	if err != nil { | ||||
| @@ -303,21 +320,21 @@ func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeRe | ||||
| 	} | ||||
| 	ctx, cancel := context.WithCancel(repo.Ctx) | ||||
| 	if err := checker.Init(ctx); err != nil { | ||||
| 		log.Error("Unable to open checker for %s. Error: %v", commitID, err) | ||||
| 		log.Error("Unable to open attribute checker for commit %s, error: %v", commitID, err) | ||||
| 	} else { | ||||
| 		go func() { | ||||
| 			err := checker.Run() | ||||
| 			if err != nil && err != ctx.Err() { | ||||
| 				log.Error("Unable to open checker for %s. Error: %v", commitID, err) | ||||
| 			if err != nil && !IsErrCanceledOrKilled(err) { | ||||
| 				log.Error("Attribute checker for commit %s exits with error: %v", commitID, err) | ||||
| 			} | ||||
| 			cancel() | ||||
| 		}() | ||||
| 	} | ||||
| 	deferable := func() { | ||||
| 	deferrable := func() { | ||||
| 		_ = checker.Close() | ||||
| 		cancel() | ||||
| 		deleteTemporaryFile() | ||||
| 	} | ||||
|  | ||||
| 	return checker, deferable | ||||
| 	return checker, deferrable | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user