Bug Report HOWTO
- How do I file a useful bug report?
- gtk-gnutella is doing something wrong or unexpected.
- gtk-gnutella won't compile!
- gtk-gnutella crashed! Now what?
- Where's the best place to submit my bug report?
How do I file a useful bug report?
Developers love getting good bug reports. Unfortunately, for one reason or another, the reports they get are often of no use. Here's some hints on producing bug reports that will help make gtk-gnutella better. The ideal bug report would contain exactly the information needed - no more, no less - and a lovingly crafted patch to correct the problem. If you'd like to contribute a patch, please read the development page and the Developers Howto. Most of us, however, don't have the skills and/or time to fix gtk-gnutella for ourselves. That's OK, we can still help.
Keep in mind that the developers are only interested in bug reports from the latest released version or from versions built from current SVN. The developers code gtk-gnutella not for profit, but because they find it an interesting hobby and because they want to give something back to the open source community. Please don't treat them as if they were a company that you paid money to and that you can now expect service from. Supporting old versions falls into the "been there, done that, boring" category and new versions are generally better for you and better for the gnet.
A common mistake people make is to include too little information in their report. The developers would much rather search through a bug report and find what they need than to get no bug report at all. They don't have time to extract the information bit by bit from the user. So, if you're not sure, put it in. Once you have filed a report make sure you stay tuned for a request for more information from the developer. If they do ask you for more details, make sure you answer all their questions, even if the answer is "I don't know." Nothing is more frustrating than knowing you have a bug in your program but not having quite enough information to fix it.
The first thing developers want to know is the version of gtk-gnutella that experienced the bug so they will know which version of the source code has the problem (and if the bug is already fixed.) You can copy this information from the About pop up window. For example:
gtk-gnutella/0.92 (15/06/2003; X11; Linux 2.4.21 i586)
If it's a distribution package, say which one and where you got it. For example:
I'm using the GTK2-gtk-gnutella_0.92.0-0_i386.deb package from the gtk-gnutella web site.
If you compiled gtk-gnutella from SVN, you can use
ident
to verify which revisions of which sources files your binary
was compiled with. This can be useful to verify whether you
really compiled against the latest revision.
If you compiled it yourself, say which ./Configure
options
you used. For example:
./Configure -Dprefix=/usr -Dccflags="-g -Wall" -Doptimize="-O2" -Dgtkversion=2 -ders
Say what distribution and version and what architecture you're running. For example:
debian 2.2.22 on compaq alpha
Include the relevant version information in every bug report.
gtk-gnutella is doing something wrong or unexpected.
If gtk-gnutella is acting the way its programmers intended but you would prefer it behaved differently, then you should probably file a feature request rather than a bug report. Of course, there are exceptions - the behavior could be harmful in some unforeseen way or not conform to standards. Besides, it's hard to know what the developer intended, so the traditional confusion about bug vs feature is inevitable.
If you decide it is a bug, explain clearly what gtk-gnutella is doing wrong and what you think it should be doing. Your description should be detailed enough that someone else can reproduce the bug from your report. Which pane were you in and what options did you have selected? What were the precise actions that led to the bug? It may help to write a few quick notes before you forget.
gtk-gnutella won't compile!
Not many compilation problems are reported for gtk-gnutella. It's known to compile on Linux, OS X, and FreeBSD with gcc. If you have problems, paste the last compiler command, for example:
gcc -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/include/gtk-1.2
-I/usr/include/glib-1.2 -I/usr/lib/glib/include -I/usr/X11R6/include
-I/usr/include/libxml2 -g -O2 -Wall -c nodes.c
and the errors that it generated into your report, along with the version and configuration options described above.
gtk-gnutella crashed! Now what?
In order to debug a crash, the executable needs to have its debugging symbols intact. Unfortunately, to save space on the hard drive and in memory, debugging symbols are stripped from gtk-gnutella when a distribution package is created. The rpm, debian, and slackware packages on the gtk-gnutella download site have all been stripped and are useless for debugging. But if you have a crash while using a package, you should still report the bug and the exact error message so others can attempt to reproduce it with an unstripped executable.
If you run gtk-gnutella from an xterm, then you'll find the error message
in the terminal window (might have to scroll back a bit.) If you start
gtk-gnutella from an icon or menu, then you can find the error wherever
your X error log is. The whole error message and preferably about 10
lines leading up to the error should be pasted into your bug report. If
you're paranoid (after all, they are out to get you)
you could obfuscate filenames. You'll only find the error if
gtk-gnutella abort
s, not if it has a segmentation fault
so
you should say which case applies.
The most common reason for a gtk-gnutella crash is an "assertion" failure.
Assertions are logical statements that are placed strategically throughout
the code to help programmers find bugs. They "assert" that, at a
particular place in the code execution, a particular condition must be met
or the program is not behaving as the developer understands it should.
For example, an assertion could state that a variable should at least have
a value i.e., the value is not null: g_assert(header != NULL);
or that the value should be in some numerical range:
g_assert(parq_ul->position > 0);
. If the assertion fails,
the program aborts with an error message saying which assertion failed and
exactly where in the code the assertion was placed. For example:
** ERROR **: file parq.c: line 1138 (parq_upload_free): assertion failed:
(parq_ul->by_ip->uploading <= parq_ul->by_ip->total)
The developers can then investigate the values and hopefully realize where the bug is that led to the incorrect value. Or they can add more assertions further back in the code until the problem has been isolated. There are more than five hundred assertions in the gtk-gnutella code, so you can see why the developers need you to give them the exact error message, including the file and line number.
If you are using a package or you have stripped the gtk-gnutella executable yourself, there's not much more information to be gained from your crash unless you recompile and can reproduce the bug. If you don't want to do that, then provide the information described so far. That isn't usually enough information to fix the problem but at least it's a heads up that there is a bug. If you've provided a clear enough description, someone else may be able to reproduce the bug with a debugging version of gtk-gnutella.
If you have compiled gtk-gnutella yourself then by default, it will be
compiled with the -O
option passed to the compiler and, in
addition make install
will strip the executable. For bug
reporting, you should compile with -g3 -O0
to get debugging
symbols and use less optimization. For example:
./Configure -O -Dccflags="-g3 -Wall" -Doptimize="-O0" -ders
There is currently no way to tell make install
to
not strip the executable so you will have to copy the
unstripped version over the installed version. For example:
su -c 'install -m 555 src/gtk-gnutella /usr/local/bin/gtk-gnutella'
When gtk-gnutella crashes, it will dump a "core" file containing an image
of the memory it used, including all the values held in RAM at the time.
This file can then be loaded into the gdb debugger to investigate the
state of gtk-gnutella at the time of the crash. However, most
distributions turn core dumps off by default. You can turn on core dumps
with the shell command ulimit -S -c unlimited
, which will
only affect that terminal, or you can put the command on your shell config
file (e.g., ~/.profile
or ~/.cshrc
) to allow core
dumps globally. Newer core files will overwrite older ones so you should
move them to a safe place. The core file will be in your home directory
or in the current directory if you called gtk-gnutella from a terminal.
If you're serious about bug hunting for gtk-gnutella you might want to use
something like the following shell script to start it. You'll have to
modify it to suit your system, of course. For instance, the core file
could be named "core", "gtk-gnutella.core", "core.[PID]", etc.
#!/bin/sh
# This is where the configuration stuff is stored.
#export GTK_GNUTELLA_DIR=$HOME/.gtk gnutella
# Turn on core dumps and delete old dump and log
ulimit -S -c unlimited
rm -f core gtk-gnutella.log
# Run gtk-gnutella and redirect output to a log file
# The log could get quite large if your uptime is long.
# To just keep output in the terminal use:
# gtk-gnutella
# instead and remove the other log references.
gtk-gnutella >gtk-gnutella.log 2>&1
# If a core is dumped, create a uniquely named directory
# to save the core, log and executable
if [ -e core ] ; then
Core_Save_Dir=$(date "+core%Y.%m.%d.%H.%M.%S")
mkdir $Core_Save_Dir
cp $(which gtk-gnutella) $Core_Save_Dir
cp core $Core_Save_Dir
cp gtk-gnutella.log $Core_Save_Dir
fi
Ok, now that you have an unstripped executable and a core file, you can
use the gdb
debugger to make a backtrace. Note that in this
example, the gtk-gnutella executable and the core have been saved to the
same directory.
~/src/test/core2003.06.12.18.01.40> gdb -c core ./gtk-gnutella
GNU gdb 5.2
Copyright 2002 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 "i386-slackware-linux"...
Core was generated by `gtk-gnutella'.
Program terminated with signal 6, Aborted.
Reading symbols from /usr/lib/libgtk-1.2.so.0...done.
Loaded symbols for /usr/lib/libgtk-1.2.so.0
Reading symbols from /usr/lib/libgdk-1.2.so.0...done.
Loaded symbols for /usr/lib/libgdk-1.2.so.0
Reading symbols from /usr/lib/libgmodule-1.2.so.0...done.
Loaded symbols for /usr/lib/libgmodule-1.2.so.0
Reading symbols from /usr/lib/libglib-1.2.so.0...done.
Loaded symbols for /usr/lib/libglib-1.2.so.0
Reading symbols from /lib/libdl.so.2...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /usr/X11R6/lib/libXext.so.6...done.
Loaded symbols for /usr/X11R6/lib/libXext.so.6
Reading symbols from /usr/X11R6/lib/libX11.so.6...done.
Loaded symbols for /usr/X11R6/lib/libX11.so.6
Reading symbols from /lib/libm.so.6...done.
Loaded symbols for /lib/libm.so.6
Reading symbols from /usr/lib/libz.so.1...done.
Loaded symbols for /usr/lib/libz.so.1
Reading symbols from /usr/lib/libxml2.so.2...done.
Loaded symbols for /usr/lib/libxml2.so.2
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /usr/X11R6/lib/X11/locale/common/xlcDef.so.2...done.
Loaded symbols for /usr/X11R6/lib/X11/locale/common/xlcDef.so.2
Reading symbols from /usr/X11R6/lib/X11/locale/common/ximcp.so.2...done.
Loaded symbols for /usr/X11R6/lib/X11/locale/common/ximcp.so.2
Reading symbols from /lib/libnss_compat.so.2...done.
Loaded symbols for /lib/libnss_compat.so.2
Reading symbols from /lib/libnsl.so.1...done.
Loaded symbols for /lib/libnsl.so.1
Reading symbols from /lib/libnss_db.so.2...done.
Loaded symbols for /lib/libnss_db.so.2
Reading symbols from /lib/libnss_files.so.2...done.
Loaded symbols for /lib/libnss_files.so.2
Reading symbols from /lib/libdb-3.1.so...done.
Loaded symbols for /lib/libdb-3.1.so
#0 0x4036b2f1 in kill () from /lib/libc.so.6
(gdb)
OK, now let's do a full backtrace:
(gdb) bt full
#0 0x4036b2f1 in kill () from /lib/libc.so.6
No symbol table info available.
#1 0x4036afbc in raise () from /lib/libc.so.6
No symbol table info available.
#2 0x4036c7cb in abort () from /lib/libc.so.6
No symbol table info available.
#3 0x4018f9de in g_logv () from /usr/lib/libglib-1.2.so.0
No symbol table info available.
#4 0x4018fa91 in g_log () from /usr/lib/libglib-1.2.so.0
No symbol table info available.
#5 0x0814efda in parq_upload_free (parq_ul=0x8d62328) at parq.c:1138
No locals.
#6 0x0814d696 in parq_close () at parq.c:416
queues = (GList *) 0x0
dl = (GList *) 0x0
sl = (GSList *) 0x8a20040
remove = (GSList *) 0x8a204b8
removeq = (GSList *) 0x8a204c0
#7 0x0811f3a4 in gtk_gnutella_exit (n=0) at main.c:113
now = 1055466099
tick = 143511256
#8 0x080d7eba in quit (force=0) at main_cb.c:44
confirm = 0
#9 0x080d7f04 in on_button_quit_clicked (button=0x8358d44, user_data=0x0) at main_cb.c:62
No locals.
#10 0x400b10d5 in gtk_marshal_NONE__NONE () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#11 0x400e091c in gtk_signal_remove_emission_hook () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#12 0x400dfd85 in gtk_signal_set_funcs () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#13 0x400dde63 in gtk_signal_emit () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#14 0x401149be in gtk_widget_activate () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#15 0x400b9534 in gtk_menu_shell_activate_item () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#16 0x400b87ba in gtk_menu_shell_deactivate () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#17 0x400b0d5f in gtk_marshal_BOOL__POINTER () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#18 0x400dfdc3 in gtk_signal_set_funcs () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#19 0x400dde63 in gtk_signal_emit () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#20 0x4011487b in gtk_widget_event () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#21 0x400b0ca5 in gtk_propagate_event () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#22 0x400afe0e in gtk_main_do_event () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#23 0x4015f047 in gdk_wm_protocols_filter () from /usr/lib/libgdk-1.2.so.0
No symbol table info available.
#24 0x4018d258 in g_main_dispatch () from /usr/lib/libglib-1.2.so.0
No symbol table info available.
#25 0x4018d863 in g_main_iterate () from /usr/lib/libglib-1.2.so.0
No symbol table info available.
#26 0x4018d9fc in g_main_run () from /usr/lib/libglib-1.2.so.0
No symbol table info available.
#27 0x400af707 in gtk_main () from /usr/lib/libgtk-1.2.so.0
No symbol table info available.
#28 0x080d7cf2 in main_gui_run () at main_gui.c:650
coord = {0, 0, 1276, 965}
#29 0x0811fc2b in main (argc=1, argv=0xbffff924, env=0xbffff92c) at main.c:463
i = 256
#30 0x4035a17d in __libc_start_main () from /lib/libc.so.6
No symbol table info available.
Paste the backtrace into your bug report.
The developers will probably need some more information but if you send the backtrace and the other information, then they'll have a good place to start. They can then get back to you and request that you load the core into gdb again and print the specific values they need. However, for bonus points, you can anticipate their needs. If you understand C, you can take a peek at the code and decide what to include but if you don't know C, you can still take a guess by having a look at the assertion. In this example, the error message was:
** ERROR **: file parq.c: line 1138 (parq_upload_free): assertion failed:
(parq_ul->by_ip->uploading <= parq_ul->by_ip->total)
Looking at the backtrace, you see in #5 parq.c:1138
, the same
line where the assertion was placed, so lets investigate some values in
that frame:
(gdb) frame 5
#5 0x0814efda in parq_upload_free (parq_ul=0x8d62328) at parq.c:1138
1138 g_assert(parq_ul->by_ip->uploading <= parq_ul->by_ip->total);
First, lets print out the values of the members of parq_ul
.
(gdb) p * parq_ul
$1 = {magic = 1782120609, flags = 10, position = 1735, relative_position = 1, has_slot = 0, had_slot = 0, eta = 81,
expire = 1055465788, retry = 1055465787, enter = 1055465787, updated = 1055465787, ban_timeout = 1055466387,
disc_timeout = 0, last_queue_sent = 0, queue_sent = 0, queue_refused = 0, is_alive = 0,
id = 0x8a15af8 "6cad90dc1f0edd94f5d0e991cc89f25e",
ip_and_name = 0x8a16578 "3521280541 Somethingorother.mp3",
name = 0x8a16583 "Somethingorother.mp3", remote_ip = 3521280541, file_size = 2652639,
chunk_size = 1005329, ip = 0, port = 0, major = 0, minor = 0, queue = 0x84f85c8, by_ip = 0x86259e8}
Notice that the last member listed is by_ip = 0x86259e8
.
The assertion compares two of the members of parq_ul->by_ip
so let's print out the values.
(gdb) p * parq_ul->by_ip
$2 = {uploading = 2, total = 1, ip = 3521280551, list = 0x8bb639c}
There are the values the developer was looking for:
parq_ul->by_ip->uploading
= 2 and
parq_ul->by_ip->total
= 1. Since 2 <= 1
is
false, the assertion failed. Now the developer can try and figure out
what went wrong.
Where's the best place to submit my bug report?
You can report your bug using the SourceForge.net Bug Tracker or you can email your report to the gtk-gnutella-devel mailing list. You can also find a developer on IRC on the Freenode network in the #gtk-gnutella channel.
IRC can be useful for a quick response if you happen to catch a developer in the channel, but it's easy for bugs to be forgotten if they are only reported there. It can be a good place to go if you aren't sure whether your problem is really a bug or not. It's an excellent place to go when you have already made a report on the list or bug tracker and you want to know if the developers need more information from you. At the time this was written, the developers all lived in the Central European Time (CET) zone (UTC+1). You might catch them for a quick question in the morning before work but the best time is in the evenings or on weekends. You can have a look at the IRC log to get an idea of when to find people in the channel. The times listed in the log are also UTC+1.
The developers' mailing list is a good place to report critical bugs like crashes, although you could use the bug tracker for these as well. More people will read a bug report on the list than on the bug tracker and it's perhaps a little more convenient for reading backtraces, etc. On the other hand, bugs reported to the list can be more easily forgotten than those submitted to the bug tracker. You have to register on SourceForge to subscribe to gtk-gnutella-devel, but you don't need to be subscribed to post a message. If you post a message although you're not subscribed to the mailing list, either add your own email address to the Reply-To: header or mention that you're not subscribed.
The best place to submit bugs is the SourceForge bug tracker. After all, that's what it was designed for. Have a look and see if your bug has already been reported and if so, add your report as a comment rather than submitting a new bug. You need to register at SourceForge and be logged in before you can submit a bug.
Once you have submitted your report, don't forget it. Your bug report is not complete until you've answered any follow-up questions the developers have for you. Bug reporters who don't respond to followups are a major irritant to developers. Debugging software can be a frustrating experience for developers but receiving good bug reports can help make writing free software a little more satisfying.