[vte/vte-0-62] widget: Reference terminals while processing
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte/vte-0-62] widget: Reference terminals while processing
- Date: Sat, 3 Oct 2020 09:26:15 +0000 (UTC)
commit bd7909c961c055d772b9005a7bc112e8c898b034
Author: Christian Persch <chpe src gnome org>
Date: Sat Oct 3 11:25:33 2020 +0200
widget: Reference terminals while processing
In some language bindings, the callbacks we emit during processing
may cause their GC to run, which could finalise a VteTerminal,
removing it from g_active_terminals list while we're iterating
over that list.
https://gitlab.gnome.org/GNOME/vte/-/issues/270
(cherry picked from commit de1ee80d07ef3d7da138bf7f03395685d7327d97)
src/vte.cc | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
---
diff --git a/src/vte.cc b/src/vte.cc
index 829e6630..c33b27c4 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -10282,6 +10282,33 @@ Terminal::process(bool emit_adj_changed)
return is_active;
}
+
+/* We need to keep a reference to the terminals in the
+ * g_active_terminals list while iterating over it, since
+ * in some language bindings the callbacks we emit
+ * during processing may cause their GC to run, causing
+ * later elements in this list to be removed from the list.
+ * See issue vte#270.
+ */
+
+static void
+unref_active_terminals(GList* list)
+{
+ g_list_free_full(list, GDestroyNotify(g_object_unref));
+}
+
+static auto
+ref_active_terminals() noexcept
+{
+ GList* list = nullptr;
+ for (auto l = g_active_terminals; l != nullptr; l = l->next) {
+ auto that = reinterpret_cast<vte::terminal::Terminal*>(l->data);
+ list = g_list_prepend(list, g_object_ref(that->vte_terminal()));
+ }
+
+ return std::unique_ptr<GList, decltype(&unref_active_terminals)>{list, &unref_active_terminals};
+}
+
/* This function is called after DISPLAY_TIMEOUT ms.
* It makes sure initial output is never delayed by more than DISPLAY_TIMEOUT
*/
@@ -10299,6 +10326,8 @@ try
"Process timeout: %d active\n",
g_list_length(g_active_terminals));
+ auto death_grip = ref_active_terminals();
+
for (l = g_active_terminals; l != NULL; l = next) {
auto that = reinterpret_cast<vte::terminal::Terminal*>(l->data);
bool active;
@@ -10391,6 +10420,8 @@ update_repeat_timeout (gpointer data)
"Repeat timeout: %d active\n",
g_list_length(g_active_terminals));
+ auto death_grip = ref_active_terminals();
+
for (l = g_active_terminals; l != NULL; l = next) {
auto that = reinterpret_cast<vte::terminal::Terminal*>(l->data);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]