-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
git staTUS spawns infinite(?) amounts of child processes. #1496
Comments
@tamlin-mike was this in Git Bash or Git CMD? |
CMD, but IIRC I tested it with bash too, and it also failed. My guess is there's a strcmp() for "status" or "git-status" on argv[0], but since it's a case insensitive filesystem argv[0] could be "git-staTUS". |
@tamlin-mike how about giving the fix a shot yourself? It should be as easy as inserting some code somewhere here: https://github.com/git-for-windows/MINGW-packages/blob/7637a1c656d24a4e58dd69838b00891a34f5afc7/mingw-w64-git/git-wrapper.c#L554-L562 Either add |
@dscho Thanks for the pointer to the src. I don't think auto-correcting, even if "only" case, is an option. To be consistent with POSIX platform behavior, checking and bailing out on error seems more reasonable. I suspect the following could do, though I don't have a system set up to build git itself currently. To check:
If it turns out to solve the problem, feel free to commit it. |
Don't you worry. Should it turn out that I can take on this project, too (because you make no signs of helping me there, apart from a code snippet that is so straight-forward that I already thought of it before you wrote it down), I shall feel free to commit it, indeed. I do not even need encouragement to commit things I implement myself. 😁 |
I have given this some thought, and the "patch" it's obviously incomplete as-is. I can see two solutions:
Case mapping/switching UCS-2 (Microsoft might claim they are UTF-16, but that's just hogwash at least for the filesystem) is impossible to do reliably. Option 1 has the benefit of always working, even if there are git commands added with uppercase characters. Downside is an extra kernel call, and general ickyness. Option 2 feels "cleaner" to me, but relies on an assumption that, while I find it probable, I don't know if it can be relied upon. Iff it can, then it could be as simple as looping the input command and check for "[A-Z]" (i.e. iswupper), and bail out if anything found. |
I can't reproduce this problem:
There is already some logic in place at git.c#L641-L655 to prevent recursively calling the same executable:
|
For precision, I'm using: Microsoft Windows [Version 10.0.16299.248] @kgybels Can you verify it still works for you if you do not have I was using a slightly older version, 2.16.1.windows.4, but the code you refer to has apparently been in place for four years, so that's not the part solving it. Updating to 2.16.2.windows.1, I can still repro, whether I run "git staTUS" inside a git-managed directory or not. Both tests only performed from cmd.exe. I do not have
0xc0000017 is the NT error One possible (even if unlikely) difference is that I have both disabled (and probably cleaned all possible) 8.3 paths from the volume. From an admin command prompt, see: cmd.exe codepage ( |
@kgybels the problem occurs only when the Git wrapper is involved, i.e. when |
@kgybels to be precise, I already identified where this would need to be fixed in this comment. To be quite honest, reading over the code again I am quite surprised that An alternative would of course be to set an environment variable in the clause handling builtins, to detect recursion. The simplest I could come up with is this patch: diff --git a/mingw-w64-git/git-wrapper.c b/mingw-w64-git/git-wrapper.c
index 594f803d..07e96966 100644
--- a/mingw-w64-git/git-wrapper.c
+++ b/mingw-w64-git/git-wrapper.c
@@ -557,6 +557,10 @@ int main(void)
prefix_args_len = wcslen(buffer);
}
else if (!wcsnicmp(basename, L"git-", 4)) {
+ LPCWSTR builtin_env = L"GIT_WRAPPER_BUILTIN_NAME";
+ LPWSTR p;
+ int len;
+
needs_env_setup = 0;
/* Call a builtin */
@@ -565,6 +569,26 @@ int main(void)
if (!wcsicmp(prefix_args + prefix_args_len - 4, L".exe"))
prefix_args_len -= 4;
+ len = GetEnvironmentVariableW(builtin_env, NULL, 0);
+ if (len == prefix_args_len + 1) {
+ p = malloc(sizeof(WCHAR) * len);
+ if (!p ||
+ !GetEnvironmentVariableW(builtin_env, p, len) ||
+ !wcsnicmp(p, prefix_args, prefix_args_len)) {
+ fwprintf(stderr,
+ L"Invalid builtin name (incorrect "
+ "case?): '%.*s'\n",
+ prefix_args_len, prefix_args);
+ exit(1);
+ }
+ free(p);
+ }
+ p = malloc(sizeof(WCHAR) * (prefix_args_len + 1));
+ memcpy(p, prefix_args, sizeof(WCHAR) * prefix_args_len);
+ p[prefix_args_len] = L'\0';
+ SetEnvironmentVariableW(builtin_env, p);
+ free(p);
+
/* set the default exe module */
wcscpy(exe, exepath);
PathAppend(exe, L"git.exe"); |
@dscho @tamlin-mike Even without Here is the result without
To check the process call chain in Process Explorer, I replaced
Normally, |
Problem only happens with the portable version:
|
... or when hardlinks are not available (such as on FAT drives). What do you think about my proposed patch? |
Misspelling the commant `git status` as `GIT STATUS` will fail due to the incorrect case: `git.exe` would not think that this is a builtin, and execute the dashed `git-STATUS.exe`, which in turn would match `git-status.exe` on Windows (because case-insensitive file system), and that would be the Git wrapper, which would then call `git.exe STATUS` again. This fixes git-for-windows/git#1496. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
@dscho When not hard linking, instead of doing a copy, the wrapper is used to save disk space? If the wrapper wouldn't change the command line, then the recursion would be broken by the main git executable. Instead of the following process call chain:
It should be like:
argv[0] will become git-STATus, and the main git executable will recognize it as trying to execute a builtin, without falling back to calling git-STATus. Would this solution be possible? We could even make a purpose build executable to use as a hard link stand-in, that would just execute the target executable passing the command line unchanged. This will save even more disk space then using the current wrapper, which serves more purposes than just being a hard link substitute. Another solution would be to just remove all the
It feels like a workaround for a problem that shouldn't be there in the first place. |
@dscho I tried making a hard link stand-in executable, just calling
Even though I could see I was correctly calling I found that argv[0] is always set to the executable path in msc_startup:
The same thing happens in mingw_startup. This is very unfortunate because setting argv[0] to |
Using a command line of the form: git-<command> <arguments>, will cause git to to treat the command as a builtin, preventing git from calling an external helper. Otherwise, git could call back to the wrapper leading to an infinite mutual recursion. Fixes git-for-windows/git#1496 Signed-off-by: Kim Gybels <kgybels@infogroep.be>
Instead of basing argv[0] on the executable path, use argv[0] as provided on the command line. Setting argv[0] to git-<builtin> is currently the only way to prevent git from falling back to calling a helper executable. This change will allow the git-wrapper executable, that Git for Windows uses, to signal to git to handle the command as a builtin. Related to git-for-windows#1496 Signed-off-by: Kim Gybels <kgybels@infogroep.be>
That had been proposed, but the core Git maintainer states that a Git without those dashed forms of the builtins is not a Git.
It is as soon as
If And we cannot solve that by patching So I am afraid that even if my "ugly" solution does not meet your bar, it is the one that works... |
I never knew this issue would open up such a can of worms. :-)
That makes two of us. I would have expected the Windows module "database" to keep the canonical (on-filesystem) name. Your finding suggests it may be loading N instances of the same binary for N different casing (upper/lower).
Between a rock and a hard place, I think even an ugly solution (since it seems it may be impossible to get an elegant solution on Windows) is better than "fork-bomb". |
I think @kgybels has a point, and if we can join efforts with the "RUNTIME_PREFIX everywhere" patch series, we probably can avoid my ugly work-around. |
This change also allows us to stop overriding argv[0] with the absolute path of the executable, allowing us to preserve e.g. the case of the executable's file name. This fixes git-for-windows#1496 partially. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This change also allows us to stop overriding argv[0] with the absolute path of the executable, allowing us to preserve e.g. the case of the executable's file name. This fixes git-for-windows#1496 partially. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This change also allows us to stop overriding argv[0] with the absolute path of the executable, allowing us to preserve e.g. the case of the executable's file name. This fixes git-for-windows#1496 partially. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This change also allows us to stop overriding argv[0] with the absolute path of the executable, allowing us to preserve e.g. the case of the executable's file name. This fixes git-for-windows#1496 partially. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This change also allows us to stop overriding argv[0] with the absolute path of the executable, allowing us to preserve e.g. the case of the executable's file name. This fixes git-for-windows#1496 partially. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
@kgybels I integrated @danjacques' and my |
Oh, and of course I am reopening the issue! |
Using a command line of the form: git-<command> <arguments>, will cause git to to treat the command as a builtin, preventing git from calling an external helper. Otherwise, git could call back to the wrapper leading to an infinite mutual recursion. Fixes git-for-windows/git#1496 Signed-off-by: Kim Gybels <kgybels@infogroep.be>
You guys already did all the work that needs to be done for git itself, now only need to merge git-for-windows/MINGW-packages#23 to resolve the problem. |
Git [no longer enters an infinite loop](git-for-windows/git#1496) when misspelling `git status` as, say, `git Status`. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This change also allows us to stop overriding argv[0] with the absolute path of the executable, allowing us to preserve e.g. the case of the executable's file name. This fixes #1496 partially. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This change also allows us to stop overriding argv[0] with the absolute path of the executable, allowing us to preserve e.g. the case of the executable's file name. This fixes #1496 partially. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
It seems that I am experiencing a problem possibly related to this with Git 2.20.1.windows.1 running on Windows 10 1809 with NTFS. I left a comment on #1855 which appeared to be a possible match as well. In my case, any call to the executable Both Setting GIT_TRACE 1 has no visible output. Setting GIT_TRACE to a file starting with "/" per the code did not show any trace file created. Update: I have two systems with mostly the same software and verified the sha1 of the problematic git.exe as identical on both the working and non-working system. I will leave the other system in a broken state to investigate potential differences. Update 2: If I connect to the system with the "fork bomb" behavior via Remote Desktop git works fine and there is no "fork bomb" behavior. If I log in locally to the physical machine, the "fork bomb" behavior resumes. |
@maxxd this sounds like a very different problem you have than the one reported in this ticket. If I had to bet, I would put my money on an anti-malware going haywire. |
@dscho I agree, the common symptom is the child process bomb, but not the same executable. In the case I ran into, it was the wrapper repeatedly being executed, not the actual git executable. Going back to 2.19 resolved the issue I was experiencing, and since this was reported against 2.15/2.16 that is another difference. Additionally, I also traced the source of the problem that I experienced to a commit about 2 months ago. Specifically, line 66 of this commit of Dec 8, 2018 added the git-for-windows/MINGW-packages@521a655#diff-764b20bf126c245c501c9f87566af95cR66 So I would agree. Unrelated. I'll try the portable version on my systems and see if I can repro this one. |
@dscho I tried and was able to reproduce this with I was unable to reproduce it with So, confirmed. different issue |
@maxxd thanks for following up! |
Tested on Windows 10 64-bit, versions 2.15 and 2.16.
Mis-spell "status" as "staTUS", and it seems all POSIX platforms complain and just terminate. Windows, not so much. It spawns an insane amount of child processes, before terminating due to lack of resources.
The text was updated successfully, but these errors were encountered: