mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 03:29:43 -10:00
gfx_widgets: the menu state a widget iterate reads travels with the frame
The netplay ping widget asked the menu whether it was open, from gfx_widget_netplay_ping_iterate(), which the threaded wrapper runs on the video thread. The menu's flags are a read-modify-write on the main thread - runloop_check_state() clears two of them in the same expression - so the read raced the write, on a word the whole menu keeps its state in. The frame already carries those flags: video_driver_frame() copies them where the menu cannot be changing. The worker latches that copy before it iterates, and the widget reads the latch. Found with networking on. The threaded video suites had been run against a build configured without it, so the file this lives in was never compiled and the widget never ran.
This commit is contained in:
1 parent
3da8ee7485
commit
99d852a93b
3 files changed
+11
-1
No files matched your search
@@ -2790,6 +2790,7 @@ void gfx_widgets_worker_step(void *data,
|
||||
video_info->width, video_info->height);
|
||||
/* What the frame carried, not the settings the main thread writes:
|
||||
* this runs on the video thread under the threaded wrapper. */
|
||||
p_dispwidget->frame_menu_st_flags = (uint16_t)video_info->menu_st_flags;
|
||||
gfx_widgets_iterate_frame(
|
||||
video_info->width, video_info->height, video_info->fullscreen,
|
||||
video_info->widget_dir_assets,
|
||||
|
||||
@@ -335,6 +335,12 @@ typedef struct dispgfx_widget
|
||||
|
||||
char monochrome_png_path[PATH_MAX_LENGTH];
|
||||
char gfx_widgets_path[PATH_MAX_LENGTH];
|
||||
|
||||
/* The menu state the frame being iterated was built with. A widget
|
||||
* that wants to know whether the menu is open reads this rather
|
||||
* than the menu's own flags: those are a read-modify-write on the
|
||||
* main thread, and an iterate runs on the thread that draws. */
|
||||
uint16_t frame_menu_st_flags;
|
||||
} dispgfx_widget_t;
|
||||
|
||||
/* A widget */
|
||||
|
||||
@@ -10643,7 +10643,10 @@ static void gfx_widget_netplay_ping_iterate(void *user_data,
|
||||
netplay_t *netplay = net_st->data;
|
||||
settings_t *settings = config_get_ptr();
|
||||
#ifdef HAVE_MENU
|
||||
bool menu_open = menu_state_get_ptr()->flags &
|
||||
/* What the frame this iterate belongs to was built with: the menu's
|
||||
* own flags are a read-modify-write on the main thread, and this
|
||||
* runs on the thread that draws. */
|
||||
bool menu_open = dispwidget_get_ptr()->frame_menu_st_flags &
|
||||
MENU_ST_FLAG_ALIVE;
|
||||
#endif
|
||||
bool show_ping = settings->bools.netplay_ping_show;
|
||||
|
||||
Reference in new issue
Block a user