Debugging GNOME Shell

(See Projects/GnomeShell/Debugging/Graphics for graphics-specific information).
(See Projects/GnomeShell/DebuggingJavaScript for a description about how to debug JavaScript code).

First, you need to understand GNOME Shell is split between C and JavaScript. There are a variety of tools available for debugging, but the primary one is gdb. gdb is useful for debugging the C side primarily. By far the easiest setup is to have two computers, and ssh from one into the other.

Starting GNOME Shell under gdb

Do not run these commands from your existing login session; you will freeze the desktop. You need two computers and ssh or you need to be able to switch from the X VT to a console and back reliably (should be fine with all KMS drivers).

If you only want a backtrace from your existing session, you can just use this simple GDB command, but that will only get for you the C and JS stack traces, but no other interaction (unless you don't add other commands manually).

First, obtain a shell that's independent from your GNOME session from which you can extract a log of the output. That means SSH from a second computer or using screen to record the output on a VT on the same computer. If this is from a second computer:

$ ssh sameuser@gnome-shell-computer

(Do not enable X11 forwarding on the SSH session.)

If this is from the same computer, press CTRL-ALT-F2 and, at the black console you see, login as the same user whom has a GNOME session running. Run screen. You should see either a welcome message or immediately see a new command prompt with a little status bar at the bottom of the screen, depending on your distribution configuration. Immediately press CTRL-A, release, SHIFT-H. Screen will confirm that it is now recording the session to screenlog.0 or hardcopy.0, depending on your distribution. Make a note of the file name.

Second, inside this new, independent shell, you must establish the minimum environment variables for X session communication. Download and save the following script to your GNOME Shell system to, for example, ~/bin/

gnome_session=$(pgrep -u $USER gnome-session)
eval export $(sed 's/\o000/\n/g;' < /proc/$gnome_session/environ | grep DISPLAY)
eval export $(sed 's/\o000/\n/g;' < /proc/$gnome_session/environ | grep XAUTHORITY)
eval export $(sed 's/\o000/\n/g;' < /proc/$gnome_session/environ | grep DBUS_SESSION_BUS_ADDRESS)

After you have saved this script, source the file from inside your independent shell with:

. ~/bin/

Third, you are now ready to start GNOME Shell inside of gdb.

$ libtool --mode=execute gdb --args ./src/gnome-shell --replace
(gdb) run


Attach to an existing instance:

$ gdb -p $(pidof gnome-shell)

OR (e.g., if you are not running in a dev environment)

$ gdb --args /usr/bin/gnome-shell --replace
(gdb) run

Fourth, it's now time to make GNOME Shell crash. Flip back to your GNOME session (if same computer, with CTRL-ALT-F7 or -F1, depending on distro) and proceed to perform the behavior which causes a crash. When you have succeeded, the entire desktop will appear to freeze. This means that gdb is waiting for your attention.

Flip over to the gdb window (on the second computer or on the other VT at -F2) and run the "Acquiring a backtrace" steps below.

When you're done, type "quit" to terminate gdb. GNOME Shell will finish crashing and you'll be back at your GNOME desktop. If you started screen, type exit to log out of screen and then exit again to log out of the console.

Upload or paste the SSH output or Screen log output somewhere.

Do not run the above steps from a terminal on your desktop, or you will freeze your desktop. (If you already did before you read this, you can type CTRL-ALT-F2, then log in, then type killall gdb, then press one of ALT-F1 or ALT-F7 (depending on OS version).

Acquiring a backtrace

The first part here dumps the C stacks for all threads. The second part calls into Spidermonkey and acquires the JavaScript stacks.

(gdb) t a a bt
(gdb) call gjs_dumpstack ()

Debugging GNOME Shell with valgrind

$ env G_SLICE=always-malloc ./src/gnome-shell --replace -g --debug-command="libtool --mode=execute valgrind"

Note: You probably also want to specify --log-file=/tmp/gnome-shell.valgrind or the like since valgrind can produce a lot of output, so:

$ env G_SLICE=always-malloc ./src/gnome-shell --replace -g --debug-command="libtool --mode=execute valgrind --log-file=/tmp/gnome-shell.valgrind"

Performance metrics

Linux now has a new tool called "perf", the simplest thing to do is:

$ perf record -p $(pidof gnome-shell)
  (time passes, press Ctrl-C)
$ perf report -i

See also sysprof.

Projects/GnomeShell/Debugging (last edited 2017-10-21 22:17:41 by MarcoTrevisan)