Difference between revisions of "Debugging Inkscape"

From Inkscape Wiki
Jump to navigation Jump to search
Line 28: Line 28:
== Debugging Tips for Windows ==
== Debugging Tips for Windows ==
=== How to run in debug mode ===
=== How to run in debug mode ===
# 1.open command prompt (cmd)
# Open command prompt (cmd)
# 2.type <code>set GTK_DEBUG=interactive</code> and hit enter
# Type <code>set GTK_DEBUG=interactive</code> and hit enter
# 3.then "C:\Program Files\Inkscape\bin\inkscape.exe" or however you launch Inkscape from the same command prompt
# Then <code>C:\Program Files\Inkscape\bin\inkscape.exe</code> or however you launch Inkscape from the same command prompt
# After that inkscape will start wit gtk inspector


First, have a look at the [[Using Visual Studio]] page for how to use that program on Windows to debug Inkscape.
First, have a look at the [[Using Visual Studio]] page for how to use that program on Windows to debug Inkscape.

Revision as of 08:34, 18 November 2020

  • If you're hunting down a GTK warning, run G_DEBUG=fatal-warnings gdb inkscape so you can capture a backtrace. ("run", "bt")
  • If you're hunting down a g_assert, you can set a breakpoint in gdb for "g_assertion_message_expr" (or "g_assertion_message" maybe) to stop execution and make a backtrace.
  • gdb can catch throwing of an exception. Type: "catch throw" and gdb will stop execution at the point of where the exception is thrown, without unwinding the stack, so you can get a backtrace!
  • Bug list

- w32 version asks for (that crappy) Verdana typeface (which is not the most usual w32 typeface, also some users have deleted it to save disk space)

Debugging Tips for OS X

When running the .app package for OS X, it can be difficult to get a backtrace because the application binary is launched through another application and 2 scripts. One way to get a backtrace is:

  • Add '-g' to $CFLAGS in your build script before building.
  • Remove the signal() calls (segv_handler = signal (SIGSEGV,... ) ) in inkscape_application_init() in src/inkscape.cpp.
  • In the Resources/bin/inkscpe script, change the last line from:
    exec "$CWD/inkscape-bin" "$@"
   to:
    exec "/usr/bin/gdb" "stuff/inkscape-bin"
  • Build and package the app (see CompilingMacOsX).
  • Run the application in Terminal:
    
    $ cd packaging/macosx
    $ Inkscape.app/Contents/MacOS/Inkscape
    ...
    (gdb) run
    

Debugging Tips for Windows

How to run in debug mode

  1. Open command prompt (cmd)
  2. Type set GTK_DEBUG=interactive and hit enter
  3. Then C:\Program Files\Inkscape\bin\inkscape.exe or however you launch Inkscape from the same command prompt
  4. After that inkscape will start wit gtk inspector

First, have a look at the Using Visual Studio page for how to use that program on Windows to debug Inkscape.

Second, make use of the View > Messages... dialog from within the program. Capturing the log here will show you messages printed with g_message(), g_warning(), and g_error()..

Finally, look into how to compile Inkscape as a command line app so you can capture debug messages at the prompt, more like you would do in Linux.

How Johan works

Of course I am always compiling with -mconsole, instead of -mwindows. I don't compile with -g or any other extra flags. This is unnecessary and reduces build times significantly.

For example for crashes, usually I add g_message("blah") to the code to see where the execution of code goes and to see on which line things break:

   g_message("1");
   some_piece_of_code1();
   g_message("2");
   some_piece_of_code2();
   g_message("3");
   some_piece_of_code3();
   g_message("4");
   some_piece_of_code4();
   g_message("5");

If I see the message "2" but not "3" I know the crash happened in some_piece_of_code2.

I also use GDB to get backtraces. Again, don't compile with -g. Not necessary at all! One of the problems with running Inkscape in gdb is that you cannot open a file with the file dialog: Inkscape will hang. I don't know the reason, but I do know a solution! Open the file through Inkscape's cmdline parameters:

    D:\Inkscape\inkscape>gdb
    GNU gdb 6.6
    Copyright (C) 2006 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-mingw32".
    (gdb) file inkscape.exe inkscape.dbg
    Reading symbols from D:\Inkscape\inkscape/inkscape.exe...(no debugging symbols found)...done.
    Reading symbols from D:\Inkscape\inkscape/inkscape.dbg...done.
    (gdb) run Tekening.svg
    Starting program: D:\Inkscape\inkscape/inkscape.exe Tekening.svg


Example of how to fix a bug

See this bugreport: https://bugs.launchpad.net/inkscape/+bug/169135

I started gdb like above. And then I saw this:

   Program received signal SIGSEGV, Segmentation fault.
   0x005c94ec in Inkscape::UI::Widget::Scalar::setValue ()
   (gdb) bt
   #0  0x005c94ec in Inkscape::UI::Widget::Scalar::setValue ()
   #1  0x0044fc11 in Inkscape::CanvasXYGrid::readRepr ()
   #2  0x0044de22 in Inkscape::CanvasXYGrid::onReprAttrChanged ()

The crashing piece of code looked like this:

  void Scalar::setValue(double value)
  {
      g_assert(_widget != NULL);
      setProgrammatically = true; // callback is supposed to reset back, if it cares
      static_cast<Gtk::SpinButton*>(_widget)->set_value(value);
  }

Nothing much can crash there, the assert checks that _widget is not NULL, and then the cast is valid aswell. So what crashed? What happens is that the setValue method is called for an object that does not exist. _widget is not NULL, but "this" is! this->_widget would crash. g_assert (this != NULL) would give an assertion message. (checked by adding " if (this==NULL) g_message("ja hoor"); " )

It is absurd to check for "this" to be non-NULL at the start of every method, so the bug is not in this method but in the function calling it! That's why we turn our attention to Inkscape::CanvasXYGrid::readRepr ().

readRepr is long, but we only have to look where it does something with a Scalar widget. It's the validateScalar functions. When we comment those out, the bug is solved. (it causes another bug with the specific SVG file, where Inkscape hangs when the grid spacing equals zero. validateScalar used to check for that...) The strange thing is that the widgets are all created and initialized in the constructor of CanvasXYGrid. So perhaps readRepr is being called *during* construction of CanvasXYGrid, while the Scalar widget is still invalid? Using the g_message tip above I found out that the problem code was:

       sutemp = _rsu_sx.getSU();
  g_message("CanvasXYGrid 1");
       sutemp->setDigits(4);
  g_message("CanvasXYGrid 2");

Researching the setDigits path, I could not find a bug. Then it hit me: _rsu_sx is initialized, then readRepr is called, but this is before _rsu_sy is initialized. Then

   void RegisteredScalarUnit::setValue (double val)
   {
       _widget->setValue (val);
   }

is called, but _widget is still NULL, hence the crash. As usual, the fix is easy:

   void RegisteredScalarUnit::setValue (double val)
   {
       if (_widget)
           _widget->setValue (val);
   }

Don't forget to fix the setValue methods of the other Registered widgets!!!

The fix can be seen in SVN revision 16544.

Problems running GDB

From an inexperienced user of GDB just trying to get backtraces, here is a tip I found running gdb.

I simply downloaded the latest version of Inkscape Dev full debug, extracted to a directory and ran gdb exactly as above from within the directory, only changing the name of the svg file.

Everything went exactly as above for "file inkscape.exe inkscape.dbg", however after executing the "run {filename.svg}" command, I received the following message;

    Program received signal SIGSEV, Segmentation fault.
    0x03de8cf1 in xslDebugStatus ()

This has stumped me once before, but this time I checked out the help menus, and found under "help running" that I could simply type "continue". I figured that xslDebugStatus was nothing to do with the Inkscape program itself, but more to do with gdb, and after typing "continue" it seems to run Inkscape under gdb as normal, allowing backtraces.

guard32.dll error

If you try to run gdb but it halts, complaining about guard32.dll, your Comodo Firewall installation is blocking gdb. Easiest way around this is to disable the Defense+ module completely -- open up Comodo Firewall, click on Defense+, Defense+ settings, set Security Level to "Disabled", and check "Deactivate the Defense+ permanently". Reboot.

Debugging Tips for Linux

Debugging Inkscape on Linux is most easily done using Eclipse (or any other IDE). When however a breakpoint is reached while Inkscape is in a pointer grab (for example when dragging a control point or drawing a path), then X will stop responding. If you want to debug in such a case then you'll have to use gdb from the console. In Fedora 10 you'll get to the console when pressing ctrl-alt-F5. Now enter

    declare -x DISPLAY=":0"

and startup gdb to load Inkscape and the debugging symbols, set your breakpoints, and start Inkscape. Now you can switch back to X (ctrl-alt-F1) and interact with Inkscape. When Inkscape stops responding because it hit a breakpoint, switch back to the console and do your debugging.

If you happen to run into some issues with one of the Gtk+ libraries and want to step through its code using the debugger, you will have to install its debugging symbols. For Fedora 10 you can simply enable the fedora-debuginfo repository in /etc/yum.repos.d/fedora.repo and then use yum to install for example the "gtk2-debuginfo" and "glib-debuginfo" package. For other distros you'll find some usefull information here:

    http://live.gnome.org/GettingTraces/DistroSpecificInstructions