1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-23 15:52:55 +01:00

Fix a crash when closing windows would open other windows (#24972)

This could happen when trying to open a ride, which does not have
entrance or exit, from the ride list window. The `OnClose` handler would
want to open a window for placing said elements causing invalidation of
the window list.

20ac77904b/src/openrct2-ui/windows/RideConstruction.cpp (L324)
This commit is contained in:
Michał Janiszewski
2025-08-16 00:07:07 +02:00
committed by GitHub
parent 5a8150a941
commit eb5dababc9
2 changed files with 16 additions and 2 deletions

View File

@@ -20,6 +20,7 @@
- Fix: [#24955] Hybrid Zero G Rolls do not fully block metal supports. - Fix: [#24955] Hybrid Zero G Rolls do not fully block metal supports.
- Fix: [#24958] Android: fix crash when device is offline. - Fix: [#24958] Android: fix crash when device is offline.
- Fix: [#24961] Queues with corner connections set with the tile inspector draw incorrect sprites. - Fix: [#24961] Queues with corner connections set with the tile inspector draw incorrect sprites.
- Fix: [#24972] Fix crash when closing windows would open other windows.
0.4.25 (2025-08-03) 0.4.25 (2025-08-03)
------------------------------------------------------------------------ ------------------------------------------------------------------------

View File

@@ -981,6 +981,10 @@ public:
template<typename TPred> template<typename TPred>
void CloseByCondition(TPred pred, uint32_t flags = WindowCloseFlags::None) void CloseByCondition(TPred pred, uint32_t flags = WindowCloseFlags::None)
{ {
// Collect windows to close first to avoid iterator invalidation
// when Close() might trigger window creation via OnClose()
std::vector<WindowBase*> windowsToClose;
for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); ++it) for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); ++it)
{ {
auto& wnd = *(*it); auto& wnd = *(*it);
@@ -989,13 +993,22 @@ public:
if (pred(&wnd)) if (pred(&wnd))
{ {
Close(wnd); windowsToClose.push_back(&wnd);
if (flags & WindowCloseFlags::CloseSingle) if (flags & WindowCloseFlags::CloseSingle)
{ {
return; break;
} }
} }
} }
// Now close the collected windows
for (auto* wnd : windowsToClose)
{
if (!(wnd->flags & WF_DEAD))
{
Close(*wnd);
}
}
} }
/** /**