* [PATCH] git-gui: drain the cat-file pipe before closing it
@ 2026-09-03 16:17 chib via GitGitGadget
2026-09-03 17:49 ` Johannes Sixt
0 siblings, 1 reply; 2+ messages in thread
From: chib via GitGitGadget @ 2026-09-03 16:17 UTC (permalink / raw)
To: git; +Cc: chib, Johannes Sixt, chib
From: chib <chib@foxmail.com>
commit_committree opens "git cat-file commit <parent>" to read the tree
line for the empty-commit check, reads only the first line, and then
closes the pipe while the rest of the commit object (often several
kilobytes of commit message) is still unread.
On Linux this is harmless: the child process dies of SIGPIPE when it
keeps writing, and that is not reported as an error when the pipe is
closed. On Windows there is no SIGPIPE: the native git.exe gets a
broken-pipe error when writing and exits with a non-zero status. Tcl's
[close] then surfaces that as "child process exited abnormally", the
commit is aborted, and the index lock is released with nothing
committed. The failure only shows up once the parent commit's object is
larger than the pipe buffer: in testing with Git for Windows 2.52,
objects up to ~6.5 KiB always succeed while objects of ~9 KiB and up
fail 10 out of 10 times (the threshold is around the 8 KiB pipe
buffer). Amending a commit with a long message therefore triggers it
reliably while short commits slip through. Reading the pipe to EOF
before closing fixes it 10 out of 10 times, and is harmless on POSIX
platforms where the same test succeeds either way.
Read the rest of the pipe before closing it, mirroring what the amend
path already does when loading the parent commit's message.
Signed-off-by: chib <chib@foxmail.com>
---
git-gui: drain the cat-file pipe before closing it
commit_committree opens "git cat-file commit " to read the tree line for
the empty-commit check, reads only the first line, and then closes the
pipe while the rest of the commit object (often several kilobytes of
commit message) is still unread.
On Linux this is harmless: the child process dies of SIGPIPE when it
keeps writing, and that is not reported as an error when the pipe is
closed. On Windows there is no SIGPIPE: the native git.exe gets a
broken-pipe error when writing and exits with a non-zero status. Tcl's
[close] then surfaces that as "child process exited abnormally", the
commit is aborted, and the index lock is released with nothing
committed. The failure only shows up once the parent commit's object is
larger than the pipe buffer: in testing with Git for Windows 2.52,
objects up to ~6.5 KiB always succeed while objects of ~9 KiB and up
fail 10 out of 10 times (the threshold is around the 8 KiB pipe buffer).
Amending a commit with a long message therefore triggers it reliably
while short commits slip through. Reading the pipe to EOF before closing
fixes it 10 out of 10 times, and is harmless on POSIX platforms where
the same test succeeds either way.
Read the rest of the pipe before closing it, mirroring what the amend
path already does when loading the parent commit's message.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2216%2F1dao%2Fgui-drain-catfile-pipe-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2216/1dao/gui-drain-catfile-pipe-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/2216
lib/commit.tcl | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/commit.tcl b/lib/commit.tcl
index 89eb8c7b73..5e5f879f0e 100644
--- a/lib/commit.tcl
+++ b/lib/commit.tcl
@@ -386,6 +386,10 @@ proc commit_committree {fd_wt curHEAD msg_p} {
set fd_ot [git_read [list cat-file commit $PARENT]]
fconfigure $fd_ot -encoding iso8859-1
set old_tree [gets $fd_ot]
+ # Drain the pipe before closing it: on Windows, closing it
+ # while git cat-file still has output to write makes the
+ # child process exit with a failure status.
+ read $fd_ot
close $fd_ot
if {[string equal -length 5 {tree } $old_tree]
base-commit: 5dcb97869546d600a114ef422a135e2e909c923c
--
gitgitgadget
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] git-gui: drain the cat-file pipe before closing it
2026-09-03 16:17 [PATCH] git-gui: drain the cat-file pipe before closing it chib via GitGitGadget
@ 2026-09-03 17:49 ` Johannes Sixt
0 siblings, 0 replies; 2+ messages in thread
From: Johannes Sixt @ 2026-09-03 17:49 UTC (permalink / raw)
To: chib; +Cc: chib via GitGitGadget, git
Am 03.09.26 um 18:17 schrieb chib via GitGitGadget:
> From: chib <chib@foxmail.com>
>
> commit_committree opens "git cat-file commit <parent>" to read the tree
> line for the empty-commit check, reads only the first line, and then
> closes the pipe while the rest of the commit object (often several
> kilobytes of commit message) is still unread.
>
> On Linux this is harmless: the child process dies of SIGPIPE when it
> keeps writing, and that is not reported as an error when the pipe is
> closed. On Windows there is no SIGPIPE: the native git.exe gets a
> broken-pipe error when writing and exits with a non-zero status. Tcl's
> [close] then surfaces that as "child process exited abnormally", the
> commit is aborted, and the index lock is released with nothing
> committed. The failure only shows up once the parent commit's object is
> larger than the pipe buffer: in testing with Git for Windows 2.52,
> objects up to ~6.5 KiB always succeed while objects of ~9 KiB and up
> fail 10 out of 10 times (the threshold is around the 8 KiB pipe
> buffer). Amending a commit with a long message therefore triggers it
> reliably while short commits slip through.
Nicely analyzed. While this all sounds sensible, I am unable to
reproduce the failure on Windows. (But I use my own build, not Git for
Windows.) I made a tiny change, then inserted a lot of text in the
commit message field (18k), and committed. Then I clicked "Amend Last
Commit", changed the commit message slightly, and committed again. No
error. Do you have instructions how to reproduce the failure?
> Reading the pipe to EOF
> before closing fixes it 10 out of 10 times, and is harmless on POSIX
> platforms where the same test succeeds either way.
>
> Read the rest of the pipe before closing it, mirroring what the amend
> path already does when loading the parent commit's message.
You can't compare this case with the "amend" case, because "amend" needs
the commit message. The usual way to stop that 'close' complains is to
wrap it in a 'catch'.
> Signed-off-by: chib <chib@foxmail.com>
Please use your full name as author and to sign off, not a nick name.
-- Hannes
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-03 18:36 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-03 16:17 [PATCH] git-gui: drain the cat-file pipe before closing it chib via GitGitGadget
2026-09-03 17:49 ` Johannes Sixt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox