Browse Source

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 năm trước cách đây
mục cha
commit
9253fc337e
1 tập tin đã thay đổi với 44 bổ sung20 xóa
  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)) {