Git sh.exe process forking issue on windows XP, slow? Git sh.exe process forking issue on windows XP, slow? bash bash

Git sh.exe process forking issue on windows XP, slow?


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\]#$ '


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.


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+0xc0antoskrnl.exe!KeAcquireSpinLockAtDpcLevel+0x732ntoskrnl.exe!KeWaitForMutexObject+0x19fntoskrnl.exe!FsRtlCancellableWaitForMultipleObjects+0x5entoskrnl.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.