Łukasz C.

Łukasz C. Senior Technical
Architect

Temat: stack trace i thread safety

Witam, jaki czas temu napisalem sobie prosty kod do debugowania aplikacji ktorego zadaniem bylo sledzenie wykonywania programu i wywalenie ladnego stack trace po wyrzuceniu wyjatku, mniej wiecej cos takiego:

Fatal error in function 'void Klasa::metoda()' from [Main.cc:18]: to jest jakis komunikat o bledzie...
Stack trace:
#4: Function 'void Klasa::metoda()' from [Main.cc:17]
#3: Function 'void funkcja3()' from [Main.cc:23]
#2: Function 'void funkcja1()' from [Main.cc:33]
#1: Function 'int main(int, char**)' from [Main.cc:39]

pelny kod i opis na: http://4programmers.net/C/Artykuły/Seksowne_raportowa...

ogolnie kod dziala ale ma conajmniej kilka wad:
1 - nie jest thread safe
2 - nie nadaje sie np: do przy wylapywaniu wyjatkow wyrzucanych przed startem funkcji main (np: konstruktor zmiennej globalnej)
3 - rekurencje?

o ile pkt 2 i 3 sa mi srednio przydatne o tyle musze sie uporac z tym aby stack trace dal sie wykorzystac przy pisaniu wielowatkowych programow.

Uzywam boost::thread i mam tam miedzy innymi namespace this_thread i funkcje get_id ktora zraca id dzialajacego watku - dzieki temu moge zidentyfikowac w jakim watku siedze, pozostaje kwestia implementacji stosu:

czy probowac zrobic jeden globalny stos zabezpieczyc go mutexem i dodawac/zdejmowac kolejne trace pointy nalezace do danego watku - zlozonosc wieksza niz O(1) ?

czy przy tworzeniu watku zrobic mu wlasny stos, ewentualnie klonowac dane z watku rodzica - wiekszy narzut pamieci i czasu ale zlozonosc O(1) przy dodawaniu/zdejmowaniu trace pointow ?

czy zrobic globalna mape ze stosami dla kazdego watku - zlozonosc O(1)

no i pozostaje kwestia wyswietlania stack trace - czy wyswietlac tylko przebieg od poczatku programu poprzez jeden watek do punktu w ktorym wystapil blad, czy wyswietlac po kolei to co sie dzialo w innych watkach?

Temat: stack trace i thread safety

Po pierwsze, to niepotrzebnie robisz to recznie, stack trace da sie zazwyczaj wydlubac z pomoca funkcji systemowych/assemblera. Wracajac jednak do tego konkretnego rozwiazania, najprosciej jest trzymac stos osobno dla kazdego watku, najprosciej w TLS, bo nie trzeba zadnego kombinowania z identyfikacja watku/synchronizacja.
Co do wyswietlania, to juz jak uwazasz. Callstacki z wszystkich watkow daja na pewno nieco pelniejszy obraz.
Łukasz C.

Łukasz C. Senior Technical
Architect

Temat: stack trace i thread safety

Maciej Siniło:
Po pierwsze, to niepotrzebnie robisz to recznie, stack trace da sie zazwyczaj wydlubac z pomoca funkcji systemowych/assemblera.

chce zeby to bylo przenosne i celuje raczej w *nixa niz win :P
Artur Kęska

Artur Kęska Senior Software
Developer, XNet
Communications

Temat: stack trace i thread safety

Łukasz Cepowski:
chce zeby to bylo przenosne i celuje raczej w *nixa niz win :P

W czym będzie to lepsze od coredump'a (*nixy)? Myślisz, że jak nadpiszesz gdzieś pamięć, to Twój trace będzie podlegał jakiejś lepszej ochronie? Tak na prawdę jedynym niezawodnym rozwiązaniem jest tu pisanie na debug-output.
Na win32 korzystanie z .map daje podobne rezultaty.
Poza tym trochę niefajne jest to, że wymagasz zmiany istniejącego kodu, co w przypadku gdy mam już tony istniejących źródeł praktycznie eliminuje możliwość użycia narzędzia.
Może dało by radę jakoś to usprawnić?
Łukasz C.

Łukasz C. Senior Technical
Architect

Temat: stack trace i thread safety

Artur Kęska:
W czym będzie to lepsze od coredump'a (*nixy)? Myślisz, że jak nadpiszesz gdzieś pamięć, to Twój trace będzie podlegał jakiejś lepszej ochronie?
No chociazby w tym ze jezeli wystapi mi jakis "lekki" blad runtime ktory niekoniecznie wywroci aplikacje do gory kolami to moge uzytkownikowi wywalic informacje o bledzie + wyslac czytelny raport z przebiegiem za pomoca np: webservices.
Sprawdzilo sie w aplikacjach na webie, java to ma wiec czemu mialbym w c++ tego nie miec ;)
Poza tym trochę niefajne jest to, że wymagasz zmiany istniejącego kodu, co w przypadku gdy mam już tony istniejących źródeł praktycznie eliminuje możliwość użycia narzędzia.
Może dało by radę jakoś to usprawnić?
no wlasnie caly motyw polega na obiektach lokalnych, dlatego jest makro, nie bardzo mam pomysl jak to mozna by nieinwazyjnie zrobic, no chyba ze jakies hardkorowe wynalazki w stylu programu ktory przeleci cale drzewo ze zrodlami i doda kod debugujacy do zrodel przed kompilacja.
Google mowi ze inni takze w mniej wiecej ten sam sposob do tego podeszli...
Szymon Kubisiak

Szymon Kubisiak Developer aplikacji
mobilnych Android

Temat: stack trace i thread safety

Łukasz Cepowski:
czy probowac zrobic jeden globalny stos zabezpieczyc go mutexem i dodawac/zdejmowac kolejne trace pointy nalezace do danego watku

Nie, bo zamienisz swój program w "jednowątkowy".
czy przy tworzeniu watku zrobic mu wlasny stos, ewentualnie klonowac dane z watku rodzica - wiekszy narzut pamieci i czasu ale

Własny stos wątku wg mnie jak najbardziej, ale po co kopiować dane? Błąd w wątku jest względem wątku, najwyżej potem sobie spojrzysz do loga by zobaczyć co się działo przed jego stworzeniem.
czy zrobic globalna mape ze stosami dla kazdego watku

Nie, bo musiałbyś jakoś strzec dostępu do niej więc wracasz do rozwiązania nr 1.
no i pozostaje kwestia wyswietlania stack trace - czy wyswietlac tylko przebieg od poczatku programu poprzez jeden watek do punktu w ktorym wystapil blad, czy wyswietlac po kolei to co sie dzialo w innych watkach?

Ty jesteś programistą i tylko Ty wiesz które informacje są Ci potrzebne do zdebugowania akurat tego błędu...
Łukasz C.

Łukasz C. Senior Technical
Architect

Temat: stack trace i thread safety

Szymon Kubisiak:
Własny stos wątku wg mnie jak najbardziej, ale po co kopiować dane? Błąd w wątku jest względem wątku, najwyżej potem sobie spojrzysz do loga by zobaczyć co się działo przed jego stworzeniem.

no tak zrobilem i ogolnie dziala, chociaz kilka poprawek dojdzie, natomiast pozostaje kwestia tego upierdliwego makra :S
Janusz U.

Janusz U.
elektronik/informaty
k,
fizyk/optoelektronik

Temat: stack trace i thread safety

Polecam sprobowac z Valgindem http://valgrind.org/
Posiada "debugowanie stosu" (memcheck) a ponadto badanie wydajnosci (callgrind) i wiele innych opcji (http://valgrind.org/info/tools.html). Narazie nie znalazlem nic
lepiej spisujacego sie. Sa jeszcze biblioteki, ktore sie wkompilowuje, ale wtedy najlepiej robic kompilacje warunkowe. A tak
mamy od razu gotowe wyniki i monitoring. W przypadku przenosnego kodu polecam w 100% valgrind, a dla czysto embedded wspomniane biblioteki (podstawiaja sie pod powiedzmy malloc czy new...) oraz obserwacje z konsoli:)
Mam tylko do siebie pretensje, ze poznalem to narzedzie zbyt pozno :)

No i zapomnialbym: skoro gcc to i gdb, czy ewentualnie http://www.gnu.org/software/ddd/
Do sledzenia programow wielowatkowych trzeba uzyc zwykle zaklecia stty (opcji nie pamietam, a pisze spod windy...).

pozdrawiam
JanuszJanusz Użycki edytował(a) ten post dnia 26.07.09 o godzinie 12:49

Temat: stack trace i thread safety

Valgrind ma ta wade, ze spowalnia wykonywanie kodu, dzieki czemu niektore waskie gardla w komunikacji wielowatkowej sie poszerzaja i program dziala dobrze. Odpalisz potem taki program bez valgrinda i po tygodniu watki sie zakleszcza na mutexach.
Marek Dąbek

Marek Dąbek Software Engineer,
Intel Technology
Poland

Temat: stack trace i thread safety

Rafał Ciepiela:
Valgrind ma ta wade, ze spowalnia wykonywanie kodu, dzieki czemu niektore waskie gardla w komunikacji wielowatkowej sie poszerzaja i program dziala dobrze. Odpalisz potem taki program bez valgrinda i po tygodniu watki sie zakleszcza na mutexach.

Dlatego Valgrind nie powinien być jedyną metodą walidacji kodu. :)
Jarosław Rybski

Jarosław Rybski Programista
C/C++/Python

Temat: stack trace i thread safety

Maciej Siniło:
Po pierwsze, to niepotrzebnie robisz to recznie, stack trace da sie zazwyczaj wydlubac z pomoca funkcji systemowych/assemblera.


A właściwie to w jaki sposób można coś takiego zrobić?

konto usunięte

Temat: stack trace i thread safety

Można pójść w drugą stronę i zamiast generowania stack trace dodawać do ścieżki błędu detale:


catch( myexception &e ) {
e.addDetails("Jestem w punkcie p1a");
throw;
}


Tu masz chyba wersję thread-safe swojego narzędzia (4Windows):
http://www.drdobbs.com/184405270Piotr Likus edytował(a) ten post dnia 21.06.10 o godzinie 09:20

Temat: stack trace i thread safety

Jarosław Rybski:
Maciej Siniło:
Po pierwsze, to niepotrzebnie robisz to recznie, stack trace da sie zazwyczaj wydlubac z pomoca funkcji systemowych/assemblera.


A właściwie to w jaki sposób można coś takiego zrobić?
Zalezy od platformy. Pod Windows jest StackWalk64, na X360 podobna f-kcja. Ogolnie, na X86 wystarczy wydlubac adres z rejestru EBP i pozniej skakac dalej (przykladowe implementacje wrzucilem kiedys tutaj: http://msinilo.pl/blog/?p=269)

konto usunięte

Temat: stack trace i thread safety

*nix:
http://www.gnu.org/software/libc/manual/html_node/Back...
win:
StackWalk64() // 32/64 bit
Jarosław Rybski

Jarosław Rybski Programista
C/C++/Python

Temat: stack trace i thread safety

Jeśli możesz dołożyć do projektu makro TRACE to bardzo fajnie natomiast gorzej jeśli inni takich makr zabraniają używać w projektach.

Dokładanie danego tekstu ręcznie do każdej funkcji żeby coś w programie sprawdzić a później ich usuwanie to strata czasu.

Dobrym pomysłem jest użycie magicznego przycisku: dołącz trace do każdej funkcji, kompilacja, test oraz usuń trace z każdej funkcji.

Postanowiłem napisać wyrażenie regularne które znajduje początek funkcji.
Ale niestety - nie działa jeszcze tak jak należy.

[\w*]+[\s*]+[\w*]+[\s*]*\([\w*\s*,="]*\)\s*[{]

void f()
{
if (a){
}
else if (b)
{
}
}

Dla tego fragmentu else if (b) { traktuje jako początek funkcji.

Jak mógłbym zmodyfikować to wyrażenie aby było całkiem poprawne.
W sumie z C++ wiele wspólnego to nie ma jednak wydaje mi się że warto mieć coś takiego.

konto usunięte

Temat: stack trace i thread safety

Rafał Ciepiela:
Valgrind ma ta wade, ze spowalnia wykonywanie kodu, dzieki czemu niektore waskie gardla w komunikacji wielowatkowej sie poszerzaja i program dziala dobrze. Odpalisz potem taki program bez valgrinda i po tygodniu watki sie zakleszcza na mutexach.

Nieprawda. Do sprawdzania aplikacji wielowątkowej używa się narzędzia helgrind w połączeniu z valgridem a nie memcheck jak jest domyślnie.
Spowolnienie nie jest absolutnie wadą a wynika z warstwy abstrakcji jaką emuluje valgrind.
Helgrind umożliwia znalezienie mnóstwa błędów nawet jest one nie powodują w danym momencie problemu.
Tu jest cała lista:
http://valgrind.org/docs/manual/hg-manual.html#hg-manu...
I całość:
http://valgrind.org/docs/manual/hg-manual.html

Debugowanie wątków printfami itp nie ma sensu bo właśnie one dość mocno potrafią spowolnić program.

Następna dyskusja:

MySQL: Thread stack overrun




Wyślij zaproszenie do