Runtime exception: RaiseExceptionClassRK13ClassDeclBase

I have macOS desktop app that contains a method that is used to count the number of WAV files in a folder, and calls itself when it finds a sub folder. I have a client using my app who has reported an error while loading a folder tree to scan all WAVs on his system. He has sent the following stack from my app’s un-handled exception window:

RuntimeRaiseException
_Z19RaiseExceptionClassRK13ClassDeclBase
RuntimeStackCheck
GlobalCodeMF.FolderItemNotNilAndExistsMF%b%o
App.!FolderItemCountChildrenWithProgBarCheck%i8%obbbo
App.!FolderItemCountChildrenWithProgBarCheck%i8%obbbo
App.!FolderItemCountChildrenWithProgBarCheck%i8%obbbo

Does “RaiseExceptionClassRK13ClassDeclBase” mean anything to anyone, or does the users folder structure simply contain too many sub-folders for the stack to handle? I’ve tried to re-produce this on macOS 10.15.7. I managed to make 86 sub-folders, the maximum Finder seems to handle before it starts throwing errors. If I load 4x WAVs into the last folder my app can scan this tree okay.

Would the following code catch the above error:

Exception err
  If err IsA StackOverflowException Then
    MessageBox("The stack has overflowed!")
  End If

Many thanks

The exception is in your code here. The lines above it are methods in the Xojo framework that get called as part of the exception process.

Thanks Greg. Then I’m not sure why I’m getting an exception in this method:

Public Function FolderItemNotNilAndExistsMF(FileOrFolder As FolderItem) As Boolean
  if FileOrFolder <> nil then
    if FileOrFolder.Exists then
      Return True
    end if
  end if
End Function

Should I put an exception handler around the 5 lines of code? Do you know of an instance where an exception could occur with the code in this method?

Thanks

My guess, since the rest of the calls are identical and the exception is a StackOverflowException that when the method in question is called, the stack is already one call away from failure.

See how it’s:

App.!FolderItemCountChildrenWithProgBarCheck%i8%obbbo

Over and over? That method is calling back into itself. If it does that too many times, one more call may be all it takes for the exception to occur. Any idea how many nested levels you were in when the exception was raised?

1 Like

It’s been a while, but as I recall, the stack size is fixed for the main thread, but you can set the StackSize on a thread you call. It seemed like I could overflow the main stack pretty easily, so putting the recursive code into a thread and bumping the stack size resolved the problem.

I guess you have some code collecting nodes while walking a folder tree, tree that can be

  1. huge while using recursive code
  2. having links being followed causing unexpected reentrancy

You may need new approaches.

The documentation for Thread.StackSize says

StackSize As [Integer]

The size of the stack, in bytes.

The StackSize can only be set when the Thread is not running. The default stack size is 512KB on macOS and Linux and 1MB on Windows. A StackSize of zero indicates the default is used.

There is generally little reason to change this. Each stack frame only need to contain information about the parameters, local variables and return address for a method call. This does not include memory needed for objects. It would take a significant amount of local variables or parameters with method calls that are 100s of levels deep in order to exhaust the stack space.

I don’t think that’s really true.

No idea how many nested calls there are. This would depend on the folder structure of the users system.

All the method ‘FolderItemCountChildrenWithProgBarCheck’ does is count the number of files in the passed folder. If the passed folder contains a sub-folder, it calls itself with that sub-folder. I use the result of this to set the max level of a progress bar before scanning all WAV files in the tree.

This method is called from a thread, so I’m guessing the next best thing to do is see how many times it’s calling itself for this user. Then possibly look at changing the StackSize as per @Tim_Hare suggestion or re-think how I do this.

Thanks all

If the folder structure is too deep you will eventually get a stack overflow error. It should be relatively easy to redesign your function to avoid this.

You also need to make sure that a sub folder isn’t an alias to one of its parent folders otherwise you will never finish.

1 Like

This is how I scan folders.

Public Function ScanTree(RootFolder As FolderItem, Extension As String, Status As DesktopLabel) As FolderItem()
  Dim Folders() As FolderItem
  Folders.Add(RootFolder)
  
  Dim Files() As FolderItem
  
  Do Until Folders.Count = 0
    Var CurrentFolder As FolderItem = Folders(0)
    Folders.RemoveAt(0)
    Status.Text = CurrentFolder.NativePath
    
    For Each Child As FolderItem In CurrentFolder.Children
      If Child.IsFolder Then
        If Child.IsReadable Then
          Folders.Add(Child)
        End If
      Else
        If Child.Name.EndsWith(Extension) Then
          Files.Add(Child)
        End If
      End If
    Next
  Loop
  
  Return Files
End Function

It doesn’t provide a total for progress bar purposes, but it does show the folder being scanned which gives some comfort to the user.

HTH
Wayne

This will fail if you have a folder with a child item inside that points at its parent folder. It would recuse forever. Until it crashed the stack.

You should check and ignore items where isAlias returns true.

https://documentation.xojo.com/api/files/folderitem.html#folderitem-isalias

Thanks @kevin_g. I’ll re-write to stop the function calling itself and also check for an alias pointing to a parent folder. Good point. Thanks @Wayne_Golding for the sample code. This is a good place for me to start.

Using FileListMBS to list items in a folder is much faster. FileListMBS can also yield a bit so that going through a lot of files doesn’t show the beachball as fast.

1 Like