Wiki page enlightenment-debugging created

Signed-off-by: Clément Bénier <clement.benier@openwide.fr>
Signed-off-by: Pierre Le Magourou <pierre.lemagourou@openwide.fr>
Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
Clément Bénier 2015-06-11 09:28:29 +02:00 committed by Cedric BAIL
parent d342f75a86
commit 14666b3336
2 changed files with 271 additions and 0 deletions

View File

@ -0,0 +1,264 @@
~~Title: Enlightenment debugging~~
==== Enlightenment Debugging ===
This tutorial aims at providing a comprehensive and reproducible documentation
to debug Enlightenment. It is divided in two sections:
* [[enlightenment_debugging#Debugging_Enlightenment_using_Gdb|Gdb]]
* [[enlightenment_debugging#Valgrind|Valgrind]]
Before debugging make sure your debug symbols are enabled, if not, go to the
[[/docs-efl-start#Enable_debug_symbols_Optional|Enable debug symbols]]
section.
=== Debugging Enlightenment using Gdb ===
In order to use gdb, we will simulate a crash in Enlightenment.
Start by running Enlightenment on a machine. Then switch to another tty
(CTRL+ALT+F1 for tty1).
At that point, 2 processes are interesting, enlightenment and
enlightenment_start. Indeed, enlightenment is traced by enlightenment_start.
Then setup SEGV to segfault enlightenment.
<code c>
kill -SIGSEGV $(pidof enlightenment)
</code>
enlightenment_start will open a pop-up named Enlightenment Error.
This pop-up indicates that Enlightenment segfaulted and allows to recover or
log out but also detaches from the child process (enlightenment) and let
advanced users use gdb to debug it.
<code bash>
#gdb on the running enlightenment process
gdb enlightenment $(pidof enlightenment)
</code>
After a bit a prompt is available, if you want, you can save the
traces in a log:
<code bash>
#save the traces in log.txt
set logging file log.txt
set logging on
</code>
== Backtrace ==
Use the backtrace command to get information about frames to
know where the segfault is coming from.
<code bash>
(gdb) bt
#0 0xb7d539f8 in select () from /lib/tls/libc.so.6
#1 0xb7dff66a in _XEnq () from /usr/X11R6/lib/libX11.so.6
#2 0xb7dffa7e in _XRead () from /usr/X11R6/lib/libX11.so.6
#3 0xb7e01795 in _XReadEvents () from /usr/X11R6/lib/libX11.so.6
#4 0xb7defa88 in XNextEvent () from /usr/X11R6/lib/libX11.so.6
#5 0x0809b698 in e_alert_show (
text=0x80a34f0 "This is very bad. Enlightenment has segfaulted.\nThis
is not meant to happen and is likely a
sign of a\nbug in Enlightenment
or the libraries it relies on.\n\nYou can gdb attach to this process
now to try"...)
at e_alert.c:136
#6 0x0808f706 in e_sigseg_act (x=11, info=0x80a9fb0, data=0x80aa030)
at e_signals.c:54
#7 <signal handler called>
#8 0xb7d539f8 in select () from /lib/tls/libc.so.6
#9 0xb7f814ee in _ecore_main_select (timeout=0)
at ecore_main.c:338
#10 0xb7f819ba in _ecore_main_loop_iterate_internal (once_only=0)
at ecore_main.c:575
#11 xb7f81a2b in ecore_main_loop_begin () at ecore_main.c:79
#12 0x08059bb3 in main (argc=1, argv=0xbffff144) at e_main.c:551
</code>
As you can see in the stack trace, gdb finds the segfault in libc and pops to the
main function in e_main. But it doesn't seem credible to have a bug in libc or
x, the important thing is Enlightenment has its own segfault handler which is
very explicit on frame 5.
The e_sigseg_act() function at frame 6 is called directly from the kernel when
the program segfaults, meaning enlightenment causes the
segfault. So, the
segfault comes from the select function (a libc function) at frame 8 called in
_e_core_main_select_function at frame 9.
== Go in a frame ==
So, the reason of segfault seems to be at frame 9, when //select// function is
called. Let's go to frame 9:
<code bash>
fr 9
#9 0xb7f814ee in _ecore_main_select (timeout=0) at ecore_main.c:338
338 ret = select(max_fd + 1, &rfds, &wfds, &exfds, t);
(gdb) l
333 }
334 }
335 #ifndef WIN32
336 if (_ecore_signal_count_get()) return -1;
337 #endif
338 ret = select(max_fd + 1, &rfds, &wfds, &exfds, t);
339 if (ret < 0)
340 {
341 if (errno == EINTR) return -1;
342 }
</code>
The first command **//fr 9//** gives useful information: name of the file,
number of the line, the function called, ...
The second command **//l//** lists the code around the called function.
Another useful command allows to print the variables, the parameters, helping
you to find out the problem, a wrong parameter, a null pointer,...
<code bash>
(gdb) p ret
$1 = -4
(gdb) p rfds
$2 = {__fds_bits = {1280, 0 <repeats 31 times>}}
(gdb) p wfds
$3 = {__fds_bits = {0 <repeats 32 times>}}
(gdb) p exfds
$4 = {__fds_bits = {0 <repeats 32 times>}}
</code>
Gdb is important to start debugging, it will help you to resize the problem
even if sometimes is not enough.
----
=== Valgrind ===
Valgrind aims at finding memory problems but for that Enlightenment needs to be run
through Valgrind.
== Prerequisites ==
This tutorial will present 3 different ways to run enlightenment through valgrind:
* remote debugging
* Xephyr invocation
* Xinit invocation
The easiest way is certainly Xephyr because it allows to target a window on a
X server host, sadly Xephyr doesn't yet support OpenGL and any issue that may
be related to it will need to use the Xinit version.
== Remote Debugging ==
Enlightenment_start launcher will handle
setting up environment variables, paths, and launching any other required
services before Enlightenment starts.
Fortunately, there are some options in enlightenment_start that allow to run
Enlightenment through valgrind:
<code bash>
$enlightenment_start --help
Options:
-valgrind[=MODE]
Run enlightenment from inside valgrind, mode is OR of:
1 = plain valgrind to catch crashes (default)
2 = trace children (thumbnailer, efm slaves, ...)
4 = check leak
8 = show reachable after processes finish.
all = all of above
-massif
Run enlightenment from inside massif valgrind tool.
-callgrind
Run enlightenment from inside callgrind valgrind tool.
-valgrind-log-file=<FILENAME>
Save valgrind log to file, see valgrind's --log-f
</code>
First of all, get the ip address of your host machine and connect to it, then
on the distant machine, launch X:
<code bash>
#launch X on tty1
sudo X -ac :1 &
</code>
For example, If you want to check leak and save traces in a log file :
<code bash>
export DISPLAY=:1
enlightenment_start -valgrind=4 -valgrind-log-file=log.txt
</code>
At that point, Enlightenment should have started on your host machine. If the
session is closed then the summary of valgrind should look like :
<code bash>
==1488==
==1488== HEAP SUMMARY:
==1488== in use at exit: 4,479,487 bytes in 24,302 blocks
==1488== total heap usage: 336,239 allocs, 311,937 frees, 88,068,674 bytes allocated
==1488==
==1488== LEAK SUMMARY:
==1488== definitely lost: 825 bytes in 15 blocks
==1488== indirectly lost: 39 bytes in 2 blocks
==1488== possibly lost: 384 bytes in 1 blocks
==1488== still reachable: 4,478,239 bytes in 24,284 blocks
==1488== suppressed: 0 bytes in 0 blocks
==1488== Rerun with --leak-check=full to see details of leaked memory
==1488==
==1488== For counts of detected and suppressed errors, rerun with: -v
==1488== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
</code>
== Valgrind Invocation - xinit ==
Create a file called .xinitrc-debug in your home with the following content:
<code bash>
#!/bin/sh
ulimit -c unlimited
log_file="$HOME/enlightenment-xinit-debug-valgrind.log"
#path of you installation
enlightenment_install_path=/usr/local
#set vars
LD_LIBRARY_PATH="$enlightenment_install_path/lib"
PATH="$enlightenment_install_path/bin:$PATH"
#log to file
echo "using installation at $enlightenment_install_path"
echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" > $log_file
echo "PATH=$enlightenment_install_path/bin: ... " >> $log_file
#start e with valgrind
$enlightenment_install_path/bin/enlightenment_start -valgrind 2>&1 | tee -a "$log_file"
</code>
You can now start a debugging session, after X was closed if it is not the
case log out:
<code bash>
/usr/bin/xinit ~/.xinitrc-debug -- :1 -nolisten tcp
</code>
== Valgrind Invocation - Xephyr ==
Xephyr is a display server implementing the X11 display server protocol which
targets a window on a X Server host. So, for this it is important that X is
launched, you can even do it in your usual window manager under X.
Of course, you need to install Xephyr.
<code bash>
Xephyr -ac -br -noreset -screen 800x600 :1
</code>
*ac: disable access control restrictions
*br: create root window with black background
*noreset: don't reset after last client exists
*screen 800x600: Specify screen characteristics
A black screen should now be displayed, and the interesting thing for us is
that you can launch a window manager on it with valgrind in addition:
<code bash>
DISPLAY=:1 enlightenment_start -valgrind
</code>

View File

@ -25,6 +25,13 @@ course you can use stable packages for your distribution as well.
* [[docs/efl/start|Get started with EFL]]
* [[docs/efl/advanced/start|Advanced EFL Topics]]
Go check the current available version of EFL on each distro/platform:
[[https://phab.enlightenment.org/w/packaging_status/|Table of current version of EFL]]
=== Debugging ===
* [[debugging/enlightenment_debugging|Enlightenment debugging]]
----
==== API Documentation ====