2009-09-26 16 views
6

Mam aplikację serwera działającą pod Cent OS. Serwer odpowiada na wiele żądań na sekundę, ale wielokrotnie ulega awarii po każdej godzinie i tworzy plik zrzutu awaryjnego. Sytuacja jest naprawdę zła i muszę jak najszybciej znaleźć przyczynę wypadku.Jak analizować plik zrzutu awaryjnego przy użyciu GDB

Podejrzewam, że problem jest związany z problemem współbieżności, ale nie jestem pewien. Mam dostęp do plików kodu źródłowego i plików zrzutu awaryjnego, ale nie wiem, jak używać zrzutów awaryjnych, aby wskazać problem.

Wszelkie sugestie są mile widziane.

Odpowiedz

7

Pierwszą rzeczą, aby szukać jest komunikat o błędzie, który pojawi się, gdy awarii programu. Dzięki temu często dowiesz się, jaki błąd wystąpił. Na przykład: "Błąd segmentacji" lub "SIGSEGV" prawie na pewno oznacza, że ​​Twój program usunął odnośnik NULL lub w inny sposób nieważny. Jeśli program jest napisany w C++, to komunikat o błędzie często wskaże nazwę nieprzechwyconego wyjątku.

Jeśli nie widzisz komunikatu o błędzie, uruchom program z wiersza poleceń lub potnij jego wyniki w pliku.

Aby plik podstawowy był naprawdę przydatny, należy skompilować program bez optymalizacji i informacji o debugowaniu. GCC wymaga następujących opcji: -g -O0. (Upewnij się, że twoja kompilacja nie ma żadnych innych opcji -O.)

Gdy masz plik core, a następnie otworzyć go w gdb z:

gdb YOUR-APP COREFILE 

Rodzaj where zobaczyć miejsce, w którym wystąpiła awaria. Zasadniczo jesteś w normalnej sesji debugowania - możesz badać zmienne, poruszać się w górę iw dół stosu, przełączać się między wątkami i czymkolwiek.

Jeśli twój program się zawiesił, prawdopodobnie jest to nieprawidłowy dostęp do pamięci - musisz więc szukać wskaźnika o zerowej wartości lub wskazać źle wyglądające dane. Możesz nie znaleźć problemu na samym dole stosu, zanim znajdziesz problem, możesz przesuwać go o kilka poziomów w górę.

Powodzenia!

0

Czy twoja aplikacja tworzy plik podstawowy? Jeśli tak, użyłbym gdb do debugowania tego problemu.

9

Jeśli pojawienie się problemu zajmuje około godziny, może to być problem z pamięcią - być może skończył się lub może tratować (na przykład przy użyciu już zwolnionej pamięci).

Mówisz, że masz pliki zrzutu awaryjnego - to jest główny zrzut?

Zakładając masz zrzutu, to pierwszym krokiem powinno być prawdopodobnie wydrukować ślad stosu:

gdb program core 
> where 

ten powinien powiedzieć, gdzie program był w momencie wystąpienia awarii. To, co jeszcze jest dostępne, zależy od sposobu kompilacji serwera. Jeśli to możliwe, powinieneś dokonać rekompilacji z włączonym debugowaniem (to byłoby z flagą "-g" z GCC). Dałoby to więcej informacji ze śledzenia stosu.

Jeśli problem dotyczy pamięci, należy rozważyć uruchomienie pod numerem valgrind.

Należy również rozważyć budowę i uruchamianie z wersją debugowania malloc(). Wersja do debugowania wykryje nadużywanie pamięci, której normalne wersje tracą - lub ulegają awarii.

+0

Dziękujemy za szczegółową odpowiedź. Serwer został skompilowany z informacjami o debugowaniu i tworzy zrzut główny, gdy się zawiesza. Serwer inicjuje wiele wątków. Za każdym razem, gdy wątki są mniejsze niż 200, serwer działa dla bitów dłużej niż godzinę, ale gdy wzrost liczby żądań zwiększa liczbę wątków w puli do około 300, serwer ulega awarii znacznie wcześniej. Czy możesz mi powiedzieć, w jaki sposób może pomóc użycie debugującej wersji malloc? Dzięki –

+0

Jeśli chodzi o "debugowanie malloc": jeśli problemem jest nadużywanie pamięci, to malloc debugowania pomoże, nagrywając więcej informacji o przydzielonej przestrzeni, zwykle poprzez przydzielenie większej ilości miejsca, więc gdy jego funkcje są wywoływane, mogą wykryć różne rodzaje nadużywania pamięci na początku procesu - ograniczanie zadawanych obrażeń i zwykle ułatwiło dostrzeżenie problemu. Na przykład, jeśli uwolnisz już uwolnioną porcję pamięci, może to zgłosić - zamiast po prostu wziąć swoją wartość za darmo i pracować z informacjami, których tak naprawdę tam nie ma. Zobacz K & R dla prostej implementacji malloc(). –

+0

Odnośnie "poniżej 200 wątków OK; ponad 300 wypadków wcześniej "; czy sprawdziłeś, czy serwer przydziela pulę o stałym rozmiarze jakiegoś zasobu (może 200, może 256) i czy nie sprawdza poprawnie wyczerpania tego zasobu. Może to być zestaw muteksów lub semaforów lub coś innego, co powoduje nadużywanie pamięci. Czy kod serwera został napisany? Czy warto rozważyć ograniczenie liczby wątków w pracy? –

5
gdb -c core.file exename 
bt 

Zakładając, że exename został zbudowany z symboli debugowania (i wszystkich jego dynamiczny zależności są w drodze), który będzie Ci prześledzić wstecz. "W górę" i "W dół" przesunie Cię w górę i w dół w stosie, a p varname może zostać użyty do zbadania miejscowych i parametrów.

Można również spróbować uruchomić go pod valgrind:

valgrind --tool=memcheck --leak-check=full exename 
Powiązane problemy