restore term when receive signal (#200)

* restore term when receive signal

add `CaptureExitSignal` to capture exit signals and exit gracefull(disabled by default)

* update deps
This commit is contained in:
ChenYe 2022-04-24 21:25:55 +08:00 committed by GitHub
parent c34436b973
commit 80e2d1961b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 9 deletions

View File

@ -85,6 +85,7 @@ func main() {
panic(err) panic(err)
} }
defer l.Close() defer l.Close()
l.CaptureExitSignal()
setPasswordCfg := l.GenPasswordConfig() setPasswordCfg := l.GenPasswordConfig()
setPasswordCfg.SetListener(func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) { setPasswordCfg.SetListener(func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool) {

4
go.mod
View File

@ -3,8 +3,8 @@ module github.com/chzyer/readline
go 1.15 go 1.15
require ( require (
github.com/chzyer/test v0.0.0-20210722231415-061457976a23 github.com/chzyer/test v1.0.0
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5
) )
require github.com/chzyer/logex v1.2.0 require github.com/chzyer/logex v1.2.1

8
go.sum
View File

@ -1,6 +1,6 @@
github.com/chzyer/logex v1.2.0 h1:+eqR0HfOetur4tgnC8ftU5imRnhi4te+BadWS95c5AM= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
github.com/chzyer/test v0.0.0-20210722231415-061457976a23 h1:dZ0/VyGgQdVGAss6Ju0dt5P0QltE0SFY5Woh6hbIfiQ= github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@ -434,6 +434,10 @@ func (o *Operation) Slice() ([]byte, error) {
} }
func (o *Operation) Close() { func (o *Operation) Close() {
select {
case o.errchan <- io.EOF:
default:
}
o.history.Close() o.history.Close()
} }

View File

@ -17,7 +17,9 @@
// //
package readline package readline
import "io" import (
"io"
)
type Instance struct { type Instance struct {
Config *Config Config *Config
@ -270,14 +272,24 @@ func (i *Instance) ReadSlice() ([]byte, error) {
} }
// we must make sure that call Close() before process exit. // we must make sure that call Close() before process exit.
// if there has a pending reading operation, that reading will be interrupted.
// so you can capture the signal and call Instance.Close(), it's thread-safe.
func (i *Instance) Close() error { func (i *Instance) Close() error {
i.Config.Stdin.Close()
i.Operation.Close()
if err := i.Terminal.Close(); err != nil { if err := i.Terminal.Close(); err != nil {
return err return err
} }
i.Config.Stdin.Close()
i.Operation.Close()
return nil return nil
} }
// call CaptureExitSignal when you want readline exit gracefully.
func (i *Instance) CaptureExitSignal() {
CaptureExitSignal(func() {
i.Close()
})
}
func (i *Instance) Clean() { func (i *Instance) Clean() {
i.Operation.Clean() i.Operation.Clean()
} }

View File

@ -6,9 +6,11 @@ import (
"container/list" "container/list"
"fmt" "fmt"
"os" "os"
"os/signal"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"syscall"
"time" "time"
"unicode" "unicode"
) )
@ -275,3 +277,13 @@ func Debug(o ...interface{}) {
fmt.Fprintln(f, o...) fmt.Fprintln(f, o...)
f.Close() f.Close()
} }
func CaptureExitSignal(f func()) {
cSignal := make(chan os.Signal, 1)
signal.Notify(cSignal, os.Interrupt, syscall.SIGTERM)
go func() {
for range cSignal {
f()
}
}()
}