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

Make it possible to leave "follow forever" mode without pressing Ctrl+C #49

Closed
Hubro opened this issue Feb 25, 2020 · 30 comments
Closed

Comments

@Hubro
Copy link

Hubro commented Feb 25, 2020

When piping the output of a long running process to less, the follow forever (F) command is very useful for keeping the freshest content on the screen, but unfortunately there doesn't seem to be a way to leave follow mode without also stopping the process producing output (CtrlC).

Would it be possible to add a keyboard shortcut for stopping follow forever mode without affecting other processes in the pipe?

(I suspect this is impossible, or at least extremely difficult, but it doesn't hurt to ask)

@aleclearmind
Copy link

This is partially related to #6.

@gwsw
Copy link
Owner

gwsw commented Mar 30, 2020

I made an attempt at this using select() but did not come up with a working solution. I abandoned the effort for now but saved my results in the alt-intr-char branch for future reference.

@gwsw
Copy link
Owner

gwsw commented Nov 19, 2020

Related to #62.

@aleclearmind
Copy link

I made an attempt at this using select() but did not come up with a working solution. I abandoned the effort for now but saved my results in the alt-intr-char branch for future reference.

I tried with select too but it wasn't effective. What about the pool solution I proposed #6?
Back in May 2019 you seemed to be reluctant to adopt select/poll, but if you're OK with select, why not pool'
less is a tool people use interactively, if there's a slightly different behavior across operating systems people will go "oh well...". It's not like we're breaking the portability of any script/piece of code out there.

@gwsw
Copy link
Owner

gwsw commented Nov 19, 2020

Well, poll and select perform very similar functionality, and it's not immediately clear to me that it would be any easier to implement using poll vs. select. In the Linux kernel, at least, both poll and select use the same mechanism (they both call f_op->poll on the file). In what way do you think that using poll would be better than select?

@aleclearmind
Copy link

It has been a while, but the issue with select for me was that, when a pipe is closed, it is notified among file descriptors that can be read, readfds, while I'd expect it to appear among exceptfds.
On the other hand, with poll, I was able to detect quite reliably when a pipe was being closed using POLLERR and POLLHUP.

man 2 poll is pretty explicit:

POLLERR
Error condition (only returned in revents; ignored in events). This bit is also set for a file descriptor referring to the write end of a pipe when the read end has been closed.
POLLHUP
Hang up (only returned in revents; ignored in events). Note that when reading from a channel such as a pipe or a stream socket, this event merely indicates that the peer closed its end of the channel. Subsequent reads from the channel will return 0 (end of file) only after all outstanding data in the channel has been consumed.

Or maybe I'm missing something and you tried something different with select.

Maybe we can move this discussion on #6.

@piotr-dobrogost
Copy link

Related unix.stackexchange.com question Is there any way to exit “less” follow mode without stopping other processes in pipe? with answers giving workarounds using shell features to supress ctrl+c propagation across processes involved in a pipe.

@jarnos
Copy link

jarnos commented Nov 23, 2020

I do not see what is difficult there. At least in Bash shell you could put the reading process in background and wait for keypress like this:

cat /dev/urandom | tr -cd 'a-zA-Z0-9' & read -rn1; kill $!

You could pipe some appending input for less like this

{ cat /dev/urandom | tr -cd 'a-zA-Z0-9' & } | less +F

Though I do not understand why it writes only a screen of text without user interaction; Ctrl + C, F helps.

@piotr-dobrogost
Copy link

Though I do not understand why it writes only a screen of text without user interaction; Ctrl + C, F helps.

Yes, that's strange. @gwsw Any thoughts on the possible reason for this behaviour?

@gwsw
Copy link
Owner

gwsw commented Nov 24, 2020

In the second example you are piping a string of alphanumerics with no newlines into less. In other words, the file is one infinitely long line. Less doesn't handle a case like that well; it expects lines to be separated by newlines.

@gwsw
Copy link
Owner

gwsw commented Dec 1, 2020

As of 5bf862f, you should be able to exit F mode with control-X, in environments where poll() is supported.

@aleclearmind
Copy link

Nice!

So Ctrl + X interrupts following, right?
This is helpful under certain circumstances, but I've to say that it doesn't help me with the most annoying issue I have: when you're at the end of the stream and you just want to be able to press arrow up and scroll up. Before, I had to press Ctrl + C to kill an (already dead) process, now I can press Ctrl + X, but it's not a real improvement in usability.

Since we use poll, adding this extra feature would be great.

@gwsw
Copy link
Owner

gwsw commented Dec 1, 2020

The original request in this issue was to provide a way to exit F mode without terminating other processes in a pipe, which the ^X achieves. It sounds like you're asking for something different, or further, which is to avoid the need to enter a special interrupt character at all, but just allow any keypress to interrupt the read, and then get interpreted as a command. Am I understanding correctly? So your idea would just save one keypress in this situation?

@aleclearmind
Copy link

Yes, but my idea would be was to do this only once we can detect that the input pipe is closed.
But, yes, I guess that interrupting follow mode on any key press, no matter the status of the input pipe, would work too, despite being a bit more of a radical approach.

@gwsw
Copy link
Owner

gwsw commented Dec 2, 2020

Ok, I understand what you are saying and I agree. I will continue discussion in #6.

@gwsw gwsw closed this as completed Dec 2, 2020
@jarnos
Copy link

jarnos commented Dec 3, 2020

Does this help to solve #62? Why not use q as shortcut?

@gwsw
Copy link
Owner

gwsw commented Dec 3, 2020

The technique used to solve #49 might be usable to solve #62, but the current implementation does not solve #62, so I am reopening that issue.

I prefer to use ^X rather than q to exit follow mode because of the potential for accidentally quitting less. If you're in follow mode and you press q to exit, and the screen does not refresh immediately because of system load or network lag, you might hit q again, and then find that you've unexpectedly exited less when both q's are processed.

@calestyo
Copy link

calestyo commented Jan 6, 2021

What happens with the stdout from the pipe once F mode is left? Is it buffered? And can one resume F mode (and then get the output that happened in the meantime)?

@simnalamburt
Copy link

@calestyo It is buffered and you get output that happened in the meantime :)

@piotr-dobrogost
Copy link

@calestyo It's buffered until it's not due to the limited size of pipe's buffer – see How big is the pipe buffer?

@Hubro
Copy link
Author

Hubro commented Jul 26, 2022

@gwsw Sorry for bothering you, I was just wondering which release this feature (^X) was released in? 🙂 I'm on Arch Linux with less 590, and I noticed that ^X doesn't seem to work.

@tbussmann
Copy link

According to

less/NEWS

Line 114 in 22e4af5

* F command can be interrupted by ^X.
this should have been released in 581 - maybe you don't get HAVE_POLL set in configure in your environment?

@gwsw
Copy link
Owner

gwsw commented Jul 26, 2022

Yes, ^X should be supported in less-590, but it requires the OS to support poll(). If you built less yourself, you can check the definition of HAVE_POLL in defines.h to see whether less thinks the OS has poll(). If HAVE_POLL is set, another more disturbing possibility is that the OS supports poll() but it doesn't work correctly. This is the case in MacOS. I don't know much about Arch Linux so I don't know what support there is for poll().

@Hubro
Copy link
Author

Hubro commented Jul 26, 2022

I tried building from the latest master branch.

defines.h includes:

/* Define to 1 if you have the `poll' function. */
#define HAVE_POLL 1

Pressing Ctrl+X still has no effect. I tried this in both Alacritty and xfce4-terminal, to rule out any terminal emulator keybindings eating the Ctrl+X.

I'm testing with this command:

$ tail -c +0 -f defines.h | ./less

When I press Ctrl+X, nothing happens. Does this work for you?

@gwsw
Copy link
Owner

gwsw commented Aug 16, 2022

You are correct that this does not work. Less checks for a ctrl-X keypress just before each read() from the input file. While less is stuck in a blocked read, it cannot see any keys from the terminal. So a case like this would work

i=1; while :; do echo $i; sleep .1; let i=$i+1; done | less

But if the pipe is producing no data ctrl-X won't work.

I think fixing this would require using poll() on the input pipe before each read to confirm that there is data ready to be read. I've done a little work on this but it's not trivial (in particular I haven't found a good way to detect EOF if I'm avoiding calling read() when there is no data available). Meanwhile I am reopening this issue.

@gwsw gwsw reopened this Aug 16, 2022
@gwsw
Copy link
Owner

gwsw commented Nov 29, 2022

This should be fixed in less-614.

@olfway
Copy link

olfway commented Nov 29, 2022

Should it work on MacOS?

@gwsw
Copy link
Owner

gwsw commented Nov 30, 2022

No, less uses poll() to detect when the ctrl-X key is pressed, but unfortunately poll does not work on /dev/tty on MacOS. In a5bdb60 the "waiting for data" prompt will indicate whether it's supported on a particular system.

@gwsw
Copy link
Owner

gwsw commented Dec 10, 2022

It appears that the MacOS poll() bug has been fixed in newer releases (Big Sur seems to work for me), so as of fe1526f (less-617), ctrl-X will work on MacOS if the first component of uname -r is 20 or greater.

@Hubro
Copy link
Author

Hubro commented Dec 12, 2022

This seems to work perfectly! 🚀 Awesome job!

Now I just need to wait for this version to drop in Arch linux, which is currently on 608 😄

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

No branches or pull requests

9 participants