Hierzu können Sie Kenntnisse der Mutex-Interna verwenden. Normalerweise wäre dies keine sehr gute Idee, aber es ist in Ordnung zum Debuggen.
Unter Linux mit der NPTL-Implementierung von pthreads (was jedes moderne glibc ist) können Sie das __data.__owner
Mitglied der pthread_mutex_t
Struktur untersuchen, um herauszufinden, in welchem Thread es derzeit gesperrt ist. So geht's nach dem Anhängen an den Prozess mit gdb
:
(gdb) thread 2
[Switching to thread 2 (Thread 0xb6d94b90 (LWP 22026))]#0 0xb771f424 in __kernel_vsyscall ()
(gdb) bt
#0 0xb771f424 in __kernel_vsyscall ()
#1 0xb76fec99 in __lll_lock_wait () from /lib/i686/cmov/libpthread.so.0
#2 0xb76fa0c4 in _L_lock_89 () from /lib/i686/cmov/libpthread.so.0
#3 0xb76f99f2 in pthread_mutex_lock () from /lib/i686/cmov/libpthread.so.0
#4 0x080484a6 in thread (x=0x0) at mutex_owner.c:8
#5 0xb76f84c0 in start_thread () from /lib/i686/cmov/libpthread.so.0
#6 0xb767784e in clone () from /lib/i686/cmov/libc.so.6
(gdb) up 4
#4 0x080484a6 in thread (x=0x0) at mutex_owner.c:8
8 pthread_mutex_lock(&mutex);
(gdb) print mutex.__data.__owner
$1 = 22025
(gdb)
(Ich wechsle zum hängenden Thread; mache eine Rückverfolgung, um den zu finden pthread_mutex_lock()
wechsle zum hängengebliebenen festzustellen, ob er festsitzt. Ändern Sie die Stapelrahmen, um den Namen des Mutex herauszufinden, den Sie sperren möchten. Drucken Sie dann den Besitzer dieses Mutex aus.) Dies sagt mir, dass der Thread mit der LWP ID 22025 der Schuldige ist.
Sie können dann thread find 22025
die gdb
Thread-Nummer für diesen Thread ermitteln und zu dieser wechseln.
.__data.__owner
ist eine TID. Wenn jeder Thread startet, können sie einfach ihre TID (usingtid = syscall(SYS_gettid);
) sowie ihrepthread_t
(frompthread_self()
) protokollieren lassen .stat
Datei in untersuchenproc
, und er liegt ziemlich nahe (innerhalb weniger KB) ampthread_t
Wert. :-)info threads
TIDs (.__data.__owner
) pthread-IDs zuordnen (die IDs, mit denen man in gdb arbeitet).thread find
Befehl gibt. So , nachdem das Auffindenmutex.__data.__owner
22025 ist , können Sie laufen:thread find 22025
und die Nummer des Themas in GDB erhalten: (Beispiel:Thread 29 has target id 'Thread 0x7fffdf5fe700 (LWP 22025)'
). So können Sie als nächstes mit dem Befehl zu dem Thread wechseln, der die Sperre hält:thread 29
oder einfacht 29
Ich kenne keine solche Einrichtung, daher denke ich nicht, dass Sie so leicht davonkommen werden - und es wäre wahrscheinlich nicht so informativ, wie Sie denken, wenn Sie beim Debuggen Ihres Programms helfen. So Low-Tech es auch scheinen mag, die Protokollierung ist Ihr Freund beim Debuggen dieser Dinge. Sammeln Sie Ihre eigenen kleinen Protokollierungsfunktionen. Sie müssen nicht ausgefallen sein, sie müssen nur die Arbeit beim Debuggen erledigen.
Entschuldigung für das C ++, aber so etwas wie:
void logit(const bool aquired, const char* lockname, const int linenum) { pthread_mutex_lock(&log_mutex); if (! aquired) logfile << pthread_self() << " tries lock " << lockname << " at " << linenum << endl; else logfile << pthread_self() << " has lock " << lockname << " at " << linenum << endl; pthread_mutex_unlock(&log_mutex); } void someTask() { logit(false, "some_mutex", __LINE__); pthread_mutex_lock(&some_mutex); logit(true, "some_mutex", __LINE__); // do stuff ... pthread_mutex_unlock(&some_mutex); }
Die Protokollierung ist keine perfekte Lösung, aber nichts. Normalerweise erhalten Sie das, was Sie wissen müssen.
quelle
pthread_mutex_*
Funktionen mit etwas, das die Funktionsaufrufe, die Mutex-Adresse und eine Thread-ID protokolliert (pthread_t
zufällig ein integraler Typ unter Linux, keine tragbare Annahme, aber eine ziemliche Bequemlichkeit).malloc
ist es an bestimmten Stellen nicht sicher - zum Beispiel in Signalhandlern, Atfork-Handlern, zwischen Fork und Exec in einem Multithread-Programm usw. Siehe Async-Signal-Sicherheit und die anderen Manpages.Normalerweise werden libc / platform-Aufrufe von der OS-Abstraktionsschicht abstrahiert. Die toten Mutex-Sperren können mithilfe einer Eigentümervariablen und pthread_mutex_timedlock verfolgt werden. Immer wenn der Thread gesperrt wird, sollte er die Variable mit der eigenen tid (gettid () aktualisieren und kann auch eine andere Variable für die Speicherung der pthread-ID haben). Wenn also die anderen Threads blockieren und das Zeitlimit für pthread_mutex_timedlock überschritten wird, kann der Wert von Eigentümer tid und pthread_id gedruckt werden. Auf diese Weise können Sie den Eigentümer-Thread leicht herausfinden. Bitte finden Sie das Code-Snippet unten. Beachten Sie, dass nicht alle Fehlerbedingungen behandelt werden
pid_t ownerTid; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; class TimedMutex { public: TimedMutex() { struct timespec abs_time; while(1) { clock_gettime(CLOCK_MONOTONIC, &abs_time); abs_time.tv_sec += 10; if(pthread_mutex_timedlock(&mutex,&abs_time) == ETIMEDOUT) { log("Lock held by thread=%d for more than 10 secs",ownerTid); continue; } ownerTid = gettid(); } } ~TimedMutex() { pthread_mutex_unlock(&mutex); } };
Es gibt andere Möglichkeiten, um tote Sperren herauszufinden. Vielleicht hilft dieser Link http://yusufonlinux.blogspot.in/2010/11/debugging-core-using-gdb.html .
quelle
Bitte lesen Sie den folgenden Link. Dies ist eine generische Lösung, um den Schlossbesitzer zu finden. Es funktioniert auch, wenn Sie eine Bibliothek sperren und Sie nicht über den Quellcode verfügen.
https://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/Deadlocks
quelle