Crash receiving device event after any device listener has been destroyed
Steps to reproduce:
- create an AtspiDeviceListener
- attach it to listen to events (I used a keystroke listener)
- destroy that listener
- do that twice (or more, until it crashes)
The crash is in _atspi_dbus_handle_DeviceEvent()
:
0x00007ffff572a56e in _atspi_dbus_handle_DeviceEvent (bus=<optimized out>, message=0x5555562e3a00, data=<optimized out>) at ../atspi/atspi-device-listener.c:377
377 ../atspi/atspi-device-listener.c: No such file or directory.
(gdb) bt
#0 0x00007ffff572a56e in _atspi_dbus_handle_DeviceEvent (bus=<optimized out>, message=0x5555562e3a00, data=<optimized out>) at ../atspi/atspi-device-listener.c:377
#1 0x00007ffff5731791 in process_deferred_message (closure=0x5555562c5b80) at ../atspi/atspi-misc.c:747
#2 process_deferred_messages () at ../atspi/atspi-misc.c:777
#3 0x00007ffff57318c3 in process_deferred_messages () at ../atspi/atspi-misc.c:789
#4 process_deferred_messages_callback (data=<optimized out>) at ../atspi/atspi-misc.c:789
#5 0x00007ffff740b4de in g_main_dispatch (context=0x5555555b2360) at ../../../glib/gmain.c:3309
#6 g_main_context_dispatch (context=context@entry=0x5555555b2360) at ../../../glib/gmain.c:3974
#7 0x00007ffff740b890 in g_main_context_iterate (context=0x5555555b2360, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../../../glib/gmain.c:4047
#8 0x00007ffff740bb63 in g_main_loop_run (loop=0x5555558cf370) at ../../../glib/gmain.c:4241
#9 0x00007ffff7960e05 in gtk_main () at ../../../../gtk/gtkmain.c:1328
#10 0x0000555555559667 in main ()
Valgrind is more helpful:
==221750== Invalid read of size 4
==221750== at 0x70DCFC4: id_is_free (atspi-device-listener.c:112)
==221750== by 0x70DCFC4: atspi_device_listener_init (atspi-device-listener.c:171)
==221750== by 0x530BE6C: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.6400.1)
==221750== Address 0x212da5b8 is 24 bytes inside a block of size 40 free'd
==221750== at 0x48379AB: free (vg_replace_malloc.c:540)
==221750== by 0x530C06B: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.6400.1)
==221750== by 0x212DB22F: ???
==221750== Block was alloc'd at
==221750== at 0x483677F: malloc (vg_replace_malloc.c:309)
==221750== by 0x53871C8: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.1)
==221750== by 0x76A20FF: ???
==221750== by 0x539F1F1: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.1)
==221750== by 0x3: ???
==221750== by 0x48DEE4E: ??? (in /lib/x86_64-linux-gnu/libdbus-1.so.3.19.11)
==221750== by 0x27: ???
==221750== by 0x27: ???
==221750==
==221750== Invalid read of size 4
==221750== at 0x70DD480: _atspi_dbus_handle_DeviceEvent (atspi-device-listener.c:367)
==221750== by 0x70E4790: process_deferred_message (atspi-misc.c:747)
==221750== by 0x70E4790: process_deferred_messages.part.0 (atspi-misc.c:777)
==221750== by 0x70E48C2: process_deferred_messages (atspi-misc.c:788)
==221750== by 0x70E48C2: process_deferred_messages_callback (atspi-misc.c:789)
==221750== by 0x53814DD: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.1)
==221750== by 0xF076BEE: msd_rfkill_plugin_class_init (in /media/data/Hypra/dev/mate-desktop/_install/mate-settings-daemon/lib/mate-settings-daemon/librfkill.so)
==221750== Address 0x212da5b8 is 24 bytes inside a block of size 40 free'd
==221750== at 0x48379AB: free (vg_replace_malloc.c:540)
==221750== by 0x530C06B: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.6400.1)
==221750== by 0x212DB22F: ???
==221750== Block was alloc'd at
==221750== at 0x483677F: malloc (vg_replace_malloc.c:309)
==221750== by 0x53871C8: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.1)
==221750== by 0x76A20FF: ???
==221750== by 0x539F1F1: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.1)
==221750== by 0x3: ???
==221750== by 0x48DEE4E: ??? (in /lib/x86_64-linux-gnu/libdbus-1.so.3.19.11)
==221750== by 0x27: ???
==221750== by 0x27: ???
Some of that info is not really relevant, but atspi-device-listener.c:112
is useful: actually, I believe the problem is that in atspi-device-listener.c there is that device_listeners
list that gets appended to in atspi_device_listener_init()
(so whenever a device listener is created), but nothing gets removed from it, ever, even when one of the object it holds has been destroyed. This leads to accessing invalid memory when iterating that list and checking the IDs.
I would guess the right fix would be to remove the destroyed listeners, i.e. device_listeners = g_list_remove (device_listeners, listener)
in atspi_device_listener_finalize()
. If that's the right fix I can create a MR if you want -- or just do it, it looks trivial.