chzyer / readline

Readline is a pure go(golang) implementation for GNU-Readline kind library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`(*Instance).Close()` hangs if there is a concurrent `(*Instance).ReadLine` call

slingamn opened this issue · comments

I'm using the following test case with readline v1.5.1, go version go1.20 linux/amd64:

package main

import (
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"github.com/chzyer/readline"
)

func main() {
	log.SetFlags(log.LstdFlags | log.Lmicroseconds)

	rl, err := readline.New("> ")
	if err != nil {
		log.Fatal(err)
	}
	defer rl.Close()
	log.SetOutput(rl.Stderr())

	input := make(chan string)

	go func() {
		closed := false
		for {
			line, err := rl.Readline()
			if err != nil {
				fmt.Fprintln(os.Stderr, "error: failed to read new input line:", err.Error())
				return
			}
			if !closed {
				input <- line
			}
			if !closed && strings.ToLower(strings.TrimSpace(line)) == "quit" {
				log.Printf("quit received\n")
				closed = true
				close(input)
			}
		}
	}()

	for {
		line, ok := <- input
		if !ok {
			log.Printf("quit acknowledged, sleeping")
			time.Sleep(time.Second)
			log.Printf("done sleeping, exiting")
			return
		}

		fmt.Fprintf(rl, "received %s\n", strings.TrimRight(line, "\r\n"))
	}
}

If I enter quit at the prompt and wait, I get the following output:

> quit
received quit
2023/02/06 01:19:18.052671 quit received
> 2023/02/06 01:19:18.053079 quit acknowledged, sleeping
2023/02/06 01:19:19.053285 done sleeping, exiting

but then the program hangs without exiting. SIGQUIT shows that the main goroutine is blocked in (*Instance).Close():

https://gist.github.com/slingamn/eb5bea5e623e848cd0903c29b155a0b3

It seems that this Wait() call:

t.wg.Wait()

is blocked by the failure of this select to terminate:

readline/std.go

Lines 120 to 125 in 7f93d88

select {
case <-c.notify:
return c.read, c.err
case <-c.stop:
return 0, io.EOF
}

My diagnosis is that FillableStdin fails to pass the Close() call through to CancelableStdin, which would stop the select. This patch fixes the issue, but may introduce other issues:

slingamn@4c5bb20

Thanks very much for your time.