Windows 版 Git 在 WSL 下泄漏进程

Windows 版 Git 在 WSL 下泄漏进程

我在 WSL2 下的 Debian 中工作,但由于我的项目文件位于 Windows 文件系统中,因此我一直通过 WSL 互操作使用 Git for Windows,其 shell 函数如下:

git() {
    case "$PWD" in
        /mnt/*)
            /mnt/c/Program\ Files/Git/bin/git.exe "$@"
            ;;
        *)
            /usr/bin/git "$@"
            ;;
    esac
}

一般来说,这种方法效果很好,而且可以快速完成工作(比 git 从 VM 内部访问 repo 中的每个文件要快得多)。

但是,我注意到,很多时候,它最终会留下杂散的 git 进程。在我的 git 命令运行完毕后,仍然有大量进程git.exe停留在那里,有时仍然持有打开的文件句柄,但实际上什么也没做。

任务管理器中正在运行的 git.exe 进程列表

它有时会导致后续 git 命令的执行速度明显变慢、工作树中的文件被阻塞,并且可能最终导致 repo 损坏。

我已经确定,这种情况大多发生在我将 git 命令的长输出通过管道传输到WSLlesshead在 WSL 中时,例如

git log | less
git log | head -n 64

并非所有管道都像这样运行 — — 例如,管道到catnano -或确实可以tail正确终止 git.exe。

是什么原因导致的?有没有办法解决?

git version 2.33.0.windows.2

答案1

这可能是由于 Windows 和 Unix 上的信号处理不同。

在 Unix 上,当管道右侧的进程(例如less)退出时,左侧的进程会收到 SIGPIPE 信号,或者,如果左侧进程阻塞了它,则在尝试再次写入管道时会收到 EPIPE 错误。通常,该信号会终止进程并阻止其产生更多输出。

但是,Windows 没有此功能或 SIGPIPE,因此进程不会终止,直到它完成写入数据或出现错误。您会注意到,不会导致进程挂起的命令会读取所有输入,而会导致进程挂起的命令则不会。

如果您要在 WSL 下使用程序,则应避免以这种方式使用 Git for Windows,因为它无法接收 SIGPIPE 并退出。

相关内容