GHex library usage

Hello all,

I’ve tried to to use GHex libraries in a small utility application to visualize binary data (not from a full file, but sections of a file). However, when I tried to use such libraries, the appliation starts logging a bunch of critical gtk logs regarding an assertion fail that look like this:

Gtk-CRITICAL **: 00:00:00.000: gtk_adjustment_configure: assertion 'lower + page_size <= upper' failed

It then starts working for a bit, but quickly crashes (without any other further log) after interacting repeatedly with the HexWidget.

I’ve tried reading GHex code from the repository in order to figure out if there is some setup function I should run, but I have not found any relevant piece of code. It may also be relevant that I’m using gjs instead of C.

Is there any one who has experience with usage of GHex libraries outside GHex itself? Or is there a piece of code in the GHex repo that I should read more carefully? Or is there any conflict with the gjs language bindings?

P.S.: I use fedora, so I have installed the GHex libraries via the dnf and the relevant packages are ghex-libs and ghex-devel both at version 48.0-1.fc43. Since I’m using system libraries, I’m not using flatpak.

P.S.2: For some reason Gtk.Builder did not recognize HexWidget, so I constructed it manually.

Hey, that’s the warning I added! Glad to see that it’s catching real-world bugs :grinning_face:

For debugging the critical, you should put a breakpoint on g_return_if_fail_warning and see what the offending code is.

For the crash, you should, too, at least post the stack trace of where it crashes.

Hi, thank you for your reply.

For debugging the critical, you should put a breakpoint on g_return_if_fail_warning and see what the offending code is.

Unfortunately, since I’m using language bindings, I’ve no access to such function.

For the crash, you should, too, at least post the stack trace of where it crashes.

I’m not really sure if I did something wrong, but after typing bt full, the following was printed:

Python Exception <class 'gdb.error'>: could not read '.gnu_debugaltlink' section
could not read '.gnu_debugaltlink' section

The only other information that seems kind of useful is something that was printed before gdb had a chance to run. Should I copy it in full here? I tried uploading but I could not do so.

You don’t have to call it from your language, what you should do is set a breakpoint on it, in GDB, and post a backtrace when it’s hit.

Oh I see; I’ve never done that before. How do I set a breakpoint in GDB?

Hi,

Easy trick: you can set the environment variable G_DEBUG=fatal-criticals, gdb will automatically break when encountering a Gtk-CRITICAL error.

Then get the backtrace with bt full, or thread apply all bt full for all threads if needed.

Thank you,

Easy trick: you can set the environment variable G_DEBUG=fatal-criticals, gdb will automatically break when encountering a Gtk-CRITICAL error.

I managed to do that; however, I can only upload images and PDFs here (it is almost 75 kB, so I cannot copy it either).

On the other hand, I have not been able to get a backtrace on the crash itself, I get the could not read ‘.gnu_debugaltlink’ section message from gdb.

The minimalish (I just added a top bar for ease of closing the window) working example that reproduces the logs and crash is the following one:

#!/usr/bin/gjs -m

import Gtk from 'gi://Gtk?version=4.0'
import Adw from 'gi://Adw?version=1'
import Hex from 'gi://Hex?version=4'

const app = new Adw.Application()
app.connect('activate', (app)=>{
  const window = new Adw.ApplicationWindow({
    maximized: true,
    application: app,
    content: new Adw.ToolbarView({
      content: new Hex.Widget({
        document: new Hex.Document(),
      }),
    }),
  })
  window.content.add_top_bar(new Adw.HeaderBar())
  window.present()
})

app.runAsync(['test'])

I will be following any further steps to clarify what is happening; but I guessed, I should also post a minimalish script that reproduces the issue.

This is helpful, thanks, I can reproduce your issues. The mis-configurement of the adjustment happens at:

#0  g_return_if_fail_warning
    (log_domain=0x7fffdd1e53e6 "Gtk", pretty_function=0x7fffdd188fb0 <__func__.2.lto_priv.10> "gtk_adjustment_configure", expression=0x7fffdd1eabb8 "lower + page_size <= upper") at ../glib/gmessages.c:3161
#3  0x00007ffff7c457f5 in <emit signal '0x7fffc4bfc347 "draw-complete"' on instance 0x5555559bce60 [HexWidget]>
    (instance=0x5555559bce60, detailed_signal=0x7fffc4bfc347 "draw-complete") at ../gobject/gsignal.c:3639
    #1  0x00007ffff7c45412 in _g_closure_invoke_va (closure=0x5555559619f0, return_value=0x0, instance=0x5555559bce60, args=0x7fffffffb2d0, n_params=0, param_types=0x0)
    at ../gobject/gclosure.c:980
    #2  signal_emit_valist_unlocked (instance=instance@entry=0x5555559bce60, signal_id=<optimized out>, detail=0, var_args=var_args@entry=0x7fffffffb2d0)
    at ../gobject/gsignal.c:3439
#4  0x00007fffdce16628 in gtk_widget_create_render_node (widget=widget@entry=0x5555559bce60 [HexWidget], snapshot=0x555556241350 [GtkSnapshot])
    at ../gtk/gtkwidget.c:11991

that would be the recalc_scrolling function here.

One crash I got was inside key_press_cb here when trying to access self->document. Another one is in hex_widget_dispose, also when trying to unref self->document.

Clearly, HexWidget fails to ref the document (in fact, I’m not seeing a single g_object_ref call in the whole file!). It should be doing so when the document is being set, i.e. the this line should instead read:

self->document = g_value_dup_object (value);

Could you please pass this info to the GHex maintainer?

Thank you,

I just reported the issue. I’ll link it here so it is accessible from here.

Clearly, HexWidget fails to ref the document (in fact, I’m not seeing a single g_object_ref call in the whole file!). It should be doing so when the document is being set, i.e. this line should instead read:

self->document = g_value_dup_object (value);

After reading your diagnostic, I also verified that the crash no longer happens if the document is referenced from somewhere else in the script. Of course, in this case, gjs complains that the HexDocument was finalized while still owned by gjs probably because when the HexWidget is disposed, it decreases the reference count that gjs had increased to keep it alive.

So the crash can probably be consistently reproduced by typing in the HexWidget 10 seconds after nothing else references its HexDocument.

1 Like