#!/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 src/libvirtd -d src/libvirtd # examples/systemtap/lock-debug.stp src/libvirt.so # # Debug RWLock mechanisms as well. # 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 process 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") }