Ist es möglich, den Thread zu bestimmen, der einen Mutex enthält?

Lesezeit: 2 Minuten

terrys Benutzeravatar
Frottee

Erstens verwende ich die pthread-Bibliothek, um Multithreading-C-Programme zu schreiben. Threads hängen immer an ihren gewarteten Mutexe. Wenn ich das strace-Dienstprogramm verwende, um einen Thread in der FUTEX_WAIT Status möchte ich wissen, welcher Thread diesen Mutex zu diesem Zeitpunkt enthält. Aber ich weiß nicht, wie ich das machen könnte. Gibt es irgendwelche Dienstprogramme, die das tun könnten?

Jemand hat mir gesagt, dass die Java Virtual Machine dies unterstützt, also möchte ich wissen, ob Linux diese Funktion unterstützt.

Benutzeravatar von caf
Café

Dazu können Sie Kenntnisse der Mutex-Interna nutzen. Normalerweise wäre das keine sehr gute Idee, aber zum Debuggen ist es in Ordnung.

Unter Linux mit der NPTL-Implementierung von pthreads (was jede moderne glibc ist) können Sie das untersuchen __data.__owner Mitglied von pthread_mutex_t Struktur, um den Thread herauszufinden, der ihn derzeit gesperrt hat. So geht es 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 aufgehängten Thread; mache einen Backtrace, um den zu finden pthread_mutex_lock() es ist fest; Stack-Frames ändern, um den Namen des Mutex herauszufinden, den es zu sperren versucht; geben Sie dann den Eigentümer dieses Mutex aus). Dies sagt mir, dass der Thread mit der LWP-ID 22025 der Übeltäter ist.

Sie können dann verwenden thread find 22025 um das herauszufinden gdb Thread-Nummer für diesen Thread und wechseln Sie zu ihm.

  • Gibt es eine Möglichkeit zu korrelieren Daten.__owner__ mit pthread Thread-ID? Beim Spielen habe ich einfach log << mutex.__data__.owner << endl codiert und das scheint gut zu funktionieren. Aber der data.owner ist ein Wert wie 9841, während die tid wie 140505876686608 ist. Welche Beziehung besteht zwischen den beiden Werten?

    – Ente

    19. August 2010 um 18:20 Uhr

  • @Duck: Der Wert in .__data.__owner ist eine TID. Wenn jeder Thread startet, könnten Sie ihn einfach seine TID protokollieren lassen (mithilfe von tid = syscall(SYS_gettid);) sowie ihre pthread_t (aus pthread_self()).

    – Café

    20. August 2010 um 0:09 Uhr

  • Sie können auch den Stapelzeiger des Threads in untersuchen stat Datei in procund es wird ziemlich nah (innerhalb weniger kb) von der sein pthread_t Wert. 🙂

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    29. April 2011 um 3:17 Uhr

  • BTW: Könnte man gebrauchen info threads um TIDs zuzuordnen (.__data.__owner) zu pthread-IDs (die IDs, mit denen man in gdb arbeitet).

    – Adam Romanek

    29. Mai 2014 um 7:50 Uhr

  • @caf, Sie können Ihrer Antwort hinzufügen, dass es heutzutage in gdb gibt thread find Befehl. Also nachdem ich das gefunden habe mutex.__data.__owner ist 22025 können Sie ausführen: thread find 22025 und holen Sie sich die Nummer des Threads in gdb: (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 nur t 29

    Benutzer184968

    18. Dezember 2015 um 10:36 Uhr


Ich kenne keine solche Einrichtung, also glaube ich nicht, dass Sie so leicht davonkommen werden – und es wäre wahrscheinlich nicht so informativ, wie Sie denken, wenn es darum geht, Ihr Programm zu debuggen. So einfach es auch erscheinen mag, Protokollierung ist Ihr Freund beim Debuggen dieser Dinge. Sammeln Sie Ihre eigenen kleinen Logging-Funktionen. Sie müssen nicht schick sein, sie müssen nur ihre 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 ist. Es bringt Ihnen normalerweise, was Sie wissen müssen.

  • Die Protokollierung ist in der Tat ein sehr nützliches Werkzeug zum Debuggen. Vielen Dank für Ihre Vorschläge.

    – Frottee

    14. August 2010 um 16:12 Uhr

  • +1 Wer liebt das Loggen nicht? Es könnte ohne Codeänderungen mit LD_PRELOAD (und etwas Geduld) durchgeführt werden. Wickeln pthread_mutex_* Funktionen mit etwas, das die Funktionsaufrufe, die Adresse des Mutex und eine Thread-ID (pthread_t zufällig ein integraler Typ unter Linux, keine tragbare Annahme, aber eine ziemliche Bequemlichkeit).

    – Pilkrähe

    15. August 2010 um 14:25 Uhr

  • Ein mögliches Problem bei der Protokollierung besteht darin, dass es das Timing stören und das Problem verschwinden lassen könnte.

    – Spudd86

    25. November 2010 um 18:39 Uhr

  • Außerdem können Sie Bibliotheksfunktionen nicht immer/vorhersehbar zwischenschalten. Es ist keine Garantie.

    – Matt Tischler

    3. Juli 2012 um 21:06 Uhr

  • Die Protokollierung ist sehr nützlich. Es gibt jedoch einige Orte, an denen die Protokollierung nicht sicher ist. Speziell, malloc ist 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.

    – mgey

    11. April 2018 um 15:46 Uhr

Benutzeravatar von Yusuf Khan
Yusuf Khan

Normalerweise werden Aufrufe von libc/platforms von der OS-Abstraktionsschicht abstrahiert. Die Mutex-Deadlocks können mithilfe einer Besitzervariablen und pthread_mutex_timedlock nachverfolgt werden. Immer wenn der Thread sperrt, sollte er die Variable mit einer eigenen tid(gettid()) aktualisieren und kann auch eine andere Variable für die Speicherung der pthread-ID haben. Wenn also die anderen Threads bei pthread_mutex_timedlock blockieren und das Zeitlimit überschreiten, kann es den Wert von Eigentümer tid und pthread_id drucken. Auf diese Weise können Sie den Besitzer-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, Dead Locks herauszufinden, vielleicht hilft dieser Link http://yusufonlinux.blogspot.in/2010/11/debugging-core-using-gdb.html.

Bitte lesen Sie den folgenden Link. Dies hat eine generische Lösung zum Auffinden des Sperrbesitzers. Es funktioniert auch, wenn Sie eine Bibliothek einschließen und Sie den Quellcode nicht haben.

https://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/Deadlocks

1419490cookie-checkIst es möglich, den Thread zu bestimmen, der einen Mutex enthält?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy