Jump to content

Amarok/Development/DebuggingHowTo

From KDE Community Wiki
Revision as of 21:26, 24 February 2015 by Mamarok (talk | contribs) (Debugging an already running instance of Amarok: adding more precision about the meaning of 'pidof amarok')
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Normally, Amarok is expected to run correctly. The release versions have gone through betas and have been tested by many people; they rarely need debugging. In contrast, versions released in beta, along with versions taken straight from GIT, are quite likely to crash at some point. These crashes (and other bugs) are a lot easier to fix if the Developers know what the cause is. Enter debugging.


Preparing for Debugging

In order to effectively debug Amarok, you need the debug symbols both for the program itself and for kdelibs and Qt. If compiling from source, then you need to notify the compiler to keep the debug symbols (by means of certain compiler flags). If you are using your distribution's binary packages, then you need to install the associated "debugging" packages.

Compiling from source

If you are compiling Amarok from source, then you need to tell the compiler to include the debug symbols in the build (they are discarded by default). When running cmake, include the flag -DCMAKE_BUILD_TYPE=debugfull. See here for more information about compilation.

Using distribution packages

If you are using your distribution's binary packages, they will often provide debugging information in a separate package. For example, if Amarok is contained in the amarok package, there will usually be an amarok-debug or amarok-dbg package, which you should install.

In addition to Amarok's debug packages, you should install the kdelibs and Qt debug packages (most likely kdelibs-debug or kdelibs-dbg and qt-debug, qt4-debug, qt-dbg or qt4-dbg). These will provide additional debugging symbols, making your backtraces more valuable.

These debugging packages may be contained in a separate repository that is not enabled by default. See your distribution's documentation for more information.

Installing these packages will not slow Amarok down in any way. They will not have any effect until you actually try to debug Amarok in GDB, at which time they will turn a backtrace from a useless string of text and numbers into something developers can use to find and fix the problem.

Gentoo

If installing from ebuild, please ensure that you have following options in make.conf:

CXXFLAGS="... -ggdb ..."  # or: -g
FEATURES="splitdebug"  # or: nostrip

It is preferred to not include flags like -fomit-frame-pointer in CXXFLAGS.

Note that you do not need to have

USE=debug

The debug use-flag only enables debugging assertions and is useful mainly for people that want to actively help with Amarok development.

See also the Gentoo guide to get meaningful backtraces for more details about debug builds on Gentoo.

Debug Output

When Amarok is built in debug mode, it can produce a lot of console output about what it is doing. This can be useful for tracking down errors, but it slows Amarok down significantly, and so is disabled by default.

To generate debugging output (e.g., if asked by a developer), you should quit Amarok completely (Quit on the Amarok menu, or right-click the tray icon and choose Quit), then run the following in a terminal:

amarok --debug

You should soon see a flood of debugging output. This output (usually the last 50 or so lines after reproducing a problem) can be attached (as a text file) to a bug report (as appropriate).

Note: simply installing your distribution's associated debugging packages will NOT allow you to get debugging output of this form. However, it will allow you produce useful backtraces (see below).

Getting a Backtrace

A backtrace is a list of the things that the program tried to do before it crashed. As it is likely that one of these things caused the crash, the backtrace is an invaluable tool to developers.

GDB

GDB (GNU's Debugger) is a debugging tool that can be used to provide a backtrace. It comes prepackaged for many distributions, and can be installed that way, or can be compiled and installed from source. If you wish to use the binary provided by your distribution, the package is often called "gdb" and can be installed with your distribution's package management tool (apt-get for Debian/Ubuntu, yum for Redhat, etc.).

Once GDB is installed, it can be run on Amarok:

gdb amarok

(In Amarok 2, there is no separate amarokapp binary any more, so you can debug against amarok directly.)

You should see some info like this:

Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".
(gdb)

By default, KDE applications detach from the spawned shell. However, when this happens, GDB is unable to track the application. To prevent this behavior (called "forking"), KDE applications come with a --nofork flag. This flag needs to be set prior to running Amarok:

(gdb) set args --nofork

Amarok can now be started by:

(gdb) run

Now, try to repeat whatever originally caused Amarok to crash. At the point of the crash, GDB will freeze Amarok. Go back to the console GDB is running in, and type

(gdb) bt

This will cause GDB to output a backtrace. Note that it references specific functions, files, and line numbers. This backtrace should be attached to an associated bug report. If instead of something like the following you see lots of question marks, you likely do not have all of the necessary debugging symbols installed.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1236346144 (LWP 1654)]
0xb6f6179b in QString::latin1ToUnicode () from /usr/lib/libqt-mt.so.3
(gdb) bt
#0  0xb6f6179b in QString::latin1ToUnicode () from /usr/lib/libqt-mt.so.3
#1  0xb6f62056 in QString::QString () from /usr/lib/libqt-mt.so.3
#2  0xb50adb6a in HelixConfigDialog (this=0x881aea8, engine=0x86924a8, p=0x0) at helix-configdialog.cpp:215
#3  0xb50a7acc in HelixEngine::configure (this=0x86924a8) at helix-engine.cpp:96
#4  0x080c0177 in AmarokConfigDialog::soundSystemChanged (this=0x88a3660) at configdialog.cpp:307
#5  0x080bfe34 in AmarokConfigDialog::updateWidgets (this=0x88a3660) at configdialog.cpp:235
#6  0xb7684399 in KConfigDialog::show () from /usr/lib/libkdeui.so.4
#7  0x0808f051 in App::slotConfigAmarok (this=0xbffff960, page=@0xbfffed20) at app.cpp:788
#8  0x0808fc0d in App::qt_invoke (this=0xbffff960, _id=20, _o=0xbfffedb0) at app.moc:108
#9  0xb6cae067 in QObject::activate_signal () from /usr/lib/libqt-mt.so.3
#10 0xb6cadeae in QObject::activate_signal () from /usr/lib/libqt-mt.so.3
#11 0xb754d88b in KAction::activated () from /usr/lib/libkdeui.so.4
#12 0xb754cffa in KAction::slotActivated () from /usr/lib/libkdeui.so.4
#13 0xb754d2be in KAction::slotButtonClicked () from /usr/lib/libkdeui.so.4
#14 0xb754dba1 in KAction::qt_invoke () from /usr/lib/libkdeui.so.4
#15 0xb6cae067 in QObject::activate_signal () from /usr/lib/libqt-mt.so.3
#16 0xb75f7bc5 in KToolBarButton::buttonClicked () from /usr/lib/libkdeui.so.4
#17 0xb75f63ba in KToolBarButton::mouseReleaseEvent () from /usr/lib/libkdeui.so.4
#18 0xb6ce17e9 in QWidget::event () from /usr/lib/libqt-mt.so.3
#19 0xb6c56370 in QApplication::internalNotify () from /usr/lib/libqt-mt.so.3
#20 0xb6c55ac7 in QApplication::notify () from /usr/lib/libqt-mt.so.3
#21 0xb7270ab5 in KApplication::notify () from /usr/lib/libkdecore.so.4
#22 0xb6bef12f in QETWidget::translateMouseEvent () from /usr/lib/libqt-mt.so.3
#23 0xb6bece1c in QApplication::x11ProcessEvent () from /usr/lib/libqt-mt.so.3
#24 0xb6c02ec2 in QEventLoop::processEvents () from /usr/lib/libqt-mt.so.3
#25 0xb6c6774c in QEventLoop::enterLoop () from /usr/lib/libqt-mt.so.3
#26 0xb6c6760e in QEventLoop::exec () from /usr/lib/libqt-mt.so.3
#27 0xb6c5657b in QApplication::exec () from /usr/lib/libqt-mt.so.3
#28 0x081a6e55 in main (argc=1, argv=0xbffffae4) at main.cpp:92

Debugging an already running instance of Amarok

It can be quite difficult to reproduce some bugs, such that it is easier to simply debug when Amarok crashes initially. To do this, try the following in a terminal when Amarok crashes:

 gdb `which amarok` -p `pidof amarok`
 (gdb) thread apply all bt

where 'pidof amarok' needs to be replaced by the PID number of the Amarok process. You can see the PID number of processes for example by using the command "top" in a separate konsole.

You will then get a backtrace, which you should submit in your bug report.

Debugging Hangs

Amarok is a multi-threaded application, effort is taken to do potentially blocking operations in background threads so that the UI is responsive. A bug in code may cause that the UI thread is unnecessarily blocked or a complete hang may occur. Please take steps below to debug these situations.

  1. Install debug symbols for Amarok and its dependencies as shown above.
  2. Prepare 2 terminal windows (tabs). Terminal 1 will be used to launch Amarok with debugging output, terminal 2 will be used to catch a backtrace.
  3. In terminal 2 prepare (do not yet execute) following command: gdb --ex "set height 0" --ex "thread apply all bt 15" --ex "detach" --ex "q" -p $(pidof amarok)
  4. Start Amarok with debugging output in terminal 1: amarok --debug --nofork
  5. Wait for the hang to occur or trigger it. Once it occurs, run the command prepared in terminal 2.
  6. Paste (do not attach) the backtrace from terminal 2 into a bug report, include also last screen or 2 of the debugging output prior to the crash from terminal 1 (please do not paste whole debugging log unless instructed). Also include usual info like steps to reproduce and version.
  7. (Optional) Recreate the hang and backtrace multiple times and compare the backtrace of Thread 1 from different runs. Mention on the bug whether they are the same or not.