Git for Windows leaking processes under WSL
I work in Debian under WSL2, but because my project files live in the Windows filesystem, I've been using Git for Windows through the WSL interop with a shell function like this:
git() {
case "$PWD" in
/mnt/*)
/mnt/c/Program\ Files/Git/bin/git.exe "$@"
;;
*)
/usr/bin/git "$@"
;;
esac
}
Generally this works well and gets the job done quickly (much faster than git accessing every file in a repo from inside the VM).
However, I've noticed that, a lot of the time, it ends up leaving behind stray git processes. Well after my git commands have finished running, I still have a ton of git.exe
just sitting there, sometimes still holding open file handles, but not really doing anything.
It sometimes leads to significantly slower execution of subsequent git commands, files in the working tree being blocked, and, hypothetically, could eventually lead to repo corruption.
I've determined that it mostly tends to happen when I pipe long outputs of git commands to less
or head
in WSL, e.g.
git log | less
git log | head -n 64
Not all pipes behave like this - for example, piping to cat
, nano -
, or indeed tail
terminates git.exe properly.
What causes this, and is there a way to fix it?
git version 2.33.0.windows.2
This is likely due to different signal handling on Windows and Unix.
On Unix, when a process on the right side of a pipe (e.g., less
) exits, the process on the left side gets a SIGPIPE, or, if it's blocking that, an EPIPE error, when it tries to write to the pipe again. Typically that signal kills the process and prevents it from producing more output.
However, Windows doesn't have this functionality or SIGPIPE, and so the process doesn't die until it can finish writing data or it gets an error. You'll notice that the commands which don't causing hanging processes read all the input, and the ones which do cause hanging processes don't.
If you're going to work with programs under WSL, you should avoid using Git for Windows in this way because it can't receive SIGPIPE and exit.