[libvirt] [PATCH 0/2] [RFC] Use the power of SystemTap to get rid of all* deadlocks forever*

Martin Kletzander mkletzan at redhat.com
Tue Sep 9 17:51:00 UTC 2014


On Mon, Sep 08, 2014 at 03:59:04PM +0100, Daniel P. Berrange wrote:
>On Mon, Sep 08, 2014 at 04:17:44PM +0200, Martin Kletzander wrote:
>> Many moons ago, I wanted to make locking more debuggable from logs.
>> An idea appeared that this might be better off with SystemTap.  I let
>> it rot for a while and some time back I had a deadlock that I wanted
>> to try it on.  So I started scripting it and here's the work (in
>> progress).
>>
>> Well, the idea is simple.  For each mutex that is about to get locked,
>> append it's symname and pid that locked it into the list A, when it
>> get's locked move it to list B and when it's unlocked, remove it.
>> Then whenever the user presses ^C, the script prints all the locks
>> that were locked (with their particular backtraces) and locks that are
>> waiting to be locked.  This could be enhanced that it would print both
>> pieces of information only for the locks that are waiting to be
>> acquired.  But I don't really care what color the shed will have.
>>
>>
>> Here are some problems I'd love to get any help with:
>>
>>  - I cannot run it against built git version, two problems with that:
>>
>>     - When I'm not root, staprun needs setuid bit set and that is, of
>>       course, incompatible with the needed LD_LIBRARY_PATH.
>
>The example command line shows you using 'stap' to actually
>launch libvirtd. This is a convenient approach since stap
>automatically gets the PID of the process to trace. You do
>not need todo it this way though.  You can simply run the
>stap script, and then start libvirtd manually (at least for
>session mode libvirtd).
>

Yes, but then I might miss some information on the locks.  However
it might still help sometimes.

>>     - Even when I am root, I'm unable to get any backtrace that goes
>>       beyond virLogMutex() no matter how I'm loading the debug symbols.
>
>Hmm, I just tried your example script and seemed to get the
>full trace of symbols
>
># ./run stap --ldd -c daemon/libvirtd -d daemon/libvirtd  examples/systemtap/lock-debug.stp src/.libs/libvirt.so
>WARNING: Missing unwind data for module, rerun with 'stap -d ...ge/src/virt/libvirt/src/.libs/libvirt_driver_vbox_network.so'
>WARNING: Missing unwind data for module, rerun with 'stap -d ...ge/src/virt/libvirt/src/.libs/libvirt_driver_vbox_storage.so'
>WARNING: Missing unwind data for module, rerun with 'stap -d ...errange/src/virt/libvirt/src/.libs/libvirt_driver_nodedev.so'
>WARNING: Missing unwind data for module, rerun with 'stap -d ...6/berrange/src/virt/libvirt/src/.libs/libvirt_driver_vbox.so'
>WARNING: Missing unwind data for module, rerun with 'stap -d ...errange/src/virt/libvirt/src/.libs/libvirt_driver_network.so'

This is another thing that has to be done.  I guess --ldd doesn't load
symbols for these drivers because the daemon is not dynamically linked
with them, it just loads them.

[...]
>0x7f5eb4000c00(22462):
>virMutexLock+0x0 [libvirt.so.0.1002.9]
>0x7f5ec1bb65bb [libvirt_driver_network.so+0xd5bb]
>---
>virLogMutex+0x0/0x28 [...9576/berrange/src/virt/libvirt/src/.libs/libvirt.so.0.1002.9](22449):
>virMutexLock+0x0 [libvirt.so.0.1002.9]
>main+0x1f33 [lt-libvirtd]
>__libc_start_main+0xf5 [libc-2.18.so]
>_start+0x29 [lt-libvirtd]
>---
>The following locks are waiting to be acquired:
>virLogMutex+0x0/0x28 [...9576/berrange/src/virt/libvirt/src/.libs/libvirt.so.0.1002.9](22462):
>virMutexLock+0x0 [libvirt.so.0.1002.9]
>virLogVMessage+0x365 [libvirt.so.0.1002.9]
>virLogMessage+0x97 [libvirt.so.0.1002.9]
>virCommandRunAsync+0x44f [libvirt.so.0.1002.9]
>virCommandRun+0x3a4 [libvirt.so.0.1002.9]
>dnsmasqCapsRefreshInternal+0x106 [libvirt.so.0.1002.9]
>dnsmasqCapsNewFromBinary+0x1b [libvirt.so.0.1002.9]
>0x7f5ec1bb67e2 [libvirt_driver_network.so+0xd7e2]
>---
>eventLoop+0x0/0x70 [...9576/berrange/src/virt/libvirt/src/.libs/libvirt.so.0.1002.9](22449):
>virMutexLock+0x0 [libvirt.so.0.1002.9]
>virEventPollRunOnce+0x401 [libvirt.so.0.1002.9]
>virEventRunDefaultImpl+0x42 [libvirt.so.0.1002.9]
>virNetServerRun+0x13d [lt-libvirtd]
>main+0x1f40 [lt-libvirtd]
>__libc_start_main+0xf5 [libc-2.18.so]
>_start+0x29 [lt-libvirtd]
>---
>

How did you manage to run it with the git built daemon?  Or did you
just connected to it?  If you just ran it as written above:

># ./run stap --ldd -c daemon/libvirtd -d daemon/libvirtd  examples/systemtap/lock-debug.stp src/.libs/libvirt.so

then I myself am impressed that it works, because for me it doesn't :)

>>  - When running with installed libvirtd, I am not getting as nice
>>    backtrace as I would in gdb (but that's probably the only way how
>>    systemtap will get any backtrace so it's better than nothing).  And
>>    I'm unable to get line numbers even with addr2line.
>
>Yeah, the systemtap backtrace is based solely on info available in
>the loaded ELF library unwind data.  GDB meanwhile will look at the
>debuginfo packages to resolve to line numbers/files. The data your
>script is printing out has only shown addresses relative to the
>start of the function, and addr2line cannot convert that into line
>numbers. AFAICT addr2line only works with addresses relative to
>the load address of the ELF library.
>
>You can make a tweak to the script to instead use sprint_usyms(ubacktrace())
>which gets it to print out more data
>
>---
>
>0x7f224c000c00(23921):
> 0x7f226f0cd850 : virMutexLock+0x0/0x10 [...9576/berrange/src/virt/libvirt/src/.libs/libvirt.so.0.1002.9]
> 0x7f225a7f35bb : 0x7f225a7f35bb [...errange/src/virt/libvirt/src/.libs/libvirt_driver_network.so+0xd5bb/0x223000]
>
>---
>virLogMutex+0x0/0x28 [...9576/berrange/src/virt/libvirt/src/.libs/libvirt.so.0.1002.9](23908):
> 0x7f226f0cd850 : virMutexLock+0x0/0x10 [...9576/berrange/src/virt/libvirt/src/.libs/libvirt.so.0.1002.9]
> 0x7f226fc1d163 : main+0x1f33/0x269c [...1524c9576/berrange/src/virt/libvirt/daemon/.libs/lt-libvirtd]
> 0x7f226b94ed65 : __libc_start_main+0xf5/0x1c0 [/usr/lib64/libc-2.18.so]
> 0x7f226fc1d8f5 : _start+0x29/0x34 [...1524c9576/berrange/src/virt/libvirt/daemon/.libs/lt-libvirtd]
>
>
>Unfortuntely these addresses appear to be absolute offsets in the process
>memory, which is still useless unless you know the load address of each
>ELF module.
>

I don't know what's the difference between the offsets before and
after the slash (e.g. in main+0x1f33/0x269c), maybe it's from-to?

>
>I definitely think it ought to be possible to convert an address like
>virCommandRunAsync+0x44f into a proper line number though. Perhaps we
>would need to directly write code against elfutils, instead of relying
>on addr2line.
>

That's out of my league for now (even though Id love to get some more
insights on ELF structure, etc.).  But do you think it would be worth
adding even without this info (for now)?  If yes, then I'd be happy to
polish it a bit and propose it.

Thank you for the response,
Martin

>Regards,
>Daniel
>--
>|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
>|: http://libvirt.org              -o-             http://virt-manager.org :|
>|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
>|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20140909/943e6b4b/attachment-0001.sig>


More information about the libvir-list mailing list