overlays: Fix use after free

- Overlay can be closed when secondary thread is asleep!
  Wait for it to wake before proceeding with deletion.
This commit is contained in:
kd-11 2020-02-07 12:57:21 +03:00 committed by kd-11
commit e45360de2b
3 changed files with 42 additions and 22 deletions

View file

@ -229,26 +229,30 @@ namespace rsx
} }
else else
{ {
thread_ctrl::spawn("dialog input thread", [&] std::scoped_lock lock(m_threadpool_mutex);
if (!exit)
{ {
if (interactive) m_workers.emplace_back([&]
{ {
if (auto error = run_input_loop()) if (interactive)
{ {
rsx_log.error("Dialog input loop exited with error code=%d", error); if (auto error = run_input_loop())
{
rsx_log.error("Dialog input loop exited with error code=%d", error);
}
} }
} else
else
{
while (!exit)
{ {
refresh(); while (!exit)
{
refresh();
// Only update the screen at about 60fps since updating it everytime slows down the process // Only update the screen at about 60fps since updating it everytime slows down the process
std::this_thread::sleep_for(16ms); std::this_thread::sleep_for(16ms);
}
} }
} });
}); }
} }
return CELL_OK; return CELL_OK;

View file

@ -308,11 +308,19 @@ namespace rsx
// Unreachable // Unreachable
return 0; return 0;
} }
void user_interface::close(bool use_callback) void user_interface::close(bool use_callback)
{ {
// Force unload // Force unload
exit = true; exit.release(true);
{
reader_lock lock(m_threadpool_mutex);
for (auto& worker : m_workers)
{
worker.join();
}
}
if (auto manager = g_fxo->get<display_manager>()) if (auto manager = g_fxo->get<display_manager>())
{ {
if (auto dlg = manager->get<rsx::overlays::message_dialog>()) if (auto dlg = manager->get<rsx::overlays::message_dialog>())

View file

@ -17,6 +17,8 @@
#include "Utilities/CPUStats.h" #include "Utilities/CPUStats.h"
#include "Utilities/Timer.h" #include "Utilities/Timer.h"
#include <list>
// Utils // Utils
std::string utf8_to_ascii8(const std::string& utf8_string); std::string utf8_to_ascii8(const std::string& utf8_string);
std::string utf16_to_ascii8(const std::u16string& utf16_string); std::string utf16_to_ascii8(const std::u16string& utf16_string);
@ -48,8 +50,9 @@ namespace rsx
}; };
// Interactable UI element // Interactable UI element
struct user_interface : overlay class user_interface : public overlay
{ {
public:
// Move this somewhere to avoid duplication // Move this somewhere to avoid duplication
enum selection_code enum selection_code
{ {
@ -76,19 +79,24 @@ namespace rsx
pad_button_max_enum pad_button_max_enum
}; };
protected:
Timer input_timer; Timer input_timer;
bool exit = false; atomic_t<bool> exit{ false };
s32 return_code = CELL_OK;
std::function<void(s32 status)> on_close; std::function<void(s32 status)> on_close;
shared_mutex m_threadpool_mutex;
std::list<std::thread> m_workers;
public:
s32 return_code = CELL_OK;
public:
void update() override {} void update() override {}
compiled_resource get_compiled() override = 0; compiled_resource get_compiled() override = 0;
virtual void on_button_pressed(pad_button /*button_press*/) virtual void on_button_pressed(pad_button /*button_press*/) {}
{
close();
}
void close(bool use_callback = true); void close(bool use_callback = true);