mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-26 23:55:23 +00:00
119 lines
2.7 KiB
Plaintext
119 lines
2.7 KiB
Plaintext
|
#!/usr/bin/stap --ldd -d /usr/sbin/libvirtd -c libvirtd
|
||
|
#
|
||
|
# Usage with installed libvirt daemon:
|
||
|
# stap --ldd -d /usr/sbin/libvirtd -c libvirtd \
|
||
|
# lock-debug.stp /usr/lib/libvirt.so
|
||
|
#
|
||
|
# If made executable; simple './lock-debug.stp' should work too.
|
||
|
#
|
||
|
# TODOs:
|
||
|
#
|
||
|
# Document usage with uninstalled daemon and libs. Assuming CWD is toplevel
|
||
|
# source git directory, it should be only slight modification to the following:
|
||
|
#
|
||
|
# ./run stap --ldd -c daemon/libvirtd -d daemon/libvirtd
|
||
|
# examples/systemtap/lock-debug.stp src/.libs/libvirt.so
|
||
|
#
|
||
|
# Debug RWLock mechanisms as well.
|
||
|
#
|
||
|
# Author: Martin Kletzander <mkletzan@redhat.com>
|
||
|
|
||
|
|
||
|
global mx_tolock
|
||
|
global mx_locked
|
||
|
|
||
|
|
||
|
function filter()
|
||
|
{
|
||
|
if (pid() != target())
|
||
|
return 1
|
||
|
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
probe library = process( %( $# > 0 %? @1 %: "/usr/lib/libvirt.so" %) )
|
||
|
{
|
||
|
if (filter()) next
|
||
|
}
|
||
|
|
||
|
probe lock = library.function("virMutexLock")
|
||
|
{
|
||
|
lockname = usymdata($m)
|
||
|
}
|
||
|
|
||
|
probe unlock = library.function("virMutexUnlock")
|
||
|
{
|
||
|
lockname = usymdata($m)
|
||
|
}
|
||
|
|
||
|
probe begin
|
||
|
{
|
||
|
%( $# > 1 %? println("error: Too many parameters"); exit();
|
||
|
%: print("Started, press ^C when the proccess hangs\n"); %)
|
||
|
}
|
||
|
|
||
|
probe lock.call
|
||
|
{
|
||
|
mx_tolock[lockname, tid()] = sprint_usyms(ubacktrace())
|
||
|
}
|
||
|
|
||
|
probe lock.return
|
||
|
{
|
||
|
if ([lockname, tid()] in mx_tolock) {
|
||
|
mx_locked[lockname, tid()] = mx_tolock[lockname, tid()]
|
||
|
delete mx_tolock[lockname, tid()]
|
||
|
} else {
|
||
|
printf("internal error: lock acquired unwillingly?\n")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
probe unlock.call
|
||
|
{
|
||
|
found = 0
|
||
|
|
||
|
foreach ([lock, tid] in mx_locked) {
|
||
|
if (lock != lockname)
|
||
|
continue
|
||
|
if (tid != tid()) {
|
||
|
printf("Warning: lock released on different thread that locked it.\n")
|
||
|
printf("Lock trace:\n%s\n", mx_locked[lock, tid])
|
||
|
printf("Unlock trace:\n%s\n", sprint_usyms(ubacktrace()))
|
||
|
}
|
||
|
|
||
|
found = tid
|
||
|
break
|
||
|
}
|
||
|
|
||
|
if (found && [lockname, found] in mx_locked)
|
||
|
delete mx_locked[lockname, found]
|
||
|
}
|
||
|
|
||
|
probe end
|
||
|
{
|
||
|
tmp = 0
|
||
|
|
||
|
printf("\n=============\n")
|
||
|
|
||
|
foreach (bt1 = [lock1, tid1] in mx_tolock) {
|
||
|
deadlock = 0
|
||
|
|
||
|
foreach (bt2 = [lock2, tid2] in mx_tolock) {
|
||
|
if (lock1 == lock2) {
|
||
|
if (!tmp++)
|
||
|
printf("The following locks cannot be acquired:\n")
|
||
|
|
||
|
if (!deadlock++)
|
||
|
printf("Lock %s was locked in thread %d with this trace:\n%s\n",
|
||
|
lock1, tid1, bt1)
|
||
|
|
||
|
printf("and is waiting to be locked by thread %d here:\n%s\n",
|
||
|
tid2, bt2)
|
||
|
}
|
||
|
}
|
||
|
if (deadlock)
|
||
|
printf("---\n")
|
||
|
}
|
||
|
if (!tmp)
|
||
|
printf("No deadlocks found, sorry.\n")
|
||
|
}
|