Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Elusive and peculiar issue with TreeStore and EntryCompletion #102
I'm experiencing a very strange reproducible crash, which seems to be related to TreeStore. Let me sketch my situation: I have a sort of 'file browser' that contains a simple TreeView with TreeStore. I also have a ListStore, that keeps track of the files inside the TreeStore and updates itself (or rather: will update, as this is not implemented yet) whenever the tree is updated. This ListStore is also used by an EntryCompletion as model so you can search through the files of the tree.
At startup, I load in a bunch of folders in my file browser asynchronously (in a separate thread created by D's taskPool, using threadsAddIdle to do the actual GTK manipulations in the main thread). The ListStore is simply built by hooking into the method that adds a node to the tree. This works fine, I can use the EntryCompletion to complete my text successfully. What is very strange is that any modification I do to the original TreeStore (thus, not the model used by the EntryCompletion) causes any completion in the EntryCompletion to crash the entire application. My tree also listens to editing the text in cells and update files on disk accordingly, but even though the ListStore is not modified in any way when this happens, the application still crashes when searching it through the EntryCompletion. In short:
I have been searching for a while and tried a dozen different solutions, but nothing seems to work, also using the TreeStore directly in the EntryCompletion (thus bypassing the ListStore) has the same effect: a crash whenever the tree is first modified. Every modification after startup runs through the exact same code as on startup. This crash both happens with DMD 2.066.1 as well as GDC 4.9.2, attaching GDB to the GDC version yields a huge backtrace:
As you can see, the backtrace claims to crash in 'toLower', which is called during filtering in my EntryCompletion.setMatchFunc() method, but it runs just fine on startup. The end of the back trace is also not always constant: sometimes it claims to crash somewhere else. Could this possibly be a memory corruption of some kind? The other threads in my application are created using D's taskPool and at the time of the backtrace were all finished running.
I wish I could be more specific about what specifically is crashing, but this issue seems to be rather elusive. Any tips or suggestions are welcome. I was hoping that you might have some idea what could be causing this, I'm not sure if this is even a GtkD issue, it could very well also be a Gtk, a GDC/DMD, a Phobos, or even a garbage collector issue. In very rare cases, the crash also doesn't seem to occur at all.
Thanks in advance for any help you can offer
Thanks for your response. I've uploaded the code that GDB is claming crashes to Pastebin. I've added a comment to the location of the crash, and also noticed the following during yet another debug run: if I remove all the code inside the 'try' block, no crash occurs when searching after a tree modification. However, readding just the first getDObject (TreeIter) call is sufficient to make it happen again, but this time not immediately after modifying the tree; it happens a few searches later, this time GDB is pointing its finger at the readded getDObject call . What however is strange, is that not only the same massive backtrace as above is printed, but the backtrace also goes through the same steps:
The same seems to occur if I just use auto iter = new TextIter(rawIter). What seems to happen is that the allocation of a new TextIter causes the garbage collector to do a full garbage collection (so far: seems normal), which causes some ObjectG object to finalize (still normal) and end up in its destructor where the stealData call is performed, which eventually ends up in allocating more memory. One would think that the garbage collector enters some sort of infinite loop (IIRC it collects memory during memory (de)allocation) when finalizing an object during an allocation, another allocation happens in the destructor (the toStringz), which does the same thing over again. However, if this was the case one would expect more references to fullcollect.
I wasn't able to drop in the code as is, as GDC is complaining about not being able to cast a string to a char pointer, but I used the following code instead:
With this in place, I seem to no longer be able to reproduce the issue; I can happily modify the model without the crash occurring, so this does indeed seem to fix it. I thought that D's garbage collector was aware and prepared for memory allocations during finalization, but this doesn't completely seem to be the case.
Many thanks, this seems to be the second time you've saved the day with a strange bug I was having