瀏覽代碼

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.
Felix Lange 10 年之前
父節點
當前提交
9253fc337e
共有 1 個文件被更改,包括 44 次插入20 次删除
  1. 44 20
      cmd/geth/js.go

+ 44 - 20
cmd/geth/js.go

@@ -22,6 +22,7 @@ import (
 	"fmt"
 	"math/big"
 	"os"
+	"os/signal"
 	"path/filepath"
 	"strings"
 
@@ -47,7 +48,8 @@ type dumbterm struct{ r *bufio.Reader }
 
 func (r dumbterm) Prompt(p string) (string, error) {
 	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) {
@@ -182,30 +184,52 @@ func (self *jsre) exec(filename string) error {
 }
 
 func (self *jsre) interactive() {
-	for {
-		input, err := self.Prompt(self.ps1)
-		if err != nil {
-			break
+	// Read input lines.
+	prompt := make(chan string)
+	inputln := make(chan string)
+	go func() {
+		defer close(inputln)
+		for {
+			line, err := self.Prompt(<-prompt)
+			if err != nil {
+				return
+			}
+			inputln <- line
 		}
-		if input == "" {
-			continue
+	}()
+	// Wait for Ctrl-C, too.
+	sig := make(chan os.Signal, 1)
+	signal.Notify(sig, os.Interrupt)
+
+	defer func() {
+		if self.atexit != nil {
+			self.atexit()
 		}
-		str += input + "\n"
-		self.setIndent()
-		if indentCount <= 0 {
-			if input == "exit" {
-				break
+		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 == "" {
+				continue
+			}
+			str += input + "\n"
+			self.setIndent()
+			if indentCount <= 0 {
+				hist := str[:len(str)-1]
+				self.AppendHistory(hist)
+				self.parseInput(str)
+				str = ""
 			}
-			hist := str[:len(str)-1]
-			self.AppendHistory(hist)
-			self.parseInput(str)
-			str = ""
 		}
 	}
-	if self.atexit != nil {
-		self.atexit()
-	}
-	self.re.Stop(false)
 }
 
 func (self *jsre) withHistory(op func(*os.File)) {