cmd/geth: exit the console cleanly when interrupted

This fix applies mostly to unsupported terminals that do not trigger the
special interrupt handling in liner. Supported terminals were covered
because liner.Prompt returns an error if Ctrl-C is pressed.
This commit is contained in:
Felix Lange 2015-05-27 00:52:02 +02:00
parent 612f01400f
commit 9253fc337e

@ -22,6 +22,7 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"os" "os"
"os/signal"
"path/filepath" "path/filepath"
"strings" "strings"
@ -47,7 +48,8 @@ type dumbterm struct{ r *bufio.Reader }
func (r dumbterm) Prompt(p string) (string, error) { func (r dumbterm) Prompt(p string) (string, error) {
fmt.Print(p) fmt.Print(p)
return r.r.ReadString('\n') line, err := r.r.ReadString('\n')
return strings.TrimSuffix(line, "\n"), err
} }
func (r dumbterm) PasswordPrompt(p string) (string, error) { func (r dumbterm) PasswordPrompt(p string) (string, error) {
@ -182,10 +184,38 @@ func (self *jsre) exec(filename string) error {
} }
func (self *jsre) interactive() { func (self *jsre) interactive() {
// Read input lines.
prompt := make(chan string)
inputln := make(chan string)
go func() {
defer close(inputln)
for { for {
input, err := self.Prompt(self.ps1) line, err := self.Prompt(<-prompt)
if err != nil { if err != nil {
break return
}
inputln <- line
}
}()
// Wait for Ctrl-C, too.
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt)
defer func() {
if self.atexit != nil {
self.atexit()
}
self.re.Stop(false)
}()
for {
prompt <- self.ps1
select {
case <-sig:
fmt.Println("caught interrupt, exiting")
return
case input, ok := <-inputln:
if !ok || indentCount <= 0 && input == "exit" {
return
} }
if input == "" { if input == "" {
continue continue
@ -193,19 +223,13 @@ func (self *jsre) interactive() {
str += input + "\n" str += input + "\n"
self.setIndent() self.setIndent()
if indentCount <= 0 { if indentCount <= 0 {
if input == "exit" {
break
}
hist := str[:len(str)-1] hist := str[:len(str)-1]
self.AppendHistory(hist) self.AppendHistory(hist)
self.parseInput(str) self.parseInput(str)
str = "" str = ""
} }
} }
if self.atexit != nil {
self.atexit()
} }
self.re.Stop(false)
} }
func (self *jsre) withHistory(op func(*os.File)) { func (self *jsre) withHistory(op func(*os.File)) {