Git für Windows unter ReactOS herunterladen

Guten Tag an alle! Bild


Mein Name ist Stanislav und ich schreibe gerne Code. Dies ist mein erster Artikel über Habré, für den mich mehrere Faktoren zum Schreiben veranlassten:



Lassen Sie mich Ihnen die Helden dieser Feier vorstellen (ein behobener Fehler, der den Start von Git in ReactOS verhinderte) - den französischen Entwickler Hermès Bélusca-Maïto (im Folgenden einfach Hermes mit dem Spitznamen hbelusca ) und mich (mit dem Spitznamen x86corez ).


Die Geschichte beginnt mit den folgenden Nachrichten des IRC-Kanals der ReactOS-Entwickler:


 Jun 03 18:52:56 <hbelusca> Anybody want to work on some small problem? If so, can someone figure out why this problem https://jira.reactos.org/browse/CORE-12931 happens on ReactOS? :D Jun 03 18:53:13 <hbelusca> That would help having a good ROS self-hosting system with git support. Jun 03 18:53:34 <hbelusca> (the git assertion part only). 

Nachbesprechung


Da ReactOS derzeit auf Kompatibilität mit Windows Server 2003 ausgerichtet ist, wurde Git Version 2.10.0 als experimentelles Kaninchen ausgewählt, das letzte , das Unterstützung für Windows XP und 2003 beansprucht.


Die Tests wurden über die ReactOS-Befehlszeile durchgeführt, die externen Symptome des Problems waren eher gemischt. Wenn Sie beispielsweise git ohne Angabe zusätzlicher Argumente starten, werden problemlos Hilfeinformationen in der Konsole angezeigt. Es hat sich jedoch gelohnt, den git clone oder zumindest die git --version . In den meisten Fällen zeigte die Konsole überhaupt nichts an oder zeigte gelegentlich eine fehlerhafte Nachricht mit der Behauptung:


 git.exe clone -v "https://github.com/minoca/os.git" "C:\Documents and Settings\Administrator\Bureau\minocaos" A ssertionfailed ! P rogram : C : \ P rogram F iles \ G it \ mingw 3 2 \ bin \ git . exe F ile : exec _ cmd . c , L ine 2 3 E xpression : argv 0 _ path This application has requested the Runtime to terminate in an unusual way. Please contact the application's support team for more information. 

Es war sehr hilfreich, das Problem zu untersuchen, dass der Git-Client Open Source war, und es war nicht schwierig, die Zeile zu finden, in der die Ausnahme auftrat: https://github.com/git-for-windows/git/blob/4cde6287b84b8f4c5ccb4062617851a2f3d7fc78/exec_cm. c # L23


 char *system_path(const char *path) { /*  */ #ifdef RUNTIME_PREFIX assert(argv0_path); //    assert(is_absolute_path(argv0_path)); /*  */ #endif strbuf_addf(&d, "%s/%s", prefix, path); return strbuf_detach(&d, NULL); } 

Der Wert der Variablen argv0_path in diesem Codeabschnitt festgelegt:


 const char *git_extract_argv0_path(const char *argv0) { const char *slash; if (!argv0 || !*argv0) return NULL; slash = find_last_dir_sep(argv0); if (slash) { argv0_path = xstrndup(argv0, slash - argv0); return slash + 1; } return argv0; } 

Nachdem ich diese Details geklärt hatte, habe ich mich im IRC-Kanal abgemeldet:


 Jun 03 19:04:36 <x86corez> hbelusca: https://github.com/git-for-windows/git/blob/4cde6287b84b8f4c5ccb4062617851a2f3d7fc78/exec_cmd.c#L23 Jun 03 19:04:41 <x86corez> assertion is here Jun 03 19:04:57 <hbelusca> yes I know, I've seen the code yesterday. The question is why it's FALSE on ROS but TRUE on Windows. Jun 03 19:06:02 <x86corez> argv0_path = xstrndup(argv0, slash - argv0); Jun 03 19:06:22 <x86corez> xstrndup returns NULL %-) Jun 03 19:06:44 <hbelusca> ok, so what's the values of argv0 and slash on windows vs. on ROS? :P Jun 03 19:08:48 <x86corez> good question! 

Der Variablenname weist sozusagen darauf hin, dass der Wert von argv[0] - normalerweise enthält der Nullindex dieses Arrays eine Zeichenfolge mit dem Namen des Befehls, mit dem das aktuelle Programm aufgerufen wurde. Aber in Zukunft war nicht alles so offensichtlich ...


 Jun 03 20:15:21 <x86corez> hbelusca: surprise... git uses its own xstrndup implementation Jun 03 20:15:35 <x86corez> so I can't simply hook it xD Jun 03 20:15:56 <hbelusca> well, with such a name "xstrndup" it's not surprising it's its own implementation Jun 03 20:16:04 <x86corez> probably I would need an user-mode debugger... like OllyDbg Jun 03 20:16:09 <hbelusca> that's everything but standardized function. Jun 03 20:16:24 <hbelusca> x86corez: ollydbg should work on ROS. Jun 03 20:16:30 <mjansen> what are you breaking today? Jun 03 20:16:44 <x86corez> mjansen: https://jira.reactos.org/browse/CORE-12931 Jun 03 20:16:51 <hbelusca> (of course if you also are able to compile that git with symbols and all the stuff, it would be very nice) 

Gehen Sie zum Handeln


Danach habe ich beschlossen, git aus der Quelle zu kompilieren, damit es einfacher ist, die Werte der interessierenden Variablen direkt in der Konsole anzuzeigen. Ich habe dieses Schritt-für-Schritt-Handbuch ausgewählt und zum Erstellen einer kompatiblen Version diesen Zweig ausgewählt: https://github.com/git-for-windows/git/tree/v2.10.0-rc2


Das Einrichten der mingw32-Toolchain verlief ohne Probleme, und ich habe mit dem Build begonnen. Aber solche Schritt-für-Schritt-Handbücher haben oft undokumentierte Fallstricke, und ich bin sofort auf eines davon gestoßen:


Bild


Durch Versuch und Irrtum sowie die Verwendung von Eingabeaufforderungen des Publikums (IRC-Kanal) wurden alle Kompilierungsprobleme behoben. Wenn jemand meinen Pfad wiederholen möchte, teile ich das fertige Diff für einen erfolgreichen Build: https://pastebin.com/ZiA9MaKt


Um den Einfluss vieler Funktionen während der Initialisierung zu eliminieren, habe ich beschlossen, mehrere Debugging-Meldungen direkt am Anfang der main() -Funktion anzuzeigen, die sich im Fall von git in der Datei common-main.c :


 int main(int argc, const char **argv) { /* * Always open file descriptors 0/1/2 to avoid clobbering files * in die(). It also avoids messing up when the pipes are dup'ed * onto stdin/stdout/stderr in the child processes we spawn. */ //DebugBreak(); printf("sanitize_stdfds(); 1\n"); sanitize_stdfds(); printf("git_setup_gettext(); 1\n"); git_setup_gettext(); /* * Always open file descriptors 0/1/2 to avoid clobbering files * in die(). It also avoids messing up when the pipes are dup'ed * onto stdin/stdout/stderr in the child processes we spawn. */ printf("sanitize_stdfds(); 2\n"); sanitize_stdfds(); printf("git_setup_gettext(); 2\n"); git_setup_gettext(); printf("before argv[0] = %s\n", argv[0]); argv[0] = git_extract_argv0_path(argv[0]); printf("after argv[0] = %s\n", argv[0]); restore_sigpipe_to_default(); printf("restore_sigpipe_to_default(); done\n"); return cmd_main(argc, argv); } 

Die Schlussfolgerung war wie folgt:


 C:\>git --version sanitize_stdfds(); 1 git_setup_gettext(); 1 sanitize_stdfds(); 2 git_setup_gettext(); 2 before argv[0] = git after argv[0] = git restore_sigpipe_to_default(); done A ssertionfailed ! ( ,    ) 

Es scheint, dass alles in Ordnung ist, argv[0] sollte so sein. Die Idee kam, git im Debugger auszuführen, zum Beispiel in OllyDbg, aber etwas ist schief gelaufen ...


 Jun 04 01:54:46 <sanchaez> now please try gdb/ollydbg in ROS Jun 04 01:58:11 <sanchaez> you have gdb in RosBE Jun 04 01:58:20 <sanchaez> just in case :p Jun 04 01:59:45 <x86corez> ollydbg says "nope" with MEMORY_MANAGEMENT bsod Jun 04 02:00:07 <x86corez> !bc 0x0000001A Jun 04 02:00:08 <hTechBot> KeBugCheck( MEMORY_MANAGEMENT ); Jun 04 02:00:13 <hbelusca> :/ Jun 04 02:00:49 <sanchaez> welp Jun 04 02:00:56 <sanchaez> you only have one option now :D 

Und hier schlug Sanchaez eine großartige Idee vor, die viel Licht ins Dunkel bringt !


Bild


Es gab keine Ausnahmen mehr und git druckte erfolgreich seine Versionsnummer.


 Jun 04 02:23:40 <x86corez> it prints! Jun 04 02:23:44 <x86corez> but only in gdb Jun 04 02:23:53 <hbelusca> oh Jun 04 02:24:00 <hbelusca> C:\git/git.exe Jun 04 02:24:13 <hbelusca> I wonder whether it's the same in windows, or not. 

Die Dinge kamen auf den Weg und ich beschloss, anders zu versuchen, Git auf der Kommandozeile auszuführen, und ich verlor nicht!


Bild


Das Problem war eindeutig, dass Git den vollständigen Pfad in der Befehlszeile erwartete. Dann habe ich beschlossen zu überprüfen, welche Daten in Windows angezeigt werden. Die Ergebnisse haben mich ein wenig überrascht.


Bild


Aus irgendeinem Grund hatte die Variable argv[0] den vollständigen Pfad zur Anwendung.


 Jun 05 23:01:44 <hbelusca> x86corez: can you try to run git also by not using cmd.exe? Jun 05 23:02:05 <hbelusca> (to exclude the possibility it's cmd that doesn't call Createprocess with a complete path) Jun 05 23:02:09 <hbelusca> while I think it should... Jun 05 23:02:30 <x86corez> not using cmd... moment Jun 05 23:02:55 <hbelusca> x86corez: alternatively, on windows, try starting git using our own cmd.exe :) 

Hermes schlug vor, zu überprüfen, ob irgendwo in der ReactOS-Befehlszeile ein Problem vorliegt ...


Bild


Das war aber nicht der Fall. Die Option cmd shell verschwindet.


 Jun 05 23:04:38 <x86corez> ROS cmd is not guilty Jun 05 23:07:57 <hbelusca> If there was a possibility to consult the received path, before looking at the contents of argvs... ? Jun 05 23:08:30 <x86corez> dump contents of actual command line? Jun 05 23:08:39 <hbelusca> yeah Jun 05 23:09:39 <hbelusca> The thing you retrieve using GetCommandLineW Jun 05 23:10:03 <hbelusca> (which is, after simplifications, basically : NtCurrentPeb()->ProcessParameters->CommandLine ) Jun 05 23:10:59 <hbelusca> Also I was thinking it could be a side-effect of having (or not having) git path into the env-vars.... Jun 05 23:12:17 <x86corez> hbelusca, command line is "git --version" Jun 05 23:12:34 <hbelusca> Always? Jun 05 23:12:39 <x86corez> Yes, even on Windows Jun 05 23:15:13 <hbelusca> ok but then it would be nice if these different results are at least the same on Windows and on ROS, so that we can 100% exclude problems outside of msvcrt. 

Jetzt musste nur noch die Bibliothek msvcrt.dll von ReactOS für Windows getestet werden. Ich habe versucht, die Datei in dasselbe Verzeichnis zu stellen, in dem git.exe lag, aber das hat nicht geholfen. Mark schlug einen Weg mit einer .local-Datei vor:


 Jun 05 22:59:01 <mjansen> x86corez: add .local file next to msvcrt.dll ;) Jun 05 22:59:47 <mjansen> exename.exe.local Jun 05 23:00:17 <x86corez> just an empty file? Jun 05 23:00:21 <mjansen> yea Jun 05 23:00:49 <hbelusca> mjansen: do we support these .local files? Jun 05 23:00:52 <mjansen> we dont Jun 05 23:00:54 <mjansen> windows does Jun 05 23:15:48 <x86corez> moment... I'll try with .local Jun 05 23:18:43 <x86corez> mjansen: I've created git.exe.local but it still doesn't load msvcrt.dll in this directory 

Aus irgendeinem Grund funktionierte diese Option jedoch auch nicht. Vielleicht hat die Tatsache, dass ich alle Experimente mit der Serverversion von Windows Server 2008 R2 durchgeführt habe, Auswirkungen.


Hermes schlug die letzte Idee vor:


 Jun 05 23:19:28 <hbelusca> last solution: patch "msvcrt" name within git and perhaps other mingwe dlls ^^ Jun 05 23:20:12 <x86corez> good idea about patching! 

Mit WinHex habe ich alle Vorkommen des msvcrt Teilstrings in der Datei msvcrt durch msvcrd und msvcrt.dll von ReactOS entsprechend umbenannt.


Bild


 Jun 05 23:23:29 <x86corez> Yes! guilty is msvcrt :) Jun 05 23:25:37 <hbelusca> ah, so as soon as git uses our msvcrt we get the problem on windows. Jun 05 23:25:38 <x86corez> hbelusca, mjansen, https://image.prntscr.com/image/FoOWnrQ4SOGMD-66DLW16Q.png Jun 05 23:25:58 <hbelusca> aha and it asserts <3 Jun 05 23:26:03 <hbelusca> (it shows the assertion now) 

Jetzt unter Windows haben wir die gleiche Fehlermeldung erhalten! Dies bedeutet, dass die Ursache des Problems die Implementierung einer der msvcrt-Funktionen von ReactOS ist.


Es ist auch zu beachten, dass unter Windows der Ausnahmetext korrekt angezeigt wird.


 Jun 05 23:26:13 <x86corez> but it prints text and correctly. Jun 05 23:26:20 <hbelusca> oh Jun 05 23:26:33 <x86corez> and on ROS it doesn't print in most cases xD Jun 05 23:26:38 <hbelusca> so also it excludes another hypothesis, namely that it could have been a bug in our msvcrt/crt Jun 05 23:26:56 <hbelusca> So possibly a strange bug in our console 

Es blieb nur herauszufinden, welche Funktion in msvcrt den vollständigen Pfad zur ausführbaren Datei der laufenden Anwendung bereitstellt. Ich googelte ein wenig und schlug vor, dass der Punkt in der Funktion _pgmptr .


 Jun 06 00:07:43 <x86corez> https://msdn.microsoft.com/en-us/library/tza1y5f7.aspx Jun 06 00:07:57 <x86corez> When a program is run from the command interpreter (Cmd.exe), _pgmptr is automatically initialized to the full path of the executable file. Jun 06 00:08:01 <x86corez> this ^^) Jun 06 00:08:50 <hbelusca> That's what GetModuleFileName does. Jun 06 00:09:04 <x86corez> yeah Jun 06 00:10:30 <hbelusca> Of course in ROS msvcrt we don't do this, but instead we initialize pgmptr to what argv[0] could be. Jun 06 00:11:08 <hbelusca> That's one thing. Jun 06 00:11:34 <hbelusca> The other thing is that nowhere it appears (in MS CRT from VS, or in wine) that argv is initialized using pgmptr. Jun 06 00:13:33 <x86corez> hbelusca, I've checked argv[0] in some ROS command line tools, running them in Windows Jun 06 00:13:56 <x86corez> they all interpret argv[0] as command line, not full path Jun 06 00:14:04 <x86corez> so... I think it's git specific behaviour Jun 06 00:14:16 <x86corez> or specific mingw compiler settings Jun 06 00:28:12 <hbelusca> x86corez: I'm making a patch for our msvcrt, would be nice if you could test it :) Jun 06 00:28:21 <x86corez> I'll test it 

Hermes hat einen Link zum Patch gesendet, ich habe ihn manuell angewendet und das System neu erstellt. Danach hat alles magisch funktioniert, wie es sollte!


Bild


 Jun 06 00:34:26 <x86corez> hbelusca, IT WORKS! Jun 06 00:35:10 <hbelusca> LOL Jun 06 00:35:18 <hbelusca> So it seems that something uses pgmptr to rebuild an argv. Jun 06 00:35:52 <x86corez> I've even able to clone :) Jun 06 00:36:19 <hbelusca> \o/ Jun 06 00:36:21 <gigaherz> 2.10.0-rc2? not the release? Jun 06 00:36:24 <hbelusca> ok I'm gonna commit that stuff. Jun 06 00:36:43 <hbelusca> x86corez: gonna have ROS self-hosting <33 Jun 06 00:36:48 <x86corez> yeah! Jun 06 00:37:01 <x86corez> gigaherz: I've built that from sources Jun 06 00:37:37 <gigaherz> oh, for testing this bug? o_O Jun 06 00:37:50 <sanchaez> yes, you missed the fun :p Jun 06 00:39:46 <x86corez> git 2.10.0-windows.1 (release) works too! Jun 06 00:39:54 <encoded> commit!!! 

Nachwort


Ein weiterer Fehler, der indirekt die Selbstorganisation von ReactOS in ReactOS behinderte, wurde durch gemeinsame Anstrengungen behoben. Ein lustiger Zufall ist die Tatsache, dass kurz zuvor ein weiterer Fehler in derselben msvcrt (nämlich in der qsort Funktion) behoben wurde, der das Zusammenstellen von USB-Treibern in ReactOS nicht ermöglichte.


Ich bin an der Entwicklung vieler Projekte beteiligt, die in verschiedenen Programmiersprachen geschrieben sind, sowohl Closed als auch Open Source. Ich arbeite seit 2014 mit dem ReactOS-Projekt, habe aber erst 2017 angefangen, aktiv zu helfen und Code zu schreiben. Es ist besonders interessant, in diesem Bereich zu arbeiten, da es sich um ein ganzes Betriebssystem handelt! Man spürt das enorme Ausmaß des Ergebnisses, in das Anstrengungen investiert wurden, sowie das angenehme Gefühl, dass ein Fehler weniger wurde! :) :)


Jemand wird sich wahrscheinlich fragen, warum ich ReactOS helfe und nicht zum Beispiel Linux. Historisch gesehen schrieb ich in den meisten Fällen Programme für Windows, und meine bevorzugte Programmiersprache ist Delphi. Vielleicht ist deshalb die Architektur von Windows NT zusammen mit der Win32-API für mich sehr interessant, und das Projekt des freien Betriebssystems ReactOS erweckt einen alten Traum zum Leben - in der Praxis können Sie herausfinden, wie alles von innen funktioniert.


Ich hoffe, Sie fanden es interessant, meinen ersten Artikel hier zu lesen. Ich freue mich auf Ihre Kommentare!


Referenzen


Source: https://habr.com/ru/post/de414947/


All Articles