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();
for (GtkWidget *label : _status_bar_labels) {
gtk_container_remove(GTK_CONTAINER(_status_bar), label);
for (GtkWidget *flow_box_child : _status_bar_labels) {
gtk_container_remove(GTK_CONTAINER(_status_bar), flow_box_child);
g_object_unref(flow_box_child);
}
_status_bar_collectors.clear();
_status_bar_labels.clear();
@ -252,7 +253,8 @@ idle() {
gtk_label_set_text(GTK_LABEL(_frame_rate_label), buffer);
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;
collectors.push_back(0);
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("");
gtk_container_add(GTK_CONTAINER(_status_bar), label);
_status_bar_labels.push_back(label);
GtkWidget *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);
}
// Gather the top-level collector list.
@ -639,15 +648,21 @@ update_status_bar() {
std::string text = def._name;
text += ": " + PStatGraph::format_number(value, PStatGraph::GBU_named | PStatGraph::GBU_show_units, def._level_units);
GtkWidget *flow_box_child;
GtkWidget *label;
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());
}
else {
label = gtk_label_new(text.c_str());
gtk_container_add(GTK_CONTAINER(_status_bar), label);
_status_bar_labels.push_back(label);
// See comment above
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);
@ -737,7 +752,8 @@ status_bar_button_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
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,
GDK_GRAVITY_NORTH_WEST,
GDK_GRAVITY_SOUTH_WEST, nullptr);
@ -855,7 +871,8 @@ handle_status_bar_popup(int item) {
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,
GDK_GRAVITY_NORTH_WEST,
GDK_GRAVITY_SOUTH_WEST, nullptr);

View File

@ -123,6 +123,7 @@ make_monitor(const NetAddress &address) {
if (_status_bar_label != nullptr) {
gtk_container_remove(GTK_CONTAINER(_status_bar), _status_bar_label);
g_object_unref(_status_bar_label);
_status_bar_label = nullptr;
}
@ -177,9 +178,16 @@ new_session() {
std::ostringstream strm;
strm << "Waiting for client to connect on port " << _port << "...";
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_widget_show(_status_bar_label);
g_object_ref(_status_bar_label);
}
gtk_widget_set_sensitive(_new_session_menu_item, FALSE);
@ -462,6 +470,7 @@ close_session() {
if (_status_bar_label != nullptr) {
gtk_container_remove(GTK_CONTAINER(_status_bar), _status_bar_label);
g_object_unref(_status_bar_label);
_status_bar_label = nullptr;
}