Crash during recursive cleanup with refresh policy "assume deleted"
Lithopsian opened this issue · comments
I have a crash that is reliably reproduced here, except that it doesn't happen in a debug build.
I have configured the Delete Junk Files cleanup to assume item has been deleted. Which happens to be untrue, don't know if that is important, probably not. Other than that, I think it is standard. I went to .cache/chromium/Default/Cache/Cache_Data although I don't think the exact location is important. I executed Delete Junk Files and it crashes.
I can get the crash location at FileInfo.cpp:371 being called from SelectionModel.cpp:267. In a debug build, it doesn't crash, but I can get some information about the variables involved: ancestor (and this) is null and fwiw magic as shown in the debugger is 1. subtree is not null and magic is 4242. In the debug build, it just skips the loop and returns false, all is well. In the non-debug build, it looks like any attempt to access ancestor, including me adding some logging statements, causes the crash. Possibly this/ancestor is garbage but not zero in the non-debug build.
You probably know how all this works already, but I was deliberately trying to cause the deletingChild() signal to be emitted for testing TreemapView. I was surprised to find it is hardly ever called, but using the assume item has been deleted option is one way to do it.
When I said "reliably", I may have been a bit too optimistic. I can reproduce it every time with that exact directory, but on others the cleanup works without crashing. I haven't been able to spot which ones cause a crash and which ones don't, but it seems consistent: directories which crash once crash every time; those that don't crash never crash.
Hm - I use that cleanup all the time (with its default refresh policy), but also quite some that use assume deleted, and I never got a crash.
For debugging, you can also simply use a cleanup that does nothing (a command like echo hello
) and a refresh policy of assume deleted; that makes it a lot easier.
I wonder if that is connected to the recent changes to the future selection.
I added this cleanup that only deletes an item from the in-memory DirTree
:
[Cleanup_99]
Active=true
AskForConfirmation=false
Command=echo %n
Hotkey=F8
OutputWindowAutoClose=false
OutputWindowPolicy=ShowNever
Recurse=false
RefreshPolicy=AssumeDeleted
Title=Ghost-kill
WorksForDir=true
WorksForDotEntry=true
WorksForFile=true
So far, I could not reproduce the problem.
I also tried it with Recurse=true
, but that still doesn't change anything.
But maybe it does sometimes; because that "Delete Junk files" cleanup is called recursively, and it's called top-down. That might actually be a problem when the call to the subtree root is removed first from the DirTree
. Please check.
I added a sleep 1
to the command, and now it does crash.
AFAICS the order of actions is wrong: It deletes the in-memory subtree too early, and then it recurses into any subdirectories - with the pointers to those subdirectories and/or the subtree root already being invalidated.
Probably both the recursing and the cleanup taking a little while are the key here.
Now preventing recursion together with refresh policy "Assume Deleted".
Since this is a completely artificial scenario anyway, I am not going to add a ton of code to do something complex like the delayed Refresher
which triggers a subtree refresh after the processes that might still be in the queue of the OutputWindow
are all done.
You can now select either recursion or the "Assume Deleted" refresh policy, but not both. The cleanup config page now checks that and disables the "Recurse" checkbox if "Assume Deleted" is selected, and posts a warning pop-up.
On the execution side, the cleanup itself now checks the same thing and logs an error if needed and does not recurse: The user can still edit the config file manually, so it needs to be checked when the cleanup is actually used.
Maybe a little late, but I already tested if recursion was the culprit. It seemed like a good candidate, but it doesn't make any difference here. I still don't have a definite combination of circumstances that will cause the crash, but being deeper in the directory tree seems to help.
So likewise, after these fixes, I still get the same crash after the same steps.