Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL_SetObjectsInvalid assertion failure when closing a minimal tray example #11893

Open
madebr opened this issue Jan 9, 2025 · 10 comments
Open
Assignees
Milestone

Comments

@madebr
Copy link
Contributor

madebr commented Jan 9, 2025

Using the minimal tray example from #11892, I get an assertion failure when closing the window, or pressing CTRL+C

#define SDL_MAIN_USE_CALLBACKS 1
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>

static SDL_Window* g_window;

SDL_AppResult SDL_AppIterate(void *appstate)
{
    return SDL_APP_CONTINUE;
}

SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{

    if (!SDL_Init(SDL_INIT_VIDEO)) {
        return SDL_APP_FAILURE;
    }

    g_window = SDL_CreateWindow("tray example", 800, 600, 0);

    if (g_window == NULL) {
        return SDL_APP_FAILURE;
    }

    SDL_Tray* tray = SDL_CreateTray(NULL, "Happy Tray Icon");

    if (tray == NULL) {
        return SDL_APP_FAILURE;
    }

    SDL_TrayMenu* menu = SDL_CreateTrayMenu(tray);

    SDL_InsertTrayEntryAt(menu, 0, "entry", SDL_TRAYENTRY_BUTTON);

    return SDL_APP_CONTINUE;
}

SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{
    switch (event->type) {
    case SDL_EVENT_QUIT:
        SDL_Log("SDL_EVENT_QUIT");
        return SDL_APP_SUCCESS;
    case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
        SDL_Log("SDL_EVENT_WINDOW_CLOSE_REQUESTED");
        if (SDL_GetWindowFromID(event->window.windowID) == g_window) {
            SDL_DestroyWindow(g_window);
            return SDL_APP_SUCCESS;
        }
    }
    return SDL_APP_CONTINUE;
}

void SDL_AppQuit(void *appstate, SDL_AppResult result)
{
}

These are the messages printed on stdout:

(a.out:175235): Gtk-CRITICAL **: 03:37:12.214: gtk_widget_get_scale_factor: assertion 'GTK_IS_WIDGET (widget)' failed
^CSDL_EVENT_QUIT
Leaked thread (0x38749cc0)
WARNING: 

Assertion failure at SDL_SetObjectsInvalid (/home/maarten/projects/SDL/src/SDL_utils.c:226), triggered 1 time:
  'SDL_HashTableEmpty(SDL_objects)'

This is the backtrace:

#0  0x00007ffff7a3cfcf in SDL_SetObjectsInvalid () at /home/maarten/projects/SDL/src/SDL_utils.c:226
#1  0x00007ffff7a36e7d in SDL_Quit_REAL () at /home/maarten/projects/SDL/src/SDL.c:653
#2  0x00007ffff7aacb0b in SDL_QuitMainCallbacks (result=SDL_APP_SUCCESS)
    at /home/maarten/projects/SDL/src/main/SDL_main_callbacks.c:147
#3  0x00007ffff7d0608f in SDL_EnterAppMainCallbacks_REAL
    (argc=1, argv=0x7fffffffdd08, appinit=0x401223 <SDL_AppInit>, appiter=0x401214 <SDL_AppIterate>, appevent=0x4012d7 <SDL_AppEvent>, appquit=0x40135c <SDL_AppQuit>)
    at /home/maarten/projects/SDL/src/main/generic/SDL_sysmain_callbacks.c:91
#4  0x00007ffff7a6bb48 in SDL_EnterAppMainCallbacks
    (a=1, b=0x7fffffffdd08, c=0x401223 <SDL_AppInit>, d=0x401214 <SDL_AppIterate>, e=0x4012d7 <SDL_AppEvent>, f=0x40135c <SDL_AppQuit>) at /home/maarten/projects/SDL/src/dynapi/SDL_dynapi_procs.h:207
#5  0x00000000004011e9 in SDL_main ()
#6  0x00007ffff7aacb50 in SDL_RunApp_REAL
    (argc=1, argv=0x7fffffffdd08, mainFunction=0x4011b6 <SDL_main>, reserved=0x0)
    at /home/maarten/projects/SDL/src/main/SDL_runapp.c:40
#7  0x00007ffff7a6435e in SDL_RunApp_DEFAULT (a=1, b=0x7fffffffdd08, c=0x4011b6 <SDL_main>, d=0x0)
    at /home/maarten/projects/SDL/src/dynapi/SDL_dynapi_procs.h:804
#8  0x00007ffff7a70bb1 in SDL_RunApp (a=1, b=0x7fffffffdd08, c=0x4011b6 <SDL_main>, d=0x0)
    at /home/maarten/projects/SDL/src/dynapi/SDL_dynapi_procs.h:804
#9  0x0000000000401212 in main ()

@slouken slouken added this to the 3.2.0 milestone Jan 9, 2025
@slouken
Copy link
Collaborator

slouken commented Jan 9, 2025

@Semphriss, can you take a look at this?

@Semphriss
Copy link
Contributor

Taking a look at this, I get a "Leaked thread (0xaddress)", but I get no assertion error. I compiled using the latest commit on the main branch (00b23a0). I'll investigate the threading issue and see if I randomly get the assertion error.

What system is this? I'll try to see if this is a system-specific issue.

@madebr
Copy link
Contributor Author

madebr commented Jan 9, 2025

Taking a look at this, I get a "Leaked thread (0xaddress)", but I get no assertion error. I compiled using the latest commit on the main branch (00b23a0). I'll investigate the threading issue and see if I randomly get the assertion error.

The error happens every execution on my system. So it's not random at all (for me).

What system is this? I'll try to see if this is a system-specific issue.

My system is Fedora 39 (which is EOL).
You probably know already, but my desktop environment (GNOME3) does not display any tray.

If I add SDL_DestroyTray(g_tray); to the SDL_EVENT_WINDOW_CLOSE_REQUESTED event handles or in SDL_AppQuit, the assertion failure does not happen.

Also, I built SDL3 with -DCMAKE_BUILD_TYPE=Debug.

@slouken
Copy link
Collaborator

slouken commented Jan 10, 2025

We currently don't clean up trays on quit, maybe we should? Technically what you're doing (leaking a tray) is resulting in the expected behavior.

@Semphriss
Copy link
Contributor

I can make trays clean up on quit if it can help, but I'd like to investigate the bug further. Bugs like this can sometimes be symptomatic of another problem, and I'd like to see if it can cause other issues down the line, other than on quit.

@Green-Sky
Copy link
Contributor

Green-Sky commented Jan 10, 2025

I also just had a random crash, which might have been triggered by changing the icon, not sure:

tomato: ../src/cairo-surface.c:938: cairo_surface_reference: Assertion `CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count)' failed.

Thread 2 "tray gtk" received signal SIGABRT, Aborted.
[Switching to LWP 624082]
0x00007ffff74a2efc in __pthread_kill_implementation ()
   from /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/libc.so.6
(gdb) bt
#0  0x00007ffff74a2efc in __pthread_kill_implementation () from /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/libc.so.6
#1  0x00007ffff7452e86 in raise () from /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/libc.so.6
#2  0x00007ffff743b935 in abort () from /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/libc.so.6
#3  0x00007ffff743b859 in __assert_fail_base.cold () from /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/libc.so.6
#4  0x00007ffff744b6e6 in __assert_fail () from /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/libc.so.6
#5  0x00007ffff0e037ad in cairo_surface_reference () from /nix/store/ag0yl2kh55ab1n3jq9d3ha0z0qi8krm2-cairo-1.18.0/lib/libcairo.so.2
#6  0x00007ffff0db9d68 in _cairo_gstate_init () from /nix/store/ag0yl2kh55ab1n3jq9d3ha0z0qi8krm2-cairo-1.18.0/lib/libcairo.so.2
#7  0x00007ffff0db6514 in _cairo_default_context_create () from /nix/store/ag0yl2kh55ab1n3jq9d3ha0z0qi8krm2-cairo-1.18.0/lib/libcairo.so.2
#8  0x00007ffff11cb4ab in get_surface_size () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#9  0x00007ffff11cbf46 in _gtk_icon_helper_get_size () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#10 0x00007ffff11e0eab in gtk_image_render_contents () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#11 0x00007ffff112dbbd in gtk_css_custom_gadget_draw () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#12 0x00007ffff1133bff in gtk_css_gadget_draw () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#13 0x00007ffff11e08f1 in gtk_image_draw () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#14 0x00007ffff135d424 in gtk_widget_draw_internal () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#15 0x00007ffff1127aa1 in gtk_container_propagate_draw () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#16 0x00007ffff1127bac in gtk_container_draw () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#17 0x00007ffff141344e in gtk_tray_icon_draw () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#18 0x00007ffff135d424 in gtk_widget_draw_internal () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#19 0x00007ffff13668a8 in gtk_widget_render () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#20 0x00007ffff12079bf in gtk_main_do_event () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#21 0x00007ffff18ec745 in _gdk_event_emit () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgdk-3.so.0
#22 0x00007ffff18fb689 in _gdk_window_process_updates_recurse_helper () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgdk-3.so.0
#23 0x00007ffff18fd296 in gdk_window_process_updates_internal () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgdk-3.so.0
#24 0x00007ffff18fd497 in gdk_window_process_updates_with_mode () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgdk-3.so.0
#25 0x00007ffff1833861 in _g_closure_invoke_va () from /nix/store/yl0m9g65iv1wa6lrbbk959ag2ahw355b-glib-2.80.2/lib/libgobject-2.0.so.0
#26 0x00007ffff184969c in signal_emit_valist_unlocked () from /nix/store/yl0m9g65iv1wa6lrbbk959ag2ahw355b-glib-2.80.2/lib/libgobject-2.0.so.0
#27 0x00007ffff184f2c2 in g_signal_emit_valist () from /nix/store/yl0m9g65iv1wa6lrbbk959ag2ahw355b-glib-2.80.2/lib/libgobject-2.0.so.0
#28 0x00007ffff184f36f in g_signal_emit () from /nix/store/yl0m9g65iv1wa6lrbbk959ag2ahw355b-glib-2.80.2/lib/libgobject-2.0.so.0
#29 0x00007ffff18f5a8f in gdk_frame_clock_paint_idle () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgdk-3.so.0
#30 0x00007ffff18e1b37 in gdk_threads_dispatch () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgdk-3.so.0
#31 0x00007ffff0aaec7a in g_timeout_dispatch () from /nix/store/yl0m9g65iv1wa6lrbbk959ag2ahw355b-glib-2.80.2/lib/libglib-2.0.so.0
#32 0x00007ffff0aaae39 in g_main_dispatch () from /nix/store/yl0m9g65iv1wa6lrbbk959ag2ahw355b-glib-2.80.2/lib/libglib-2.0.so.0
#33 0x00007ffff0aadfd7 in g_main_context_iterate_unlocked.isra () from /nix/store/yl0m9g65iv1wa6lrbbk959ag2ahw355b-glib-2.80.2/lib/libglib-2.0.so.0
#34 0x00007ffff0aae88f in g_main_loop_run () from /nix/store/yl0m9g65iv1wa6lrbbk959ag2ahw355b-glib-2.80.2/lib/libglib-2.0.so.0
#35 0x00007ffff1206b35 in gtk_main () from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#36 0x00000000005c74d9 in main_gtk_thread (data=data@entry=0x0) at /nix/store/2pwh4vl9h00kina3vwxykrjgwja1j95h-source/src/tray/unix/SDL_tray.c:131
#37 0x0000000000586bca in SDL_RunThread (thread=0x13dfe90) at /nix/store/2pwh4vl9h00kina3vwxykrjgwja1j95h-source/src/thread/SDL_thread.c:328
#38 0x00000000005d550f in RunThread (data=<optimized out>) at /nix/store/2pwh4vl9h00kina3vwxykrjgwja1j95h-source/src/thread/pthread/SDL_systhread.c:73
#39 0x00007ffff74a1272 in start_thread () from /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/libc.so.6
#40 0x00007ffff751cdec in clone3 () from /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/libc.so.6

commit 22422f7 (3.1.8)

I could not reproduce this yet, but I also had a situation where the menu just stopped working (no longer poped up when clicking the icon).

edit: caught another crash on exit this time:

[LWP 772709 exited]

Thread 2 "tray gtk" received signal SIGSEGV, Segmentation fault.
[Switching to LWP 772703]
0x00007ffff4826f4b in prop_array_teardown ()
   from /nix/store/vfnsmcw16g72gl51d01zw9kdab1178l9-libdbusmenu-gtk3-16.04.0/lib/libdbusmenu-glib.so.4
(gdb) bt
#0  0x00007ffff4826f4b in prop_array_teardown ()
   from /nix/store/vfnsmcw16g72gl51d01zw9kdab1178l9-libdbusmenu-gtk3-16.04.0/lib/libdbusmenu-glib.so.4
#1  0x00007ffff48272d1 in menuitem_property_idle ()
   from /nix/store/vfnsmcw16g72gl51d01zw9kdab1178l9-libdbusmenu-gtk3-16.04.0/lib/libdbusmenu-glib.so.4
#2  0x00007ffff0aaae39 in g_main_dispatch ()
   from /nix/store/yl0m9g65iv1wa6lrbbk959ag2ahw355b-glib-2.80.2/lib/libglib-2.0.so.0
#3  0x00007ffff0aadfd7 in g_main_context_iterate_unlocked.isra ()
   from /nix/store/yl0m9g65iv1wa6lrbbk959ag2ahw355b-glib-2.80.2/lib/libglib-2.0.so.0
#4  0x00007ffff0aae88f in g_main_loop_run ()
   from /nix/store/yl0m9g65iv1wa6lrbbk959ag2ahw355b-glib-2.80.2/lib/libglib-2.0.so.0
#5  0x00007ffff1206b35 in gtk_main ()
   from /nix/store/wky1jsp6g0vdn7i81g1s5yvha6fnadpr-gtk+3-3.24.42/lib/libgtk-3.so.0
#6  0x00000000005c7505 in main_gtk_thread (data=data@entry=0x0)
    at /nix/store/2pwh4vl9h00kina3vwxykrjgwja1j95h-source/src/tray/unix/SDL_tray.c:131
#7  0x0000000000586bf6 in SDL_RunThread (thread=0x13df8d0)
    at /nix/store/2pwh4vl9h00kina3vwxykrjgwja1j95h-source/src/thread/SDL_thread.c:328
#8  0x00000000005d553b in RunThread (data=<optimized out>)
    at /nix/store/2pwh4vl9h00kina3vwxykrjgwja1j95h-source/src/thread/pthread/SDL_systhread.c:73
#9  0x00007ffff74a1272 in start_thread ()
   from /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/libc.so.6
#10 0x00007ffff751cdec in clone3 () from /nix/store/dbcw19dshdwnxdv5q2g6wldj6syyvq7l-glibc-2.39-52/lib/libc.so.6

edit2: it seems to have taken another program with it (unrelated program also having a tray icon) until i ended the debugging session.

@slouken
Copy link
Collaborator

slouken commented Jan 15, 2025

@Green-Sky, please create new issues for individual crashes, thanks!

@slouken
Copy link
Collaborator

slouken commented Jan 15, 2025

@Semphriss, let's go ahead and clean up the trays when the video subsystem is shutdown. Conceptually they're linked, right?

@Semphriss
Copy link
Contributor

Conceptually they're linked, right?

It's technically separate, but it depends on video-related functions for the icon handling (SDL_Surface). I can keep a list of trays and destroy them on quit.

In the event someone unwisely destroys their trays after SDL_Quit()ting, should I ensure that destroying a tray twice does not result in double-frees?

@slouken
Copy link
Collaborator

slouken commented Jan 15, 2025

I can keep a list of trays and destroy them on quit.

That sounds good.

In the event someone unwisely destroys their trays after SDL_Quit()ting, should I ensure that destroying a tray twice does not result in double-frees?

You can add tray as a new object type in SDL_utils_c.h and use the related functions to validate the pointers, take a look at SDL_OBJECT_TYPE_WINDOW as an example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants