rickomax / psxprev

PSXPREV - Playstation (PSX) Files Previewer/Extractor

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Invalid operation from PreviewForm enumerating over modified All lists

trigger-segfault opened this issue · comments

Describe the issue:
The PreviewForm's refresh action includes updating the animations, models, and textures list. It does so by enumerating through the AllAnimations, AllEntities and AllTextures lists that are stored in Program. The problem is that these lists can be modified by the parallel scan threads while PreviewForm is enumerating through them, causing an InvalidOperationException because the list was modified, thus invalidating the enumeration process.

It looks like the code causing this is Parallel.ForEach used for ProcessFile. There's no other situation that could cause this issue, since ReloadItems is only called by the scan thread after an item is added. But if multiple scan threads are running then this can absolutely happen.

Callstack:
UI Thread:

  • PreviewForm.UpdateRootEntities(List)
  • DoScan.AnonymousMethod(PreviewForm) (refreshAction)
  • PreviewForm.ReloadItems()

Scan Thread:

  • PreviewForm.ReloadItems()
  • Program.ScanFiles.AnonymousMethod(RootEntity, long)
  • Classes.CrocModelReader.LookForCrocModel(BinaryReader, string)
  • Program.ScanFiles.AnonymousMethod(BinaryReader, string)
  • Program.ProcessFile(Stream, string, Action)
  • Program.ProcessFiles.AnonymousMethod(Action)

Solution:
Locking can be used on the list object when adding to each individual list, and when updating/refreshing each individual list. That way only one thread will have access to the list until it's done using it.

Ideally, Add* functions should added to Program to automatically handle the locking.