Open timbertson opened 9 years ago
That seems like a reasonable guess, though Selecta should print an error to stderr if it can't get a TTY.
Actually, here's the problem:
gsj@the-brick ~> set -x RESULT (cat .zshrc | hs)
gsj@the-brick ~> jobs
Job Group State Command
2 74396 stopped cat .zshrc | hs
No no no, HERE's the problem:
In fish, (foo) means $(foo) or
foo
.
Fish doesn't even have subshells, according to a quick google search. Mystery solved!
I believe it's not the same as a bash subshell, but it's still a sub-pipeline:
$ set x (echo -e '1\n2\n3' | grep 2)
$ echo $x
2
Whatever you want to call it, I don't see why selecta shouldn't work in place of grep
.
I think your jobs
thought is much more likely to be the culprit. Not sure how that happens, though.
Or, maybe I just shouldn't have called it a "subshell" in the issue - it's equivalent to $(...)
in bash, in which selecta
works fine.
My best guess is that selecta somehow starts up in a background process group, and it receives SIGTTIN
or SIGTTOU
when it tries to access the terminal.
OK, I've straced it which may help a little. Doing a diff, it looks like it's to do with the stty
process - but maybe that was already obvious.
Here are the strace
logs from a subpipeline (inside brackets) vs a top-level pipeline (which works). Both are just from the execv
on stty
onwards:
https://gist.github.com/gfxmonk/57c7e37d61baf0c48c86
Looks a lot like stty
just doesn't do anything, but I have no idea how it works, or why it might decide not to do its thing...
That gist seems to have disappeared, @timbertson. However, it seems like stty
must do something in fish; otherwise most tools with complex UIs would break. I haven't used fish myself and don't want to dive into a whole new shell to diagnose this, but I'm happy to provide a bit of support if someone else wants to look deeper.
Apologies, looks like it moved to https://gist.github.com/timbertson/57c7e37d61baf0c48c86 when I renamed myself on github (gists don't redirect)
stty
must do something in fish; otherwise most tools with complex UIs would break
I suspect that tools which (a) have complex terminal UIs and (b) are used inside a shell pipeline are rare - I can't think of any others aside from selecta that I'd use.
Maybe I'll ping the fish mailing list and see if anyone knows of ways in which sub-commands differ from top-level commands in terms of interacting with the TTY.
I did a bit of googling and, as it turns out, fish just ignores stty entirely. stty is certainly a mess of legacy badness, but that seems a bit strong! See this thread where ridiculousfish says that stty "doesn't do anything in fish". There's been no resolution there, so I guess it's still an open problem.
I assume that other interactive tools (vim, emacs, etc.) work properly because they use the underlying C functions, rather than stty.
I happened to come across this again today with another program, and since I understand it more now, I thought I'd summarize here:
As mentioned in https://github.com/fish-shell/fish-shell/issues/1949, fish runs process substitutions in a background process group, which does cause selecta to receive SIGTTOU when it tries to control the terminal (fish isn't lying - fd 0 is a tty, you're just not allowed to mess with it). It's no fault of stty, using the underlying system calls has the same issue.
A workaround is to run selecta more awkwardly so that it's a foreground process - e.g:
echo -e '1\n2\n3' | selecta | read --local result; echo "You picked: $result"
This might be a bit more robust if selecta supported null-terminating its result - then you could read --null
which would not be confused by whitespace.
Also, it would be great if selecta could handle SIGTTOU and quit with a relevant message about not being able to modify the TTY. That way the error would become much more google-able instead of the process being mysteriously suspended :)
I haven't dug into this too hard yet, I will probably try and get
strace
on it if nobody knows why this isn't working:I'm guessing it's failing to get /dev/tty from within the subshell for some reason?