Destroy timeouts on Widget deletion.

Timeouts would tick, even after the parent Widget is long gone causing
use-after-free bugs.
This commit is contained in:
scorpion-26 2024-03-15 19:33:19 +01:00
parent 5a2f75dd0d
commit 09c533a5e6
2 changed files with 14 additions and 3 deletions

View file

@ -49,7 +49,12 @@ Widget::~Widget()
{ {
if (m_Widget) if (m_Widget)
{ {
LOG("Destroy widget and its children"); // LOG("Destroy widget and its children");
for (guint timeout : m_Timeouts)
{
g_source_remove(timeout);
}
m_Timeouts.clear();
m_Childs.clear(); m_Childs.clear();
gtk_widget_destroy(m_Widget); gtk_widget_destroy(m_Widget);
} }
@ -178,7 +183,8 @@ void Widget::ApplyPropertiesToWidget()
// Apply style // Apply style
auto style = gtk_widget_get_style_context(m_Widget); auto style = gtk_widget_get_style_context(m_Widget);
gtk_style_context_add_class(style, m_CssClass.c_str()); gtk_style_context_add_class(style, m_CssClass.c_str());
for (auto& cssClass : m_AdditionalClasses) { for (auto& cssClass : m_AdditionalClasses)
{
gtk_style_context_add_class(style, cssClass.c_str()); gtk_style_context_add_class(style, cssClass.c_str());
} }

View file

@ -135,6 +135,7 @@ public:
{ {
TimerCallback<TWidget> timeoutFn; TimerCallback<TWidget> timeoutFn;
Widget* thisWidget; Widget* thisWidget;
guint id;
}; };
TimerPayload* payload = new TimerPayload(); TimerPayload* payload = new TimerPayload();
payload->thisWidget = this; payload->thisWidget = this;
@ -145,6 +146,7 @@ public:
TimerResult result = payload->timeoutFn(*(TWidget*)payload->thisWidget); TimerResult result = payload->timeoutFn(*(TWidget*)payload->thisWidget);
if (result == TimerResult::Delete) if (result == TimerResult::Delete)
{ {
payload->thisWidget->m_Timeouts.erase(payload->id);
delete payload; delete payload;
return false; return false;
} }
@ -157,7 +159,8 @@ public:
return; return;
} }
} }
g_timeout_add(timeoutMS, +fn, payload); payload->id = g_timeout_add(timeoutMS, +fn, payload);
m_Timeouts.insert(payload->id);
} }
GtkWidget* Get() { return m_Widget; }; GtkWidget* Get() { return m_Widget; };
@ -182,6 +185,8 @@ protected:
Transform m_VerticalTransform; // Y Transform m_VerticalTransform; // Y
Callback<Widget> m_OnCreate; Callback<Widget> m_OnCreate;
std::unordered_set<guint> m_Timeouts;
}; };
class Box : public Widget class Box : public Widget