mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2024-11-21 20:35:11 +00:00
Remove possible races (#4070)
This commit is contained in:
parent
bacc8609ee
commit
19495eb9bb
10
src/core.go
10
src/core.go
@ -172,7 +172,9 @@ func Run(opts *Options) (int, error) {
|
|||||||
return chunkList.Push(data)
|
return chunkList.Push(data)
|
||||||
}, eventBox, executor, opts.ReadZero, opts.Filter == nil)
|
}, eventBox, executor, opts.ReadZero, opts.Filter == nil)
|
||||||
|
|
||||||
go reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip, initialReload, initialEnv)
|
readyChan := make(chan bool)
|
||||||
|
go reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip, initialReload, initialEnv, readyChan)
|
||||||
|
<-readyChan
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matcher
|
// Matcher
|
||||||
@ -224,7 +226,7 @@ func Run(opts *Options) (int, error) {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}, eventBox, executor, opts.ReadZero, false)
|
}, eventBox, executor, opts.ReadZero, false)
|
||||||
reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip, initialReload, initialEnv)
|
reader.ReadSource(opts.Input, opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip, initialReload, initialEnv, nil)
|
||||||
} else {
|
} else {
|
||||||
eventBox.Unwatch(EvtReadNew)
|
eventBox.Unwatch(EvtReadNew)
|
||||||
eventBox.WaitFor(EvtReadFin)
|
eventBox.WaitFor(EvtReadFin)
|
||||||
@ -299,7 +301,9 @@ func Run(opts *Options) (int, error) {
|
|||||||
itemIndex = 0
|
itemIndex = 0
|
||||||
inputRevision.bumpMajor()
|
inputRevision.bumpMajor()
|
||||||
header = make([]string, 0, opts.HeaderLines)
|
header = make([]string, 0, opts.HeaderLines)
|
||||||
reader.restart(command, environ)
|
readyChan := make(chan bool)
|
||||||
|
go reader.restart(command, environ, readyChan)
|
||||||
|
<-readyChan
|
||||||
}
|
}
|
||||||
|
|
||||||
exitCode := ExitOk
|
exitCode := ExitOk
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@ -98,20 +97,14 @@ func (r *Reader) terminate() {
|
|||||||
r.mutex.Unlock()
|
r.mutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) restart(command commandSpec, environ []string) {
|
func (r *Reader) restart(command commandSpec, environ []string, readyChan chan bool) {
|
||||||
r.event = int32(EvtReady)
|
r.event = int32(EvtReady)
|
||||||
r.startEventPoller()
|
r.startEventPoller()
|
||||||
|
success := r.readFromCommand(command.command, environ, func() {
|
||||||
r.mutex.Lock()
|
readyChan <- true
|
||||||
defer r.mutex.Unlock()
|
})
|
||||||
|
r.fin(success)
|
||||||
if exec, execOut := r.startCommand(command.command, environ); exec != nil {
|
removeFiles(command.tempFiles)
|
||||||
go func() {
|
|
||||||
success := r.feedCommandOutput(exec, execOut)
|
|
||||||
r.fin(success)
|
|
||||||
removeFiles(command.tempFiles)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) readChannel(inputChan chan string) bool {
|
func (r *Reader) readChannel(inputChan chan string) bool {
|
||||||
@ -128,21 +121,29 @@ func (r *Reader) readChannel(inputChan chan string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReadSource reads data from the default command or from standard input
|
// ReadSource reads data from the default command or from standard input
|
||||||
func (r *Reader) ReadSource(inputChan chan string, root string, opts walkerOpts, ignores []string, initCmd string, initEnv []string) {
|
func (r *Reader) ReadSource(inputChan chan string, root string, opts walkerOpts, ignores []string, initCmd string, initEnv []string, readyChan chan bool) {
|
||||||
r.startEventPoller()
|
r.startEventPoller()
|
||||||
var success bool
|
var success bool
|
||||||
|
signalReady := func() {
|
||||||
|
if readyChan != nil {
|
||||||
|
readyChan <- true
|
||||||
|
}
|
||||||
|
}
|
||||||
if inputChan != nil {
|
if inputChan != nil {
|
||||||
|
signalReady()
|
||||||
success = r.readChannel(inputChan)
|
success = r.readChannel(inputChan)
|
||||||
} else if len(initCmd) > 0 {
|
} else if len(initCmd) > 0 {
|
||||||
success = r.readFromCommand(initCmd, initEnv)
|
success = r.readFromCommand(initCmd, initEnv, signalReady)
|
||||||
} else if util.IsTty(os.Stdin) {
|
} else if util.IsTty(os.Stdin) {
|
||||||
cmd := os.Getenv("FZF_DEFAULT_COMMAND")
|
cmd := os.Getenv("FZF_DEFAULT_COMMAND")
|
||||||
if len(cmd) == 0 {
|
if len(cmd) == 0 {
|
||||||
|
signalReady()
|
||||||
success = r.readFiles(root, opts, ignores)
|
success = r.readFiles(root, opts, ignores)
|
||||||
} else {
|
} else {
|
||||||
success = r.readFromCommand(cmd, initEnv)
|
success = r.readFromCommand(cmd, initEnv, signalReady)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
signalReady()
|
||||||
success = r.readFromStdin()
|
success = r.readFromStdin()
|
||||||
}
|
}
|
||||||
r.fin(success)
|
r.fin(success)
|
||||||
@ -304,8 +305,9 @@ func (r *Reader) readFiles(root string, opts walkerOpts, ignores []string) bool
|
|||||||
return fastwalk.Walk(&conf, root, fn) == nil
|
return fastwalk.Walk(&conf, root, fn) == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should be called with the mutex held
|
func (r *Reader) readFromCommand(command string, environ []string, signalReady func()) bool {
|
||||||
func (r *Reader) startCommand(command string, environ []string) (*exec.Cmd, io.ReadCloser) {
|
r.mutex.Lock()
|
||||||
|
|
||||||
r.termFunc = nil
|
r.termFunc = nil
|
||||||
r.command = &command
|
r.command = &command
|
||||||
exec := r.executor.ExecCommand(command, true)
|
exec := r.executor.ExecCommand(command, true)
|
||||||
@ -314,7 +316,8 @@ func (r *Reader) startCommand(command string, environ []string) (*exec.Cmd, io.R
|
|||||||
}
|
}
|
||||||
execOut, err := exec.StdoutPipe()
|
execOut, err := exec.StdoutPipe()
|
||||||
if err != nil || exec.Start() != nil {
|
if err != nil || exec.Start() != nil {
|
||||||
return nil, nil
|
r.mutex.Unlock()
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to call to terminate the running command
|
// Function to call to terminate the running command
|
||||||
@ -323,20 +326,9 @@ func (r *Reader) startCommand(command string, environ []string) (*exec.Cmd, io.R
|
|||||||
util.KillCommand(exec)
|
util.KillCommand(exec)
|
||||||
}
|
}
|
||||||
|
|
||||||
return exec, execOut
|
signalReady()
|
||||||
}
|
r.mutex.Unlock()
|
||||||
|
|
||||||
func (r *Reader) feedCommandOutput(exec *exec.Cmd, execOut io.ReadCloser) bool {
|
|
||||||
r.feed(execOut)
|
r.feed(execOut)
|
||||||
return exec.Wait() == nil
|
return exec.Wait() == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) readFromCommand(command string, environ []string) bool {
|
|
||||||
r.mutex.Lock()
|
|
||||||
exec, execOut := r.startCommand(command, environ)
|
|
||||||
r.mutex.Unlock()
|
|
||||||
if exec == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return r.feedCommandOutput(exec, execOut)
|
|
||||||
}
|
|
||||||
|
@ -23,8 +23,12 @@ func TestReadFromCommand(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Normal command
|
// Normal command
|
||||||
reader.fin(reader.readFromCommand(`echo abc&&echo def`, nil))
|
counter := 0
|
||||||
if len(strs) != 2 || strs[0] != "abc" || strs[1] != "def" {
|
ready := func() {
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
reader.fin(reader.readFromCommand(`echo abc&&echo def`, nil, ready))
|
||||||
|
if len(strs) != 2 || strs[0] != "abc" || strs[1] != "def" || counter != 1 {
|
||||||
t.Errorf("%s", strs)
|
t.Errorf("%s", strs)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,9 +52,9 @@ func TestReadFromCommand(t *testing.T) {
|
|||||||
reader.startEventPoller()
|
reader.startEventPoller()
|
||||||
|
|
||||||
// Failing command
|
// Failing command
|
||||||
reader.fin(reader.readFromCommand(`no-such-command`, nil))
|
reader.fin(reader.readFromCommand(`no-such-command`, nil, ready))
|
||||||
strs = []string{}
|
strs = []string{}
|
||||||
if len(strs) > 0 {
|
if len(strs) > 0 || counter != 2 {
|
||||||
t.Errorf("%s", strs)
|
t.Errorf("%s", strs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user