镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Pipeline hangs forever: external command blocks in fhandler_pipe_fifo::raw_write waiting on pipe_mtx after the reader exits #6502

Open

Description

@rbodarve

Setup

  • Which version of Git for Windows are you using? git version 2.54.0.windows.1, 64-bit
  • msys2-runtime: 3.6.7-4 (from /etc/package-versions.txt), commit fb42d71358dd896ab324c52970f7d03f9ab0dfe5
  • msys-2.0.dll SHA-256: 13f0b0dc94588766ecfa1867f1a00061508ba1dc62f5b8e858ac59f01e358aa0 (.gnu_debuglink msys-2.0.dbg, CRC32 0x23a6d10d; matching .dbg from msys2-runtime-devel-3.6.7-4-x86_64.pkg.tar.xz)
  • Windows: Windows 11 Home 10.0.26200, 64-bit, 4 cores
  • Options: defaults. Git Bash (C:\Program Files\Git\usr\bin\bash.exe), no terminal involved (the commands ran non-interactively).

Details

Minimal reproducer (run it a few times):

timeout 20 bash -c '{ echo a; /usr/bin/echo x; echo a; /usr/bin/echo x; } | true'; echo "rc=$?"

Observed:

  • Hangs 10/10 runs (killed by timeout, rc 124). Without timeout it never returns.
  • Each run prints bash: line 1: echo: write error: Permission denied: the builtin echo gets EACCES, not EPIPE.
  • With a delay first, so that the reader is gone before any write, it hangs 0/10:
    { sleep 1; echo a; /usr/bin/echo x; echo a; /usr/bin/echo x; } | true
  • Control: { sleep 1; /usr/bin/echo x; } | true → the writer dies with SIGPIPE (rc 141), 3/3.

Expected: each writer gets EPIPE/SIGPIPE once the reader (true) has exited, and the pipeline finishes, as on Linux.

Real-world trigger: for f in dir/*/file.json; do echo "$f"; grep -c … "$f"; file "$f"; done | head -20 never finished once head exited (more than 20 lines of output). The loop mixes builtin echo with external commands, like the reproducer.

Where it hangs

Full memory dump of the hung /usr/bin/echo x (taken with ProcDump), symbolized with the matching msys-2.0.dbg. Main thread:

WaitForMultipleObjects
cygwait
fhandler_pipe_fifo::raw_write+0x6d
write
_write_r
__sflush_r
_fclose_r
_sigbe / pthread_mutex_unlock
__call_exitprocs
exit
cygwin_exit

The signal thread (wait_sig) is in ReadFile, as normal.

winsup/cygwin/fhandler/pipe.cc at fb42d713, lines 464–467:

  if (pipe_mtx) /* pipe_mtx is NULL in the fifo case */
    {
      DWORD timeout = is_nonblocking () ? 0 : INFINITE;
      DWORD waitret = cygwait (pipe_mtx, timeout);

So the process blocks with no time limit while it acquires pipe_mtx during the exit-time flush of stdout. The process never gets to the NtWriteFile that would return STATUS_PIPE_CLOSED and raise SIGPIPE.

What I could not establish: which thread owns pipe_mtx. The holder must be alive, because an abandoned mutex would make cygwait return an error instead of blocking. The candidates are the other live processes of the pipeline (the bash subshell that ran the builtin echo a, and the parent bash). I could not read the mutex owner from user mode. One possibly relevant detail: raise (SIGPIPE) at lines 538 and 703 runs while pipe_mtx is still held (it is released later at 721/730). I have not confirmed that this is the cause.

The dump (~22 MB) is available on request.

Possibly related: msys2/msys2-runtime#202, https://inbox.sourceware.org/cygwin-patches/87edcqgfwc.fsf@/T/

Did you check the latest release?

Yes. After upgrading to git version 2.55.0.windows.5 (msys2-runtime 3.6.10-1, msys-2.0.dll SHA-256 e55be2d89f2756f540a8f2acf18cd14bf275d1187a32d5189946ee5c896bcf03), the reproducer still hangs 10/10 and still prints echo: write error: Permission denied. winsup/cygwin/fhandler/pipe.cc on main of git-for-windows/msys2-runtime is identical to the fb42d713 version quoted above. The dump and stack above are from 2.54.0.windows.1.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions