terminal: add way to cancel goroutines command with ctrl-C (#2278)

The goroutines command can take a long time to complete if there are
many goroutines, add the possibility to terminate it early by pressing
ctrl-C.
This commit is contained in:
Alessandro Arzilli 2021-01-04 17:54:39 +01:00 committed by GitHub
parent 6726ec3aa3
commit 75f00b963c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 0 deletions

@ -723,7 +723,12 @@ func goroutines(t *Term, ctx callContext, argstr string) error {
gslen = 0 gslen = 0
gs []*api.Goroutine gs []*api.Goroutine
) )
t.longCommandStart()
for start >= 0 { for start >= 0 {
if t.longCommandCanceled() {
fmt.Printf("interrupted\n")
return nil
}
gs, start, err = t.client.ListGoroutines(start, goroutineBatchSize) gs, start, err = t.client.ListGoroutines(start, goroutineBatchSize)
if err != nil { if err != nil {
return err return err

@ -66,6 +66,9 @@ type Term struct {
// should be resumed before quitting. // should be resumed before quitting.
quitContinue bool quitContinue bool
longCommandMu sync.Mutex
longCommandCancelFlag bool
quittingMutex sync.Mutex quittingMutex sync.Mutex
quitting bool quitting bool
} }
@ -123,6 +126,7 @@ func (t *Term) Close() {
func (t *Term) sigintGuard(ch <-chan os.Signal, multiClient bool) { func (t *Term) sigintGuard(ch <-chan os.Signal, multiClient bool) {
for range ch { for range ch {
t.longCommandCancel()
t.starlarkEnv.Cancel() t.starlarkEnv.Cancel()
state, err := t.client.GetStateNonBlocking() state, err := t.client.GetStateNonBlocking()
if err == nil && state.Recording { if err == nil && state.Recording {
@ -481,6 +485,24 @@ func (t *Term) onStop() {
t.printDisplays() t.printDisplays()
} }
func (t *Term) longCommandCancel() {
t.longCommandMu.Lock()
defer t.longCommandMu.Unlock()
t.longCommandCancelFlag = true
}
func (t *Term) longCommandStart() {
t.longCommandMu.Lock()
defer t.longCommandMu.Unlock()
t.longCommandCancelFlag = false
}
func (t *Term) longCommandCanceled() bool {
t.longCommandMu.Lock()
defer t.longCommandMu.Unlock()
return t.longCommandCancelFlag
}
// isErrProcessExited returns true if `err` is an RPC error equivalent of proc.ErrProcessExited // isErrProcessExited returns true if `err` is an RPC error equivalent of proc.ErrProcessExited
func isErrProcessExited(err error) bool { func isErrProcessExited(err error) bool {
rpcError, ok := err.(rpc.ServerError) rpcError, ok := err.(rpc.ServerError)