Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Input frequently alternates between pager and prompt #508

Open
dradtke opened this issue Dec 26, 2024 · 3 comments
Open

Input frequently alternates between pager and prompt #508

dradtke opened this issue Dec 26, 2024 · 3 comments

Comments

@dradtke
Copy link

dradtke commented Dec 26, 2024

In some scenarios, it seems like input intended for the pager is instead read by the usql prompt.

When I first start up usql and query enough data to activate the pager, I can scroll through the results and exit the pager by simply pressing q. This is the expected behavior.

However, when I then run a different query that also uses the pager, pressing q instead shows the usql prompt, with the q press read:

=> q

Pressing q a second time then successfully quits the pager, but there is still the lingering input at the prompt.

This isn't specific to q, though it's the most common scenario for me. If I run the query again, pressing j repeatedly will alternate between scrolling the pager down one row, and adding another j at the prompt. Input seems to jump back and forth between the two, until I successfully get the pager to read a q.

My PAGER environment variable is not set, so usql is using whatever the default pager is (presumably less).

Tested with usql 0.19.14 on Ubuntu 22.04.

@dradtke
Copy link
Author

dradtke commented Dec 26, 2024

Doing some testing with strace, I was able to confirm that the pager (confirmed that it is less) is only getting some of the input. It opens /dev/pts/7 to capture the keystrokes, and only reads every other press. Is it possible that usql also opens a direct connection to the TTY, and that that connection conflicts with the one opened by less?

@dradtke
Copy link
Author

dradtke commented Dec 27, 2024

I'm wondering if this is actually a weird OS-level bug, but I'm not sure how to confirm that really.

What I believe is happening is that both usql and less have an open handle to the TTY. usql grabs it first, but then when less executes as a subprocess it opens it directly as well. Input at that point should go exclusively to less until it quits, but for some reason input alternates between the two processes.

@dradtke
Copy link
Author

dradtke commented Dec 27, 2024

I was able to put together a small proof-of-concept that has basically the same behavior as what I'm seeing in usql:

package main

import (
	"os"
	"os/exec"

	"github.com/xo/usql/rline"
)

func panicIf(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {
	f, err := os.Open("../usql/main.go")
	panicIf(err)

	cmd := exec.Command("less")
	cmd.Stdin = f
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	err = cmd.Start()
	panicIf(err)

	io, err := rline.New(true, false, false, "", "")
	panicIf(err)

	io.Next()

	err = cmd.Wait()
	panicIf(err)
}

Anything can be used as input to less, but for demonstrative purposes I'm using usql's main.go.

This seems to confirm what I'm seeing is that both less and the input function are running at the same time, and both trying to read input from the terminal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant