¿Es posible determinar el hilo que contiene un mutex?

En primer lugar, uso la biblioteca pthread para escribir el progtwig C de subprocesos múltiples. Los hilos siempre cuelgan por sus mutexs esperadas. Cuando uso la utilidad strace para encontrar un hilo en estado FUTEX_WAIT , quiero saber qué hilo contiene ese mutex en ese momento. Pero no sé cómo podría hacerlo. ¿Hay alguna utilidad que pueda hacer eso?

Alguien me dijo que la máquina virtual Java es compatible con esto, así que quiero saber si Linux admite esta característica.

Puede usar el conocimiento de las partes internas de mutex para hacer esto. Por lo general, esta no sería una buena idea, pero está bien para la depuración.

En Linux con la implementación NPTL de pthreads (que es cualquier glibc moderno), puede examinar al __data.__owner miembro __data.__owner de la estructura pthread_mutex_t para descubrir el hilo que actualmente tiene bloqueado. Esta es la forma de hacerlo después de adjuntar al proceso con 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) 

(Cambio al hilo colgado, haga un seguimiento para encontrar el pthread_mutex_lock() en el que está bloqueado, cambie los marcos de stack para averiguar el nombre del mutex que está intentando bloquear y luego imprima el propietario de ese mutex). Esto me dice que el hilo con LWP ID 22025 es el culpable.

A continuación, puede usar thread find 22025 para averiguar el número de subproceso gdb para ese subproceso y cambiar a él.

No conozco ninguna de esas facilidades, así que no creo que se salga tan fácilmente, y probablemente no sea tan informativo como cree para ayudar a depurar su progtwig. Por poco tecnológico que parezca, el registro es tu amigo para depurar estas cosas. Comience a recostackr sus propias pequeñas funciones de registro. No tienen que ser elegantes, solo tienen que hacer el trabajo mientras se depuran.

Perdón por el C ++ pero algo así como:

 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); } 

El registro no es una solución perfecta, pero nada lo es. Por lo general, obtiene lo que necesita saber.

Normalmente, las llamadas libc / plataformas se abstraen mediante la capa de abstracción del sistema operativo. Los lockings muertos mutex se pueden rastrear usando una variable de propietario y pthread_mutex_timedlock. Cada vez que el hilo se bloquea, debe actualizar la variable con propio tid (gettid () y también puede tener otra variable para el almacenamiento de pthread id). Entonces, cuando los otros subprocesos bloquean y se agota el tiempo de espera en pthread_mutex_timedlock, puede imprimir el valor de owner tid y pthread_id. De esta forma, puedes encontrar fácilmente el hilo del propietario. encuentre el siguiente fragmento de código, tenga en cuenta que no se manejan todas las condiciones de error

 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); } }; 

Hay otras maneras de descubrir lockings muertos, tal vez este enlace podría ayudar http://yusufonlinux.blogspot.in/2010/11/debugging-core-using-gdb.html .

Lea el enlace a continuación. Tiene una solución genérica para encontrar el propietario del candado. Funciona incluso si se bloquea en el lateral de una biblioteca y no tiene el código fuente.

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