[Bug] program will block when recv window size change signal in do case case b := <-bufCh:
Opened this issue · 2 comments
RainyBow commented
Bug reports
程序在处理输入的过程中收到窗口变化信号会阻塞在 stopHandleSignalCh <- struct{}{}
When the program receives a window change signal during input processing, it will be blocked at stopHandleSignalCh <- struct{}{}
Please file a bug report here.
// Run starts prompt.
func (p *Prompt) Run() {
p.skipTearDown = false
defer debug.Teardown()
debug.Log("start prompt")
p.setUp()
defer p.tearDown()
if p.completion.showAtStart {
p.completion.Update(*p.buf.Document())
}
p.renderer.Render(p.buf, p.completion)
bufCh := make(chan []byte, 128)
stopReadBufCh := make(chan struct{})
go p.readBuffer(bufCh, stopReadBufCh)
exitCh := make(chan int)
winSizeCh := make(chan *WinSize)
stopHandleSignalCh := make(chan struct{})
go p.handleSignals(exitCh, winSizeCh, stopHandleSignalCh)
for {
select {
case b := <-bufCh:
if shouldExit, e := p.feed(b); shouldExit {
p.renderer.BreakLine(p.buf)
stopReadBufCh <- struct{}{}
stopHandleSignalCh <- struct{}{} /* <--- here pos1 */
return
} else if e != nil {
// Stop goroutine to run readBuffer function
stopReadBufCh <- struct{}{}
stopHandleSignalCh <- struct{}{} /* <--- here pos2*/
// Unset raw mode
// Reset to Blocking mode because returned EAGAIN when still set non-blocking mode.
debug.AssertNoError(p.in.TearDown())
p.executor(e.input)
p.completion.Update(*p.buf.Document())
p.renderer.Render(p.buf, p.completion)
if p.exitChecker != nil && p.exitChecker(e.input, true) {
p.skipTearDown = true
return
}
// Set raw mode
debug.AssertNoError(p.in.Setup())
go p.readBuffer(bufCh, stopReadBufCh)
go p.handleSignals(exitCh, winSizeCh, stopHandleSignalCh)
} else {
p.completion.Update(*p.buf.Document())
p.renderer.Render(p.buf, p.completion)
}
case w := <-winSizeCh:
p.renderer.UpdateWinSize(w)
p.renderer.Render(p.buf, p.completion)
case code := <-exitCh:
p.renderer.BreakLine(p.buf)
p.tearDown()
os.Exit(code)
default:
time.Sleep(10 * time.Millisecond)
}
}
}
func (p *Prompt) handleSignals(exitCh chan int, winSizeCh chan *WinSize, stop chan struct{}) {
in := p.in
sigCh := make(chan os.Signal, 1)
signal.Notify(
sigCh,
syscall.SIGINT,
syscall.SIGTERM,
syscall.SIGQUIT,
syscall.SIGWINCH,
)
for {
select {
case <-stop:
debug.Log("stop handleSignals")
return
case s := <-sigCh:
switch s {
case syscall.SIGINT: // kill -SIGINT XXXX or Ctrl+c
debug.Log("Catch SIGINT")
exitCh <- 0
case syscall.SIGTERM: // kill -SIGTERM XXXX
debug.Log("Catch SIGTERM")
exitCh <- 1
case syscall.SIGQUIT: // kill -SIGQUIT XXXX
debug.Log("Catch SIGQUIT")
exitCh <- 0
case syscall.SIGWINCH:
debug.Log("Catch SIGWINCH")
winSizeCh <- in.GetWinSize() /* <--here pos3 */
}
}
}
}
if get a syscall.SIGWINCH signal before pos1 and pos2 , program whill block at pos3.
Expected Behavior
do not block
Current Behavior and Steps to Reproduce
这是一个概率事件,我连续执行了很多的命令才遇到这个问题
This is a probabilistic event. I encountered this problem after executing many commands in succession.
Context
Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.
- Operating System: linux
- Terminal Emulator: (i.e. xshell/secureCRT)
- tag of go-prompt or commit revision:
gary561 commented
gary561 commented
change code
winSizeCh := make(chan *WinSize)
to
winSizeCh := make(chan *WinSize,1)
fix this issue