pstats: Workaround for Gtk bug that causes UI to crash when a session is closed

As workaround for https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/2029, we manually create a GtkFlowBoxChild instance and attach the label to it and increase its reference count so it it not prematurely destroyed when removed from the GtkFlowBox, causing the UI to segfault.
This commit is contained in:
LD 2024-01-31 21:24:49 +01:00 committed by rdb
parent a9f6e6fd8a
commit 676a6df593
2 changed files with 37 additions and 11 deletions

View File

@ -60,8 +60,9 @@ close() {
remove_all_graphs(); remove_all_graphs();
for (GtkWidget *label : _status_bar_labels) { for (GtkWidget *flow_box_child : _status_bar_labels) {
gtk_container_remove(GTK_CONTAINER(_status_bar), label); gtk_container_remove(GTK_CONTAINER(_status_bar), flow_box_child);
g_object_unref(flow_box_child);
} }
_status_bar_collectors.clear(); _status_bar_collectors.clear();
_status_bar_labels.clear(); _status_bar_labels.clear();
@ -252,7 +253,8 @@ idle() {
gtk_label_set_text(GTK_LABEL(_frame_rate_label), buffer); gtk_label_set_text(GTK_LABEL(_frame_rate_label), buffer);
if (!_status_bar_labels.empty()) { if (!_status_bar_labels.empty()) {
gtk_label_set_text(GTK_LABEL(_status_bar_labels[0]), buffer); GtkWidget *label = gtk_bin_get_child(GTK_BIN(_status_bar_labels[0]));
gtk_label_set_text(GTK_LABEL(label), buffer);
} }
} }
} }
@ -607,9 +609,16 @@ update_status_bar() {
size_t li = 1; size_t li = 1;
collectors.push_back(0); collectors.push_back(0);
if (_status_bar_labels.empty()) { if (_status_bar_labels.empty()) {
// As workaround for https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/2029
// We manually create a GtkFlowBoxChild instance and attach the label to it
// and increase its reference count so it it not prematurely destroyed when
// removed from the GtkFlowBox, causing the app to segfault.
GtkWidget *label = gtk_label_new(""); GtkWidget *label = gtk_label_new("");
gtk_container_add(GTK_CONTAINER(_status_bar), label); GtkWidget *flow_box_child = gtk_flow_box_child_new();
_status_bar_labels.push_back(label); gtk_container_add(GTK_CONTAINER(flow_box_child), label);
gtk_container_add(GTK_CONTAINER(_status_bar), flow_box_child);
_status_bar_labels.push_back(flow_box_child);
g_object_ref(flow_box_child);
} }
// Gather the top-level collector list. // Gather the top-level collector list.
@ -639,15 +648,21 @@ update_status_bar() {
std::string text = def._name; std::string text = def._name;
text += ": " + PStatGraph::format_number(value, PStatGraph::GBU_named | PStatGraph::GBU_show_units, def._level_units); text += ": " + PStatGraph::format_number(value, PStatGraph::GBU_named | PStatGraph::GBU_show_units, def._level_units);
GtkWidget *flow_box_child;
GtkWidget *label; GtkWidget *label;
if (li < _status_bar_labels.size()) { if (li < _status_bar_labels.size()) {
label = _status_bar_labels[li++]; flow_box_child = _status_bar_labels[li++];
label = gtk_bin_get_child(GTK_BIN(flow_box_child));
gtk_label_set_text(GTK_LABEL(label), text.c_str()); gtk_label_set_text(GTK_LABEL(label), text.c_str());
} }
else { else {
label = gtk_label_new(text.c_str()); label = gtk_label_new(text.c_str());
gtk_container_add(GTK_CONTAINER(_status_bar), label); // See comment above
_status_bar_labels.push_back(label); flow_box_child = gtk_flow_box_child_new();
gtk_container_add(GTK_CONTAINER(flow_box_child), label);
gtk_container_add(GTK_CONTAINER(_status_bar), flow_box_child);
_status_bar_labels.push_back(flow_box_child);
g_object_ref(flow_box_child);
} }
collectors.push_back(collector); collectors.push_back(collector);
@ -737,7 +752,8 @@ status_bar_button_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
gtk_widget_show_all(menu); gtk_widget_show_all(menu);
GtkWidget *label = monitor->_status_bar_labels[index]; GtkWidget *flow_box_child = monitor->_status_bar_labels[index];
GtkWidget *label = gtk_bin_get_child(GTK_BIN(flow_box_child));
gtk_menu_popup_at_widget(GTK_MENU(menu), label, gtk_menu_popup_at_widget(GTK_MENU(menu), label,
GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST,
GDK_GRAVITY_SOUTH_WEST, nullptr); GDK_GRAVITY_SOUTH_WEST, nullptr);
@ -855,7 +871,8 @@ handle_status_bar_popup(int item) {
gtk_widget_show_all(menu); gtk_widget_show_all(menu);
GtkWidget *label = _status_bar_labels[item]; GtkWidget *flow_box_child = _status_bar_labels[item];
GtkWidget *label = gtk_bin_get_child(GTK_BIN(flow_box_child));
gtk_menu_popup_at_widget(GTK_MENU(menu), label, gtk_menu_popup_at_widget(GTK_MENU(menu), label,
GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST,
GDK_GRAVITY_SOUTH_WEST, nullptr); GDK_GRAVITY_SOUTH_WEST, nullptr);

View File

@ -123,6 +123,7 @@ make_monitor(const NetAddress &address) {
if (_status_bar_label != nullptr) { if (_status_bar_label != nullptr) {
gtk_container_remove(GTK_CONTAINER(_status_bar), _status_bar_label); gtk_container_remove(GTK_CONTAINER(_status_bar), _status_bar_label);
g_object_unref(_status_bar_label);
_status_bar_label = nullptr; _status_bar_label = nullptr;
} }
@ -177,9 +178,16 @@ new_session() {
std::ostringstream strm; std::ostringstream strm;
strm << "Waiting for client to connect on port " << _port << "..."; strm << "Waiting for client to connect on port " << _port << "...";
std::string title = strm.str(); std::string title = strm.str();
_status_bar_label = gtk_label_new(title.c_str()); // As workaround for https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/2029
// We manually create a GtkFlowBoxChild instance and attach the label to it
// and increase its reference count so it it not prematurely destroyed when
// removed from the GtkFlowBox, causing the app to segfault.
GtkWidget * label = gtk_label_new(title.c_str());
_status_bar_label = gtk_flow_box_child_new();
gtk_container_add(GTK_CONTAINER(_status_bar_label), label);
gtk_container_add(GTK_CONTAINER(_status_bar), _status_bar_label); gtk_container_add(GTK_CONTAINER(_status_bar), _status_bar_label);
gtk_widget_show(_status_bar_label); gtk_widget_show(_status_bar_label);
g_object_ref(_status_bar_label);
} }
gtk_widget_set_sensitive(_new_session_menu_item, FALSE); gtk_widget_set_sensitive(_new_session_menu_item, FALSE);
@ -462,6 +470,7 @@ close_session() {
if (_status_bar_label != nullptr) { if (_status_bar_label != nullptr) {
gtk_container_remove(GTK_CONTAINER(_status_bar), _status_bar_label); gtk_container_remove(GTK_CONTAINER(_status_bar), _status_bar_label);
g_object_unref(_status_bar_label);
_status_bar_label = nullptr; _status_bar_label = nullptr;
} }