[meld] vcview: Fix invalid tree iter crash with queued refreshes (bgo#787256)



commit 6b7cb302e485d69b9f5f52331ee73a94efe2f616
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Sat Sep 30 13:32:57 2017 +1000

    vcview: Fix invalid tree iter crash with queued refreshes (bgo#787256)
    
    The crash observed was caused by operations on the tree iter after it
    has become invalid due to tree manipulation. Because we queue partial
    refreshes to an idle loop when the tree is in non-flattened mode, we
    could get in a situation where we'd queued multiple refreshes on
    different valid-at-the-time tree iterators, and all of the iterators
    after the first were invalidated by the refresh of the first.
    
    The solution used here is to simple pass a path around to our
    recursive tree construction, and to allow that helper to do the row
    replacement in situations where it's required.
    
    This is most easily triggerable with SVN, because we queue a refresh for
    each folder/file that you add, though it is probably reproducable in
    other cases as well.

 meld/vcview.py |   31 +++++++++++++++++++++++--------
 1 files changed, 23 insertions(+), 8 deletions(-)
---
diff --git a/meld/vcview.py b/meld/vcview.py
index b165f63..19b839b 100644
--- a/meld/vcview.py
+++ b/meld/vcview.py
@@ -311,6 +311,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
             return
 
         root = self.model.get_iter_first()
+        root_path = self.model.get_path(root)
 
         try:
             self.model.set_value(
@@ -319,7 +320,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
             pass
 
         self.scheduler.add_task(self.vc.refresh_vc_state)
-        self.scheduler.add_task(self._search_recursively_iter(root))
+        self.scheduler.add_task(self._search_recursively_iter(root_path))
         self.scheduler.add_task(self.on_treeview_selection_changed)
         self.scheduler.add_task(self.on_treeview_cursor_changed)
 
@@ -332,7 +333,23 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
         self.tooltip_text = _("%s: %s") % (_("Location"), self.location)
         self.label_changed()
 
-    def _search_recursively_iter(self, iterstart):
+    def _search_recursively_iter(self, start_path, replace=False):
+
+        # Initial yield so when we add this to our tasks, we don't
+        # create iterators that may be invalidated.
+        yield _("Scanning repository")
+
+        if replace:
+            # Replace the row at start_path with a new, empty row ready
+            # to be filled.
+            old_iter = self.model.get_iter(start_path)
+            file_path = self.model.get_file_path(old_iter)
+            new_iter = self.model.insert_after(None, old_iter)
+            self.model.set_value(new_iter, tree.COL_PATH, file_path)
+            self.model.set_path_state(new_iter, 0, tree.STATE_NORMAL, True)
+            self.model.remove(old_iter)
+
+        iterstart = self.model.get_iter(start_path)
         rootname = self.model.get_file_path(iterstart)
         display_prefix = len(rootname) + 1
         symlinks_followed = set()
@@ -705,14 +722,12 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
             it = self.find_iter_by_name(where)
             if not it:
                 return
-            newiter = self.model.insert_after(None, it)
-            self.model.set_value(newiter, tree.COL_PATH, where)
-            self.model.set_path_state(newiter, 0, tree.STATE_NORMAL, True)
-            self.model.remove(it)
+            path = self.model.get_path(it)
+
             self.treeview.grab_focus()
-            self.treeview.get_selection().select_iter(newiter)
             self.vc.refresh_vc_state(where)
-            self.scheduler.add_task(self._search_recursively_iter(newiter))
+            self.scheduler.add_task(
+                self._search_recursively_iter(path, replace=True))
             self.scheduler.add_task(self.on_treeview_selection_changed)
             self.scheduler.add_task(self.on_treeview_cursor_changed)
         else:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]