2011-06-19 11 views
16

W systemie Linux, aby uzyskać ślad wstecz, można użyć wywołania biblioteki backtrace(), ale przywraca to tylko ślad wstecz bieżącego wątku. Czy istnieje sposób na odzyskanie śladu jakiegoś innego wątku, zakładając, że wiem, że to TID (lub pthread_t) i czy mogę zagwarantować, że śpi?Uzyskanie wyniku śledzenia innego wątku

Wygląda na to, że projekt libunwind (http://www.nongnu.org/libunwind/) może pomóc. Problem polega na tym, że nie jest obsługiwany przez CentOS, więc wolę go nie używać.

Jakieś inne pomysły? Dzięki.

Odpowiedz

7

Obsługa sygnałów za pomocą śledzenia wstecznego może rozwiązać Twój cel.

Mam na myśli, jeśli masz PID wątku, możesz podnieść sygnał dla tego wątku. i w programie obsługi można użyć śledzenia wstecznego. ponieważ program obsługi byłby wykonywany w tym wątku partucularnym, ślad śledzenia byłby tym, co jest potrzebne.

+1

Nie jest to dokładnie to, czego szukałem, ale jest to niezły pomysł. Myślę, że mogę go użyć. Dzięki! –

+0

@Alexander jest rozwiązaniem dla ciebie, gdy malloc lub darmowe połączenia przypominają stos wywołań ..? i czy możesz wywołać metodę backtrace() w tym przypadku z programu obsługi sygnału? Mam awarię. – sandeep

+0

W końcu zdecydowałem się pracować z libunwind. To rozwiązanie jest zbyt skomplikowane dla moich okoliczności i postanowiłem go porzucić. W każdym razie, opublikuj tutaj, jeśli sprawisz, że zadziała jakoś. –

8

Zaimplementowałem to samodzielnie here.

Początkowo chciałem zaimplementować coś podobnego do sugestii here, tj. Uzyskać jakoś górny wskaźnik ramki wątku i odwijać go ręcznie (połączone źródło pochodzi z implementacji Jabłek backtrace, dlatego może być specyficzne dla Apple, ale pomysł jest ogólny).

Jednakże, aby mieć to bezpieczne (i powyższe źródło nie jest, a nawet może być zepsute), musisz zawiesić wątek, gdy będziesz mieć dostęp do jego stosu. Szukałem różnych sposobów zawieszenia wątku i znalazłem this,i this. Zasadniczo nie ma naprawdę dobrej drogi. Wspólnym hackiem, także used by the Hotspot JAVA VM, jest użycie sygnałów i wysłanie niestandardowego sygnału do twojego wątku poprzez pthread_kill.

Tak więc, tak jak i ja potrzebowałbym takiego hackowania sygnału, mógłbym mieć go nieco prostszego i po prostu użyć backtrace wewnątrz wywoływanego manipulatora sygnału, który jest wykonywany w docelowym wątku (jak również zasugerował here by sandeep). Jest to w zasadzie to, co robi moja implementacja.

Jeśli jesteś również zainteresowany drukowaniem śladu po śladach, to jest uzyskać przydatne informacje dotyczące debugowania (nazwa funkcji, nazwa pliku źródłowego, numer linii kodu źródłowego, ...), przeczytaj here o rozszerzonym backtrace_symbols na podstawie libbfd. Lub po prostu zobacz źródło here.

+1

Albert, mam scenariusz, w którym potrzebuję uzyskać stos wywołań głównego wątku z wątku tła. Ideą jest to, że jeśli w wątku UI zostanie zawieszony ponad 2 sekundy, wątek tła, który monitoruje wątek UI co 200 ms, będzie zbierać stos wywołań. Zastanawiam się, czy Twoje rozwiązanie może również rozwiązać ten problem? Bardzo dziękuję z góry. –

+0

@ilkerAcar: Tak, funkcja 'int GetCallstack (ThreadId threadId, void ** buffer, int size)' w mojej implementacji może być wywołana z dowolnego wątku. Wystarczy podać główny identyfikator wątku. – Albert

+0

Btw., Robię to również w niektórych projektu, zobacz 'startMainLockDetector()' [tutaj] (https://github.com/albertz/openlierox/blob/0.59/src/MainLoop.cpp). – Albert

0

gdb zapewnia tych obiektów do debugowania programów wielowątkowych:

  • automatyczne powiadamianie o nowych wątków
  • 'thread-id', polecenie, aby przełączać się między wątków
  • 'Informacje nici' komenda zapytująca o istniejące wątki:
  • 'zastosowanie wątku [lista-wątków] [all] args', polecenie zastosowania polecenia do listy wątków
  • Punkty przerwania specyficzne dla gwintów
  • "ustaw wątek wydruku zdarzeń", który steruje drukowaniem komunikatów na początku i końcu wątku.
  • 'ustaw ścieżkę libthread-db-search-path', która pozwala użytkownikowi określić, którego libthread_db użyć, jeśli domyślny wybór nie jest zgodny z programem.

Po prostu potrzebny jest wątek w GDB przez cmd: 'thread thread-id'. Następnie wykonaj "bt" w kontekście wątku, aby wydrukować ślad śledzenia wątku.

Powiązane problemy