Blog Kokosa

.NET i okolice, wydajność, architektura i wszystko inne

NAVIGATION - SEARCH

MemoryVisualizer - ClrMd i pierwszy issue

W rozwoju każdego oprogramowania przychodzi ten moment, że zdarza się pierwszy bug. Potem są już kolejne. No i ja mam za sobą ten etap – aż z wrażenia założyłem Issue we własnym projekcie:

Issue1

Bug czy nie bug – jak zwał tak zwał. Fakt faktem, że po ściągnięciu czystego repozytorium:

git clone https://github.com/kkokosa/MemoryVisualizer

I po uruchomieniu oraz odpaleniu Execute dostajemy:

Issue2

Problem zatem jest prosty, acz o nim zapomniałem. ClrMd wymaga odpowiedniej wersji biblioteki mscordacwks - zgodnej z tą, która działała na maszynie, z której pochodzi memory dump. W tym wypadku faktycznie sklonowałem projekt na innej maszynie, zatem mam prawo nie mieć odpowiedniej wersji biblioteki.

Tak jak pisałem w samo-założonym issue, rozwiązaniem może być dołączenie odpowiedniej wersji tej biblioteki do repozytorium. Ale lepsze będzie rozwiązanie umożliwiające samoistne ściągnięcie się tego pliku z odpowiednich serwerów Microsoftu (serwerów symboli). Sęk w tym, że API biblioteki ClrMd trochę się ciągle zmienia. Do niedawna działało coś takiego (przykład w C# ze strony ClrMd):

ClrInfo clrVersion = dataTarget.ClrVersions[0];
string dacLocation = clrVersion.TryDownloadDac("SRV*http://symweb.corp.microsoft.com", 
                                              @"c:\symcache");
dataTarget.CreateRuntime(dacLocation);

Ale teraz już nie jest tak łatwo, bo metoda TryDownloadDac zniknęła w czeluściach umysłów twórców ClrMd. Teoretycznie nowy kod teraz sam powinien ściągnąć ten plik - pierwszy rzut oka na to wskazuje. Kluczowa jest tu klasa SymbolLocator, a właściwie jej konkretna implementacja Utilities.DefaultSymbolLocator, która to taką obsługę przewiduje. Ale żeby to zadziałało, jak się okazuje - trzeba jej ustawić ścieżkę do symboli (oraz najlepiej wprost wskazać, gdzie będą one cache'owane lokalnie):

use target = DataTarget.LoadCrashDump(@"..\..\..\..\data\ConsoleDump.exe.dmp")
target.SymbolLocator.SymbolPath <- @"SRV*http://msdl.microsoft.com/download/symbols"
target.SymbolLocator.SymbolCache <- @"c:\symbols"
for version in target.ClrVersions do
    let dacInfo = version.DacInfo
    let runtime = version.CreateRuntime()

Kompilujemy, uruchamiamy i widzimy w konsoli Output radosną wiadomość:

symbols: Copying 'mscordacwks_amd64_amd64_4.6.96.00.dl_' from 'http://msdl.microsoft.com/download/symbols/mscordacwks_amd64_amd64_4.6.96.00.dll/55b96716988000/mscordacwks_amd64_amd64_4.6.96.00.dl_' to 'c:\symbols\mscordacwks_amd64_amd64_4.6.96.00.dll\55b96716988000\mscordacwks_amd64_amd64_4.6.96.00.dl_'.

I... tu zaczyna się problem. Czekamy, czekamy, czekamy... i nic się nie dzieje. Plik co prawda ściągnął się do c:\symbols ale program się zawiesił. Gdy program uruchomimy jeszcze raz, wszystko wykona się poprawnie - bo najwyraźniej wystarcza mu ściągnięta poprzednio kopia lokalna. Zatem połowiczny sukces osiągnęliśmy, jednak program nadal nie jest użyteczny.

Co się stało? O tym w kolejnej części, będzie ciekawie!

blog comments powered by Disqus