.. _Debugging_GtkAda_applications:

*****************************
Debugging GtkAda applications
*****************************

This chapter presents a number of technics that can be used when
debugging GtkAda applications. First, the standard tools to debug
Ada applications can be used:

*Compile with -g*
  You should almost always include debugging information when compiling and
  linking your code. This gives you the possibility to use the debugger. See
  below the variable GDK_DEBUG for how to disable grabs.

*bind with -E*
  Using this argument on the `gnatbind` or `gnatmake` command
  line will force the compiler to include backtraces when an exception is
  raised. These backtraces can be converted to symbolic backtraces by
  using the `addr2line` tool.

*Link with -lgmem*
  Using this switch gives access to the `gnatmem` tool, that helps
  you to detect memory leaks or doubly-deallocated memory. The latter
  often results in hard-to-fix Storage_Error exceptions. See the GNAT
  User's guide for more information.

There are also a number of technics specific to GtkAda or gtk+
applications. For most of them, you might need to recompile these
libraries with the appropriate switches to get access to the extended
debugging features.

*Use the `--sync` switch*
  Under unix systems, all applications compiled with gtk+ automatically
  support this switch, which forces events to be processed synchronously,
  thus making it easier to detect problems as soon as they happen.
  This switch is not relevant to Windows systems.

*break on g_log*
  In the debugger, it is often useful to put a breakpoint on the glib
  function `g_log`. When gtk+ is linked dynamically, you will need
  to first start your application with `begin`, then put the
  breakpoint and continue the application with `cont`. This helps
  understand internal errors or warnings reported by gtk+ and glib

*compile glib with `--disable-mem-pools`*
  Glib, the underlying layer that provides system-independent services
  to gtk+, has an extensive and optimized system for memory
  allocation. Bigger chunks of Memory are allocated initially, and then
  subdivided by glib itself. Although this is extremely performant, this
  also make the debugging of memory-related problems (storage_error)
  more difficult. Compiling with the above switch forces glib to use the
  standard malloc() and free() system calls. On GNU/Linux systems, it might
  be useful to set the variable `MALLOC_CHECK_` to 1 to use
  error-detecting algorithms (see the man page for malloc()).

*compile glib and gtk+ with `--enable-debug=yes`*
  It is recommended that you specify this switch on the `configure`
  command line when compiling these two libraries.
  In addition to compiling the libraries with debugging information for
  the debugger, additional runtime debug options (controllable via
  environment variables) become available.
  Specifying `--enable-debug=no` is not recommended for production
  releases (see glib or gtk+ documentation for details).

  For these three variables, the possible values are given below. These
  are lists of colon-separated keywords. You can choose to remove any of
  these value from the variable

  *GOBJECT_DEBUG=objects:signals*
    This sets up the debugging output for glib. The value @samp{objects}
    is probably the most useful, and displays, on exit of the application,
    the list of unfreed objects. This helps detect memory leaks. The
    second value @samp{signals} will display all the signals emitted by
    the objects. Note that this results in a significant amount of output.

  *GDK_DEBUG=updates:nograbs:events:dnd:misc:@*xim:colormap:gdkrgb:gc:pixmap:image:input:cursor*
    This sets up the debugging output for gdk. The most useful value is
    @samp{nograbs}, which prevents the application from ever grabbing the
    mouse or keyboards. If you don't set this, it might happen that the
    debugger becomes unusable, since you don't have access to the mouse
    when the debugger stops on a breakpoint. Another simpler solution is
    to debug remotely from another machine, in which case the grabs
    won't affect the terminal on which the debugger is running.

  *GTK_DEBUG=misc:plugsocket:text:tree:updates:keybindings*
    This sets up the debugging output for gtk. Almost all of these values
    are mostly for internal use by gtk+ developpers, although
    @samp{keybindings} might prove useful sometimes.

*keyboard input buffers/freezes while debugging on Windows*
  GTK on windows is installing a low level hook to handle snapping via 
  `set_up_low_level_keyboard_hook`. When the GTK application is stopped by
  the debugger, the GTK handler will become irresponsive and freeze
  the Keyboard input for `LowLevelHooksTimeout` ms.
  Workarounds: 
  - Set :file:`HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout`
  registry to 30ms and restart the session.
  - Recompile GTK after removing `set_up_low_level_keyboard_hook` calls.
  See https://gitlab.gnome.org/GNOME/gtk/-/issues/2015 for more details.

.. highlight:: ada

*Import the C function ada_gtk_debug_get_ref_count*
  This function has the following Ada profile::

    function Ref_Count (Add : System.Address) return Guint;
    pragma Import (C, Ref_Count, "ada_gtk_debug_get_ref_count");
    
  and should be called in a manner similar to::

    declare
       Widget : Gtk_Widget;
       Count  : Guint;
    begin
       Count := Ref_Count (Get_Object (Widget));
    end;

  and returns the internal reference counter for the widget. When this
  counter reaches 0, the memory allocated for the widget is
  automatically freed.

  This is mostly a debugging aid for people writting their own
  containers, and shouldn't generally be needed. You shouldn't rely on
  the internal reference counter in your actual code, which is why it
  isn't exported by default in GtkAda.


