Git development
 help / color / mirror / Atom feed
From: "chib via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: chib <chib@foxmail.com>, Johannes Sixt <j6t@kdbg.org>,
	chib <chib@foxmail.com>
Subject: [PATCH] git-gui: drain the cat-file pipe before closing it
Date: Thu, 03 Sep 2026 16:17:42 +0000	[thread overview]
Message-ID: <pull.2216.git.1788452262806.gitgitgadget@gmail.com> (raw)

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

             reply	other threads:[~2026-09-03 16:17 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-03 16:17 chib via GitGitGadget [this message]
2026-09-03 17:49 ` [PATCH] git-gui: drain the cat-file pipe before closing it Johannes Sixt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=pull.2216.git.1788452262806.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=chib@foxmail.com \
    --cc=git@vger.kernel.org \
    --cc=j6t@kdbg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox