Removing shortcut from an action an ModelButton tracks causes a double-free
Steps to reproduce
- Have a popover menu whose model contains an entry to an action
- Create the action on the application instance
- Add an shortcut to that action and remove it again.
#include <gtk/gtk.h>
// Stolen from https://docs.gtk.org/gtk4/getting_started.html
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
GtkWidget *button = gtk_menu_button_new ();
gtk_menu_button_set_label (GTK_MENU_BUTTON (button), "This is a button");
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (button));
GMenu *menu = g_menu_new ();
g_menu_append (menu, "Some random item", "win.do_something");
GtkWidget *popover_menu = gtk_popover_menu_new_from_model (G_MENU_MODEL (menu));
gtk_menu_button_set_popover (GTK_MENU_BUTTON (button), GTK_WIDGET (popover_menu));
// ModelButtons which seems are normally not usable for outside code like this,
// but appear to be used in Popover Menus.
gtk_widget_show (window);
// Add shortcut
gtk_application_set_accels_for_action (app, "win.do_something", (const char*[]){"J", NULL});
// Now remove it, which causes the error
gtk_application_set_accels_for_action (app, "win.do_something", (const char*[]){NULL});
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
GSimpleAction* action = g_simple_action_new ("win.do_something", NULL);
g_action_map_add_action (G_ACTION_MAP (app), G_ACTION(action));
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
I'm compiling inside the (flathub) org.gnome.Sdk 43 via gcc modelbutton.c -ggdb -o /tmp/modelbutton $(pkg-config --cflags --libs gtk4) && gdb /tmp/modelbutton
.
Version information
- GTK 4.8.1 (from
pkg-config --modversion gtk4
) - org.gnome.Sdk 43 (from flathub)
- flatpak 1.6.5
- Ubuntu 20.04.5 LTS (focal)
Warnings
None, with the exception of the following which shouldn't matter on the crash (the window still displays if I remove the offending code line):
libEGL warning: DRI2: could not open /dev/dri/card0 (Datei oder Verzeichnis nicht gefunden [File or directory not found])
amdgpu: drmGetDevice2 failed.
libGL error: glx: failed to create dri3 screen
libGL error: failed to load driver: radeonsi
libGL error: failed to open /dev/dri/card0: Datei oder Verzeichnis nicht gefunden [File or directory not found]
libGL error: failed to load driver: radeonsi
Backtrace
Thread 1 "modelbutton" received signal SIGSEGV, Segmentation fault.
g_type_check_instance_is_fundamentally_a (type_instance=type_instance@entry=0x555555a0ee10, fundamental_type=fundamental_type@entry=0x50 [GObject]) at ../gobject/gtype.c:4095
4095 node = lookup_type_node_I (type_instance->g_class->g_type);
(gdb) bt full
#0 g_type_check_instance_is_fundamentally_a (type_instance=type_instance@entry=0x555555a0ee10, fundamental_type=fundamental_type@entry=0x50 [GObject]) at ../gobject/gtype.c:4095
node = <optimized out>
#1 0x00007ffff71fbac2 in g_object_unref (_object=0x555555a0ee10) at ../gobject/gobject.c:3785
_g_boolean_var_ = <optimized out>
object = 0x555555a0ee10
__func__ = "g_object_unref"
#2 0x00007ffff7963fdc in update_accel (accel=<optimized out>, self=0x555555a31950 [GtkModelButton]) at ../gtk/gtkmodelbutton.c:857
_pp = 0x555555a319e0
_ptr = <optimized out>
button = 0x555555a31950 [GtkModelButton]
__func__ = "gtk_model_button_set_property"
#3 gtk_model_button_set_accel (accel=<optimized out>, button=0x555555a31950 [GtkModelButton]) at ../gtk/gtkmodelbutton.c:868
button = 0x555555a31950 [GtkModelButton]
__func__ = "gtk_model_button_set_property"
#4 gtk_model_button_set_property (object=0x555555a31950 [GtkModelButton], prop_id=9, value=0x7fffffffcc50, pspec=0x555555a07120 [GParamString]) at ../gtk/gtkmodelbutton.c:981
button = 0x555555a31950 [GtkModelButton]
__func__ = "gtk_model_button_set_property"
#5 0x00007ffff71fbf35 in object_set_property (object=0x555555a31950 [GtkModelButton], pspec=0x555555a07120 [GParamString], value=0x7fffffffcc50, nqueue=0x0) at ../gobject/gobject.c:1792
class = <optimized out>
pclass = 0x555555566df0
param_id = 9
__func__ = "object_set_property"
#6 0x00007ffff71fee22 in g_object_setv (values=<optimized out>, names=<optimized out>, n_properties=<optimized out>, object=0x555555a31950 [GtkModelButton]) at ../gobject/gobject.c:2701
i = <optimized out>
nqueue = <optimized out>
pspec = <optimized out>
class = 0x555555a066d0
__func__ = "g_object_setv"
__func__ = "g_object_setv"
#7 g_object_setv (object=0x555555a31950 [GtkModelButton], n_properties=<optimized out>, names=<optimized out>, values=<optimized out>) at ../gobject/gobject.c:2672
__func__ = "g_object_setv"
#8 0x00007ffff71fff21 in g_object_set_property (object=object@entry=0x555555a31950 [GtkModelButton], property_name=<optimized out>, value=value@entry=0x7fffffffcc50) at ../gobject/gobject.c:3001
#9 0x00007ffff71f0027 in on_source_notify (source=<optimized out>, pspec=<optimized out>, context=<optimized out>) at ../gobject/gbinding.c:556
binding = 0x555555a07c20 [GBinding]
target = 0x555555a31950 [GtkModelButton]
transform_func = <optimized out>
from_value = {g_type = 0x40 [gchararray], data = {{v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}, {v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}}}
to_value = {g_type = 0x40 [gchararray], data = {{v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}, {v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}}}
res = 1
#13 0x00007ffff7212303 in <emit signal notify:accel on instance 0x555555a25880 [GtkMenuTrackerItem]> (instance=instance@entry=0x555555a25880, signal_id=<optimized out>, detail=<optimized out>) at ../gobject/gsignal.c:3606
var_args = {{gp_offset = 32, fp_offset = 48, overflow_arg_area = 0x7fffffffd0d0, reg_save_area = 0x7fffffffd010}}
#10 0x00007ffff71f6502 in g_closure_invoke (closure=0x555555a0bbe0, return_value=return_value@entry=0x0, n_param_values=2, param_values=param_values@entry=0x7fffffffce50, invocation_hint=invocation_hint@entry=0x7fffffffcdd0) at ../gobject/gclosure.c:832
marshal = 0x7ffff71f96e0 <g_cclosure_marshal_VOID__PARAM>
marshal_data = 0x0
in_marshal = 0
real_closure = 0x555555a0bbc0
__func__ = "g_closure_invoke"
#11 0x00007ffff720b1c8 in signal_emit_unlocked_R (node=node@entry=0x555555566810, detail=detail@entry=1209, instance=instance@entry=0x555555a25880, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7fffffffce50)
at ../gobject/gsignal.c:3796
tmp = <optimized out>
handler = 0x555555a09280
accumulator = 0x0
emission = {next = 0x7fffffffd3f0, instance = 0x555555a25880, ihint = {signal_id = 1, detail = 1209, run_type = (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACCUMULATOR_FIRST_RUN)}, state = EMISSION_RUN, chain_type = 0x4 [void]}
hlist = <optimized out>
handler_list = 0x555555a09240
return_accu = 0x0
accu = {g_type = 0x0, data = {{v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}, {v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}}}
signal_id = 1
max_sequential_handler_number = 212
return_value_altered = <optimized out>
#12 0x00007ffff7212135 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fffffffcff0) at ../gobject/gsignal.c:3549
instance_and_params = 0x7fffffffce50
signal_return_type = <optimized out>
param_values = 0x7fffffffce68
node = <optimized out>
i = <optimized out>
n_params = <optimized out>
--Type <RET> for more, q to quit, c to continue without paging--
__func__ = "g_signal_emit_valist"
#14 0x00007ffff71fa9d4 in g_object_dispatch_properties_changed (object=0x555555a25880 [GtkMenuTrackerItem], n_pspecs=<optimized out>, pspecs=<optimized out>) at ../gobject/gobject.c:1428
i = <optimized out>
#15 0x00007ffff71fdb58 in g_object_notify_by_spec_internal (pspec=<optimized out>, object=0x555555a25880 [GtkMenuTrackerItem]) at ../gobject/gobject.c:1544
nqueue = <optimized out>
need_thaw = <optimized out>
object_flags = <optimized out>
needs_notify = 1
in_init = <optimized out>
__func__ = "g_object_notify_by_pspec"
#16 g_object_notify_by_pspec (object=0x555555a25880 [GtkMenuTrackerItem], pspec=<optimized out>) at ../gobject/gobject.c:1650
__func__ = "g_object_notify_by_pspec"
#17 0x00007ffff7ab4591 in gtk_action_muxer_primary_accel_changed (muxer=0x555555a01480 [GtkActionMuxer], action_name=0x555558013cf1 "win.do_something", action_and_target=0x555558013cf0 "|win.do_something") at ../gtk/gtkactionmuxer.c:601
action = <optimized out>
node = 0x55555599fa70 = {0x555555a25880}
#18 0x00007ffff7ab4591 in gtk_action_muxer_primary_accel_changed (muxer=0x555555a4df40 [GtkActionMuxer], action_name=0x555558013cf1 "win.do_something", action_and_target=0x555558013cf0 "|win.do_something") at ../gtk/gtkactionmuxer.c:601
action = <optimized out>
node = 0x55555595f5c0 = {0x555555a01480}
#19 0x00007ffff7ab4591 in gtk_action_muxer_primary_accel_changed (muxer=0x555555a4dac0 [GtkActionMuxer], action_name=0x555558013cf1 "win.do_something", action_and_target=0x555558013cf0 "|win.do_something") at ../gtk/gtkactionmuxer.c:601
action = <optimized out>
node = 0x5555559a3600 = {0x555555a4df40}
#20 0x00007ffff7ab4591 in gtk_action_muxer_primary_accel_changed (muxer=0x555555987a20 [GtkActionMuxer], action_name=0x555558013cf1 "win.do_something", action_and_target=0x555558013cf0 "|win.do_something") at ../gtk/gtkactionmuxer.c:601
action = <optimized out>
node = 0x7fff5002ae30 = {0x555555a4dac0}
#21 0x00007ffff7ab4591 in gtk_action_muxer_primary_accel_changed (muxer=0x55555556d940 [GtkActionMuxer], muxer@entry=0x7fffffffd1b8, action_name=0x555558013cf1 "win.do_something",
action_name@entry=0x0, action_and_target=action_and_target@entry=0x555558013cf0 "|win.do_something") at ../gtk/gtkactionmuxer.c:601
action = <optimized out>
node = 0x7fff5002ae20 = {0x555555987a20}
#22 0x00007ffff7ab6afd in gtk_action_muxer_set_primary_accel
(muxer=0x7fffffffd1b8, action_and_target=action_and_target@entry=0x555558013cf0 "|win.do_something", primary_accel=0x7ffff7ab4591 <gtk_action_muxer_primary_accel_changed+97> "H\213[\bH\205\333u\326[A\\A]A^]\303\017\037D") at ../gtk/gtkactionmuxer.c:1403
#23 0x00007ffff7838659 in gtk_application_set_accels_for_action (application=0x5555555730e0 [GtkApplication], detailed_action_name=<optimized out>, accels=0x7fffffffd298) at ../gtk/gtkapplication.c:1074
priv = <optimized out>
action_and_target = 0x555558013cf0 "|win.do_something"
__func__ = "gtk_application_set_accels_for_action"
#24 0x00005555555554af in activate (app=0x5555555730e0 [GtkApplication], user_data=0x0) at modelbutton.c:31
window = 0x555555a42340 [GtkApplicationWindow]
button = 0x555555a4c1a0 [GtkMenuButton]
menu = 0x555555a2faf0 [GMenu]
popover_menu = 0x555555a38200 [GtkPopoverMenu]
#28 0x00007ffff7212303 in <emit signal ??? on instance 0x5555555730e0 [GtkApplication]> (instance=instance@entry=0x5555555730e0, signal_id=<optimized out>, detail=detail@entry=0) at ../gobject/gsignal.c:3606
var_args = {{gp_offset = 24, fp_offset = 48, overflow_arg_area = 0x7fffffffd6e0, reg_save_area = 0x7fffffffd620}}
#25 0x00007ffff71f6502 in g_closure_invoke (closure=0x555555575e60, return_value=return_value@entry=0x0, n_param_values=1, param_values=param_values@entry=0x7fffffffd480, invocation_hint=invocation_hint@entry=0x7fffffffd400) at ../gobject/gclosure.c:832
marshal = 0x7ffff71f8800 <g_cclosure_marshal_VOID__VOID>
marshal_data = 0x0
in_marshal = 0
real_closure = 0x555555575e40
__func__ = "g_closure_invoke"
#26 0x00007ffff720b1c8 in signal_emit_unlocked_R (node=node@entry=0x55555556d3c0, detail=detail@entry=0, instance=instance@entry=0x5555555730e0, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7fffffffd480)
at ../gobject/gsignal.c:3796
tmp = <optimized out>
handler = 0x55555556a680
accumulator = 0x0
emission = {next = 0x0, instance = 0x5555555730e0, ihint = {signal_id = 8, detail = 0, run_type = (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACCUMULATOR_FIRST_RUN)}, state = EMISSION_RUN, chain_type = 0x4 [void]}
hlist = <optimized out>
handler_list = 0x55555556a680
return_accu = 0x0
accu = {g_type = 0x0, data = {{v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}, {v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}}}
signal_id = 8
max_sequential_handler_number = 50
return_value_altered = <optimized out>
#27 0x00007ffff7212135 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7fffffffd600) at ../gobject/gsignal.c:3549
instance_and_params = 0x7fffffffd480
signal_return_type = <optimized out>
param_values = 0x7fffffffd498
node = <optimized out>
i = <optimized out>
n_params = <optimized out>
__func__ = "g_signal_emit_valist"
#29 0x00007ffff733c597 in g_application_activate (application=application@entry=0x5555555730e0 [GtkApplication]) at ../gio/gapplication.c:2310
__func__ = "g_application_activate"
#30 0x00007ffff733c918 in g_application_real_local_command_line (application=0x5555555730e0 [GtkApplication], arguments=0x7fffffffd768, exit_status=0x7fffffffd764) at ../gio/gapplication.c:1146
--Type <RET> for more, q to quit, c to continue without paging--
error = 0x0
options = 0x555555574880
n_args = 1
#31 0x00007ffff733cac3 in g_application_run (application=0x5555555730e0 [GtkApplication], argc=<optimized out>, argv=<optimized out>) at ../gio/gapplication.c:2540
arguments = 0x555555579650
status = -1
context = 0x55555557a6b0
acquired_context = <optimized out>
__func__ = "g_application_run"
#32 0x000055555555559c in main (argc=1, argv=0x7fffffffd928) at modelbutton.c:47
app = 0x5555555730e0 [GtkApplication]
status = 0
action = 0x555555578800 [GSimpleAction]
(gdb)
Edited by Neui