Re: git fails with a broken pipe when one quits the pager
flat view
From: Vincent Lefevre <hidden>
Date: 2021-02-01 12:37:42
On 2021-02-01 03:33:54 -0800, Chris Torek wrote:
quoted
On 2021-01-31 21:49:49 +0100, Ævar Arnfjörð Bjarmason wrote:quoted
... That we're returning an exit code per getting a SIGHUP here is a feature. Consider: git -c core.pager=/bin/false log && echo showed you the outputThis example has a minor flaw: it should use `git -c core.pager=/bin/true`, probably.
In this case, since /bin/true doesn't read anything on purpose, I would not expect any non-zero exit status. And note that git -c core.pager="sh -c 'cat; /bin/false'" log exits with a zero exit status, which is unexpected since the pager failed. For instance, in practice, the pager could be killed by the system, but the user would not necessarily notice this as the pager may be configured to quit automatically when reaching the end of the output (there are some "less" options to do that: -E, -F). So, the user would think that he got the full output while he didn't. [...]
quoted
quoted
Not being able to write "git log" output is a real SIGPIPE.Worth noting: Linux has a pretty large pipe buffer. POSIX requires at least 4k here, as I recall, but Linux will buffer 64k or more, so that if `git log` is able to write the entire log text (will be the case for small repositories) *before* the program on the right side of the pager pipe exits (this depends on many things), the pager's exit *won't* cause a SIGPIPE. You'll get the SIGPIPE if either the pager exits very quickly, so that `git log` is unable to write much before the exit, or if the repository is sufficiently large so that the pipe blocks first.
In general, repositories have more than 64k log.
quoted
Which is not the case here, because the full output has never been requested by the user.The `git log` command *did* request the full output.
No, because the output is sent to a pager. As long as the user does not look at more than what he looks for, no more "git log" output is requested (such output can happen internally, but it is not requested by the user).
The problem that has come up is, if I understand correctly, that some Linux distributions have come with misconfigured pagers that don't bother reading their input, and silently exit zero.
They are not misconfigured. This is how they work. Actually I don't see why they should read more than needed: this would be a useless waste of memory.
This causes all kinds of Git commands to *seem* to fail. The Git commands are just fine; the bug is that the pager doesn't read or write anything. Unfortunately, the way that pipes work -- asynchronously -- means that Git really *can't* catch all problems here. But catching a SIGPIPE, whether Git itself spawned the pager or not, does indicate that something has gone wrong ... *unless* Git was piping to, e.g., less, and the user read enough, and the user typed `q` at less, and less exited without bothering to read the rest of the input. There's no good way for Git to be able to tell which of these was the case.
In the case git spawns a pager, it knows that this is a pager (as per documentation). -- Vincent Lefèvre [off-list ref] - Web: <https://www.vinc17.net/> 100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/> Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)