From 75f00b963c06e5d7a2840075a23a2de40b0ae7e2 Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Mon, 4 Jan 2021 17:54:39 +0100 Subject: [PATCH] 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. --- pkg/terminal/command.go | 5 +++++ pkg/terminal/terminal.go | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/pkg/terminal/command.go b/pkg/terminal/command.go index 1761f3c1..eac66195 100644 --- a/pkg/terminal/command.go +++ b/pkg/terminal/command.go @@ -723,7 +723,12 @@ func goroutines(t *Term, ctx callContext, argstr string) error { gslen = 0 gs []*api.Goroutine ) + t.longCommandStart() for start >= 0 { + if t.longCommandCanceled() { + fmt.Printf("interrupted\n") + return nil + } gs, start, err = t.client.ListGoroutines(start, goroutineBatchSize) if err != nil { return err diff --git a/pkg/terminal/terminal.go b/pkg/terminal/terminal.go index c042859f..f61cec9d 100644 --- a/pkg/terminal/terminal.go +++ b/pkg/terminal/terminal.go @@ -66,6 +66,9 @@ type Term struct { // should be resumed before quitting. quitContinue bool + longCommandMu sync.Mutex + longCommandCancelFlag bool + quittingMutex sync.Mutex quitting bool } @@ -123,6 +126,7 @@ func (t *Term) Close() { func (t *Term) sigintGuard(ch <-chan os.Signal, multiClient bool) { for range ch { + t.longCommandCancel() t.starlarkEnv.Cancel() state, err := t.client.GetStateNonBlocking() if err == nil && state.Recording { @@ -481,6 +485,24 @@ func (t *Term) onStop() { 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 func isErrProcessExited(err error) bool { rpcError, ok := err.(rpc.ServerError)