Windows XP 上的 Git sh.exe 进程分叉问题,速度慢?

发布于 2024-11-04 06:40:07 字数 1699 浏览 6 评论 0原文

Git 对我的工作流程至关重要。我在具有 3GB RAM 的四核计算机上运行 Windows XP 上的 MSYS Git,通常它反应灵敏且快速。

突然出现了一个问题,从 Git Bash 命令提示符运行任何命令(包括 lscd)都需要超过 30 秒的时间。有趣的是,从 bash 提示符来看,ls 运行得相当快,然后我可以看到 ls 的输出,但提示符返回需要大约 30 秒。如果我切换到 Windows 命令提示符(通过从开始菜单运行 cmd),git 相关命令也需要很长时间,即使只是运行。例如,git status 可能需要近一分钟的时间才会发生任何事情。有时这些过程根本就没有完成。

请注意,我安装了“MSYS Git”以及用于 MinGWmake 等内容的常规“MSYS”。

我相信该问题与位于 C:\Program Files\Git\bin 中的 sh.exe 有关。当我从 bash 提示符运行 ls 或从 Windows 提示符调用 git 时,任务管理器最多显示四个 sh.exe 实例> 来来去去的流程。

在这里,我等待 ls 返回,您可以看到任务管理器正在运行 git.exe 和四个 sh.exe 实例: 在这里我等待 ls 返回,您可以看到任务管理器正在运行 git.exe 和四个 sh.exe 实例

如果我在 ls 中间使用 ctrl-c,有时会收到错误,其中包括:

sh.exe": fork: Resource temporarily unavailable
      0 [main] sh.exe" 1624 proc_subproc: Couldn't duplicate my handle<0x6FC> fo
r pid 6052, Win32 error 5
sh.exe": fork: Resource temporarily unavailable

或者对于 git status: $ git status

sh.exe": fork: Resource temporarily unavailable
sh.exe": fork: Resource temporarily unavailable
sh.exe": fork: Resource temporarily unavailable
sh.exe": fork: Resource temporarily unavailable

我可以解决这个问题,以便 git 再次快速运行吗?如果是的话,怎么办?

我尝试过的事情:

  • 重新启动
  • 将 MSYS Git 升级到最新版本 &重新启动
  • 将MSYS升级到最新版本&重新启动
  • 卸载MSYS &单独卸载并重新安装 MSYS Git &重新启动

我非常希望不擦除我的盒子并重新安装 Windows,但如果我无法解决此问题,我会这样做。如果运行 git statuscd 需要超过 30 秒,我就无法再编码。

Git is essential to my workflow. I run MSYS Git on Windows XP on my quad core machine with 3GB of RAM, and normally it is responsive and zippy.

Suddenly an issue has cropped up whereby it takes >30 seconds to run any command from the Git Bash command prompt, including ls or cd. Interestingly, from the bash prompt it looks likes ls runs fairly quickly, I can then see the output from ls, but it then takes ~30 seconds for the prompt to return. If I switch to the windows command prompt (by running cmd from the start menu) git related commands also take forever, even just to run. For example git status can take close to a minute before anything happens. Sometimes the processes simply don't finish.

Note that I have "MSYS Git" installed as well as regular "MSYS" for things like MinGW and make.

I believe the problem is related to sh.exe located in C:\Program Files\Git\bin. When I run ls from the bash prompt, or when I invoke git from the windows prompt, task manager shows up to four instances of sh.exe processes that come and go.

Here I am waiting for ls to return and you can see the task manager has git.exe running and four instances of sh.exe:
Here I am waiting for ls to return and you can see the task manager has git.exe running and four instances of sh.exe

If I ctrl-c in the middle of an ls I sometimes get errors that include:

sh.exe": fork: Resource temporarily unavailable
      0 [main] sh.exe" 1624 proc_subproc: Couldn't duplicate my handle<0x6FC> fo
r pid 6052, Win32 error 5
sh.exe": fork: Resource temporarily unavailable

Or for git status:
$ git status

sh.exe": fork: Resource temporarily unavailable
sh.exe": fork: Resource temporarily unavailable
sh.exe": fork: Resource temporarily unavailable
sh.exe": fork: Resource temporarily unavailable

Can I fix this so that git runs quickly again, and if so how?

Things I have tried:

  • Reboot
  • Upgrade MSYS Git to most recent version & Reboot
  • Upgrade MSYS to most recent version & Reboot
  • Uninstall MSYS & uninstall and reinstall MSYS Git alone & Reboot

I'd very much like to not wipe my box and reinstall Windows, but I will if I can't get this fixed. I can no longer code if it takes me >30 s to run git status or cd.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

ゞ记忆︶ㄣ 2024-11-11 06:40:07

通常,当一个程序需要 30 秒来完成一些应该是瞬时的事情时,这更有可能是 I/O 超时问题(通常是网络问题),而不是 CPU 的速度或 RAM 的数量。您可能想知道网络是如何参与的,但这是一个合理的问题(我也不知道您的系统)。

Msysgit 安装一个特殊的提示符,该提示符运行一个特殊的函数 __git_ps1,该函数在提示符中显示一些有用的信息。您可以使用 echo $PS1 看到这一点,对于我的系统,这显示:

$ echo $PS1
\[\033]0;$MSYSTEM:\w\007 \033[32m\]\u@\h \[\033[33m\w$(__git_ps1)\033[0m\] $

此额外信息是完全可选的,您可以将其关闭。因此,请在 Msysgit 窗口中尝试以下操作:

$ PS1='$ '
$

这会将提示符重置为默认的 $ 并且不会尝试在提示符内运行 和 命令。如果这解决了您的延迟问题,那么它很可能是 __git_ps1 函数。尝试手动运行它:

$ __git_ps1
 (master)

看看需要多长时间才能返回。

您可以通过从 C:\Program Files\Git\etc\profile 中删除调用 __git_ps1 的行来解决此问题:

#Comment the lines below
#PS1='\[\033]0;$MSYSTEM:\w\007
#\033[32m\]\u@\h \[\033[33m\w$(__git_ps1)\033[0m\]
#$ '

Usually when a program takes 30 seconds to do something that should be instantaneous, it's more likely to be an I/O timeout problem, usually network, rather than the speed of your CPU or the amount of RAM you have. You may wonder how the network is involved, but that's a legitimate question (I wouldn't know for your system either).

Msysgit installs a special prompt that runs a special function __git_ps1 that shows some useful information in the prompt. You can see this using echo $PS1, for my system this shows:

$ echo $PS1
\[\033]0;$MSYSTEM:\w\007 \033[32m\]\u@\h \[\033[33m\w$(__git_ps1)\033[0m\] $

This extra information is totally optional and you can turn it off. So try the following in an Msysgit window:

$ PS1='$ '
$

This will reset the prompt to the default $ and not try to run and commands inside the prompt. If this solves your delay problem, then it's likely to be the __git_ps1 function. Try running it manually:

$ __git_ps1
 (master)

and see how long it takes to return.

You can fix this by removing the line that invokes __git_ps1 from C:\Program Files\Git\etc\profile:

#Comment the lines below
#PS1='\[\033]0;$MSYSTEM:\w\007
#\033[32m\]\u@\h \[\033[33m\w$(__git_ps1)\033[0m\]
#$ '
森林很绿却致人迷途 2024-11-11 06:40:07

所以我们也遇到了这个问题,我想我们最终将其追溯到 msys 对 Windows 安全模型的实现。我将尝试发布问题的简短摘要:

屏幕截图:
卡住的 sh.exe 的堆栈跟踪。请注意,当 msys-1.0.dll 调用 NetServerEnum() 时,

这就是 sh.exe 被阻止 30 秒时发生的情况。因此 NetServerEnum() 仅在 msys 中的一个地方被调用,security.cc:228get_lsa_srv_inf() 中,由 get_logon_server() 调用和 get_logon_server_and_user_domain(),它在 create_token() 中调用,它由 syscalls.cc 中的 seteuid() 调用,它由setuid()

所以本质上发生的事情是,当 msys DLL 初始化并且 sh.exe 尝试调用 setuid() 时,msys 尝试忠实地遵守 Windows 安全模型并尝试查找域服务器列表来自您的域/工作组。不幸的是,与 Linux 不同,对于 Windows 来说,这是一个阻塞调用,需要 5-30 秒才能完成/超时,而对于 git 来说实际上是不必要的。

我们的解决方案是通过设置 winsup.cc 中的 has_security 为 false。 msysgit 附带的 bash/sh.exe 与我们的新版本 msys.dll 不兼容,因此我们也必须从头开始编译一个新的 bash.exe,不知道为什么。最终结果是 sh.exe 不再尝试进行这些 NetServerEnum 调用并运行 lickity split。

So we ran into this issue too, and I think we finally traced it down to msys's implementation of the Windows security model. I'll try to post a short summary of the issue:

Screenshot:
Stack trace of stuck sh.exe. Note when msys-1.0.dll calls into NetServerEnum()

This is what's going on when sh.exe is blocked for 30 seconds. So NetServerEnum() is only called in msys in one place, security.cc:228 in get_lsa_srv_inf(), which is called by get_logon_server() and get_logon_server_and_user_domain(), which is called in create_token(), which is called by seteuid() in syscalls.cc, which is called by setuid().

So essentially whats happening is that when the msys DLL is initialized and sh.exe tries to call setuid(), msys tries to faithfully abide by the Windows security model and tries to look up the list of domain servers from your domain/workgroup. Unfortunately unlike linux, for Windows this is a blocking call that takes 5-30 seconds to complete/timeout, and is actually rather unnecessary for well, git.

Our solution is to create new msys.dll with the security "feature" disabled by setting has_security to false in winsup.cc. The bash/sh.exe that came with msysgit wasn't compatible with our new version of msys.dll, so we had to compile a new bash.exe from scratch too, no idea why. The end result was sh.exe no longer tries to make these NetServerEnum calls and runs lickity split.

久隐师 2024-11-11 06:40:07

如果同时运行多个 Git 命令时出现速度减慢,则可能是由于 msysgit 中的内核锁定问题造成的。

我们发现,在某些情况下,git.exe 的多个实例都会等待同一个内核对象(在 WaitForSingleObject 中) ()),实际上意味着一次只能在系统上运行一个 git 命令。

请参阅此处:10 git.exe processs all waiting on a single kernel object

使用 ProcessExplorer,我们可以看到所有 git.exe进程卡在这里:

ntoskrnl.exe!KeWaitForMultipleObjects+0xc0a
ntoskrnl.exe!KeAcquireSpinLockAtDpcLevel+0x732
ntoskrnl.exe!KeWaitForMutexObject+0x19f
ntoskrnl.exe!FsRtlCancellableWaitForMultipleObjects+0x5e
ntoskrnl.exe!FsRtlCancellableWaitForSingleObject+0x27 

这似乎与此问题有关:http://code.google.com/p/msysgit/issues/detail?id=320 因为它不是 Git,而是伪 Linux 运行时 (mingw) 似乎包含问题。

我们将用于运行应用程序的用户帐户从 SYSTEM 更改为交互式用户帐户,并且内核对象等待消失了:

健康的 git.exe 进程 git.exe 进程愉快地生成

因此,您看到的速度减慢可能与某种内核对象争用有关 - 只有当前面的 git 命令释放了内核锁时,其他命令才能运行。

尝试更改运行 git 命令的用户帐户,看看这是否解决了问题 - 它为我们解决了问题。

If the slowdown is seen when running multiple simultaneous Git commands, it could be due to a kernel locking issue within msysgit

We saw that under some conditions, multiple instances of git.exe would all wait on the same kernel object (inside WaitForSingleObject()), effectively meaning that only a single git command could be run on the system at a time.

See here:10 git.exe processes all waiting on a single kernel object

Using ProcessExplorer, we could see all the git.exe processes were stuck here:

ntoskrnl.exe!KeWaitForMultipleObjects+0xc0a
ntoskrnl.exe!KeAcquireSpinLockAtDpcLevel+0x732
ntoskrnl.exe!KeWaitForMutexObject+0x19f
ntoskrnl.exe!FsRtlCancellableWaitForMultipleObjects+0x5e
ntoskrnl.exe!FsRtlCancellableWaitForSingleObject+0x27 

This seems to be related to this issue: http://code.google.com/p/msysgit/issues/detail?id=320 in that it's not Git but the pseudo-Linux runtime (mingw) which appears to contain the problem.

We changed the user account used to run the applications from SYSTEM to an interactive user account, and the kernel object waits went away:

Healthy git.exe processes git.exe processes spawning happily

Therefore, the slowdown you are seeing COULD be related to some kind of kernel object contention - only when the previous git command has released the kernel lock might other commands be able to run.

Try changing the user account under which you are running the git commands, and see if this solves the issue - it did for us.

莫言歌 2024-11-11 06:40:07

尽管格雷格的回答解决了即时速度问题,但我觉得它只是掩盖了问题,并没有解决问题。

我开始让 git bash 运行缓慢,并按照 Greg 描述的步骤确实确定了 __git_ps1 是罪魁祸首。

我没有修改命令提示符信息(我发现它显示的信息很有用),而是找到了一个对我有用的解决方案,在博客文章中描述:

以 a 身份登录时减慢 Git bash 的解决方案域用户

在网上搜索了一下,我发现git使用默认的home,
在我的帐户上设置为网络帐户。这表明 git 会
一直在这个目录下查找,导致延迟。

为了解决这个问题,我创建了一个本地用户环境变量,覆盖
默认值,并将其设置为 %USERPROFILE% ,它指向
c:\users[用户名]。

同样的解决方案也发布在 SO 回答类似问题上。

添加环境变量使 git 恢复到全速,并且我仍然可以获得命令行信息。

Although Greg's answer solves the immediate speed issue I felt it is only masking the problem and not solving it.

I started having git bash run slowly and following the steps Greg describes did identify __git_ps1 as being the culprit.

Rather than modifying the command prompt info (I find it useful to have the information it displays) I found a solution which worked for me, described in a blog post:

Solution to slow Git bash when logged in as a domain user

Searching the internet a bit, i found that git uses the default home,
on my account set to be a network account. This ment that git would
look in this directory all the time, causing the delay.

To fix this i created a local user environment variable, overriding
the default one, and setting it to %USERPROFILE% which points at
c:\users[username].

The same solution was also posted on SO answering a similar question.

Adding the environment variable returned git to full speed and I still get the command line information.

山田美奈子 2024-11-11 06:40:07

我在 Windows XP 机器上遇到了缓慢的进程分叉问题。有时,进程分支需要几分钟的时间。

我的解决方法是清空计算机的 TEMP 文件夹。该计算机是共享资源,多年来一直在其中积累文件。

I had slow process forking problems on a Windows XP machine. Occasionally a process fork would take minutes.

The fix for me was to empty out the computer's TEMP folder. The computer was a shared resource and had been accumulated files in there over some years.

筱果果 2024-11-11 06:40:07

如果 sh 挂起 NetServerEnum 中的枚举登录服务器,请尝试将 LOGONSERVER 环境变量设置为实际登录服务器。

If sh hangs enumerating logon servers in NetServerEnum, try setting the LOGONSERVER environment variable to the actual logon server.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文