···221221 Dir string
222222223223 Stdout, Stderr io.Writer
224224- Stdin io.Reader
225225- PipelineFunc func(context.Context, context.CancelFunc) error
224224+225225+ // Stdin is used for passing input to the command
226226+ // The caller must make sure the Stdin writer is closed properly to finish the Run function.
227227+ // Otherwise, the Run function may hang for long time or forever, especially when the Git's context deadline is not the same as the caller's.
228228+ // Some common mistakes:
229229+ // * `defer stdinWriter.Close()` then call `cmd.Run()`: the Run() would never return if the command is killed by timeout
230230+ // * `go { case <- parentContext.Done(): stdinWriter.Close() }` with `cmd.Run(DefaultTimeout)`: the command would have been killed by timeout but the Run doesn't return until stdinWriter.Close()
231231+ // * `go { if stdoutReader.Read() err != nil: stdinWriter.Close() }` with `cmd.Run()`: the stdoutReader may never return error if the command is killed by timeout
232232+ // In the future, ideally the git module itself should have full control of the stdin, to avoid such problems and make it easier to refactor to a better architecture.
233233+ Stdin io.Reader
234234+235235+ PipelineFunc func(context.Context, context.CancelFunc) error
226236}
227237228238func commonBaseEnvs() []string {
-15
modules/indexer/code/indexer.go
···122122 indexer := *globalIndexer.Load()
123123 for _, indexerData := range items {
124124 log.Trace("IndexerData Process Repo: %d", indexerData.RepoID)
125125-126126- // FIXME: it seems there is a bug in `CatFileBatch` or `nio.Pipe`, which will cause the process to hang forever in rare cases
127127- /*
128128- sync.(*Cond).Wait(cond.go:70)
129129- github.com/djherbis/nio/v3.(*PipeReader).Read(sync.go:106)
130130- bufio.(*Reader).fill(bufio.go:106)
131131- bufio.(*Reader).ReadSlice(bufio.go:372)
132132- bufio.(*Reader).collectFragments(bufio.go:447)
133133- bufio.(*Reader).ReadString(bufio.go:494)
134134- code.gitea.io/gitea/modules/git.ReadBatchLine(batch_reader.go:149)
135135- code.gitea.io/gitea/modules/indexer/code.(*BleveIndexer).addUpdate(bleve.go:214)
136136- code.gitea.io/gitea/modules/indexer/code.(*BleveIndexer).Index(bleve.go:296)
137137- code.gitea.io/gitea/modules/indexer/code.(*wrappedIndexer).Index(wrapped.go:74)
138138- code.gitea.io/gitea/modules/indexer/code.index(indexer.go:105)
139139- */
140125 if err := index(ctx, indexer, indexerData.RepoID); err != nil {
141126 unhandled = append(unhandled, indexerData)
142127 if !setting.IsInTesting {