How to find the reason for a ThreadAccessingUIException in ListColumn.__Exit?

Got a really weird exception from a user:

2023-04-26 08:08:04 ImapIterator.GetNumberOfObjects iCloud - xxxx ! projects:::xxx::> Indiegogo:::archive 9
2023-04-26 08:08:18 --------------------------
2023-04-26 08:08:18 An error happened:
2023-04-26 08:08:18 Class/Method: ArchiveThread.Archive
2023-04-26 08:08:18 Time: 26. Apr 2023 08:08:18 323401
2023-04-26 08:08:18 Type of Error: ThreadAccessingUIException
2023-04-26 08:08:18 Error Number: 0
2023-04-26 08:08:18 Error Message: A thread has attempted to manipulate a user interface element. This can only be done from the application’s main thread.
2023-04-26 08:08:18 --------------------------
2023-04-26 08:08:18 Stack:
2023-04-26 08:08:18
Sub ListColumn.__Exit()
Sub ArchiveThread.Archive()
Sub ArchiveThread.Event_Run()

The thread doesn’t deal with listboxes at all. So I’m really confused what is crashing here. Does anyone have an idea?

Xojo 2022r3. Ventura 13.3. Code hasn’t been changed in quite a while.

In no way, even indirectly, did your thread touch a ListColumn?

If memory serves, I do remember false stack reports being fixed, but, not sure, I guess it was a war on the Windows battlefield. Same bug compiled on Windows 32 bit people could find the offending part, but on Windows 64 bit, the stack emitted false places.

Nope. The code is several years old and has been used by thousands of users. The thread does a high level iterator:

dim currentIterator as Integer
try
  'loop over the email clients/imap accounts
  for currentIterator = 0 to theMailboxIterator.LastIndex
    
    'iterate over the mailboxes
    while theMailboxIterator(currentIterator) <> Nil and theMailboxIterator(currentIterator).hasNextObject and not Globals.StopArchiving
      
      'make new folderitem for email clients and string for imap
      dim nextObject as Variant = theMailboxIterator(currentIterator).nextObject
      if nextObject = Nil then Continue
      dim theImapMailbox as String
      dim theMailboxFolderitem as FolderItem
      if nextObject isA FolderItem then
        theMailboxFolderitem = Folderitem(nextObject)
      Else
        theImapMailbox = nextObject.StringValue
      end if
      
      dim theParser as new MailParser(_
      theMailboxIterator(currentIterator).getAccountName,_'more options
      
      
      'archival of emails
      NoOfMailsAdded = NoOfMailsAdded + theParser.parse
      
    Wend
    
  next
  
Catch err as OutOfBoundsException
  'error handling here
end try

Do you have the option of producing a sample doing dummy readings compiling it using 2022r2 and 2023r1.1 and send both to your user and see if both crash?

Let’s be speculative here. Your code is not protected against some unknown exception like “Exception. A new Ventura security thing is missing”, and some crash related to it could end as some unknown behavior.

Maybe a newer version could handle it better? Like a better message?

Move this sample out from a thread, and run also one in a thread, test both, looking for some readable crash, and real, and maybe the user could see the OS popping some new message asking for some permission?

For some reason, the thread has a ListBox or listColumn object referenced, which gets destroyed.Since that happens in the thread, you get the exception.
The object is created on the main thread, gets passed to the thread and then has it’s last reference cleared there.
This could be a window, that was closed before and the listbox is still (indirectly) referenced by something in the thread.

You can look for this.

No, the thread moves through the iterator and doesn’t reference any listbox.

It may be indirectly referenced.

But for some reason, the cleanup in the thread triggers it. Could be anything and can be difficult to find.

I don’t have a solution, but you’re not the only one who’s experienced this.

I’ve had a similar, rare ThreadAccessingUIException in ListColumn.__Exit for years and never been able to track it down. It seems to have stopped recently, but I used to receive ~1 per month out of tens of thousands of installations, from a thread that doesn’t interact with or reference controls at all.

1 Like

Perhaps, as a deprecated item, it has bugs. Why not try the Desktop version? And what is ListColumn.__Exit ?

Xojo always has bugs. I’m preparing the change to Desktop controls. But it still needs some work. Haven’t a clue what ListColumn.__Exit means. The user said that he didn’t close a window when the exception happened.

Yes but I assume bugs in deprecated items get no attention, whereas bugs in non-deprecated items stand some chance of being fixed.

Some ideas:

  1. Are you 100% sure that none of your MailBoxIterator code references any UI components (windows, controls, listboxes…) Can you show us the class definition or code?
  2. Your code does not have #pragma disableBackgroundTasks and has an outer while loop and an inner For/Next loop. This means there are two possible points at which the thread could yield. Also, any methods being called (nextObject or hasNextObject …) could also be yielding. This can make the behavior non-determinant and harder to debug. Personally, I would add #pragma disableBackgroundTasks to this method (and any methods it calls) and then add an explicit Thread.Yield() call and see if this cleans up the behavior. Note: there are a very few Xojo Framework calls which have internal, undocumented yields, which have always annoyed me to no end. So even if you try to control the yielding, you can’t always succeed.
  3. What is the user doing when this happens? My guess is they do something which triggers your method and then they close a window. Have you tried doing this on your own test system? Just madly hit menu commands, close and open windows, type, hit the escape key, click randomly in your windows, etc. I call these “Clicky-Clicky” bugs and they are usually timing dependent, but sometimes you can reproduce them if you do “weird” things.
  1. What situation triggers Globals.StopArchiving = true ?

Your current code reads:

try
  for currentIterator = 0 to theMailboxIterator.LastIndex
    while theMailboxIterator(currentIterator) <> Nil and theMailboxIterator(currentIterator).hasNextObject and not Globals.StopArchiving
[...]
    Wend
  next
Catch err as OutOfBoundsException
end try

The potential bug I see:
• if Globals.StopArchiving becomes true, then the While loop will keep running (in the sense that it keeps checking theMailboxIterator(currentIterator).hasNextObject since the StopArchiving flag gets checked at the end of the line.
• would it make more sense to do this:
while not Globals.StopArchiving and theMailboxIterator(currentIterator) <> Nil and theMailboxIterator(currentIterator).hasNextObject

that way if whatever triggers Globals.StopArchiving is doing some cleanup, it will short-circuit the while loop…

  1. Other things to check: when an app quits, it throws a ThreadEndException — Xojo documentation and if you are not careful in your Try/Catch blocks you can accidentally catch (or fail to catch) this one.

This. Back in the before times, you could count on framework functions being atomic, non yeilding. Now that portions of Xojo are written in Xojo, they are susceptible to yeilding and that can get messy. It really frosts my tips.

1 Like

The user was processing data. This disables most of the menu items and shows a progress window. The user said that he didn’t close any window or cancel the processing of the data. I would have seen this in the session log.

globals.stoparchiving is a relict from - cough - the beginning of Cocoa times when UserCancelled didn’t work properly. The global usually is set to true deeper into the code. After being set to true a notification is beamed to the model class. Changing the while loop won’t hurt.

Both EndException and ThreadEndException should be handled correctly.

I made a feature request:
https://tracker.xojo.com/xojoinc/xojo/-/issues/72604

There are plenty of cases where the UITrap could be skipped.

2 Likes

I’m not understanding what’s there:

// So basically currently the Listbox destructor looks like this:

Private Sub Destructor()
  REALbasic._UITrap()
  ListboxDestructor( Self )
End Sub

// and I would like to ask for it to change like this:

Private Sub Destructor()
	if handle = nil then
		// already closed
	else
		REALbasic._UITrap()
		ListboxDestructor( Self )
	end if
End Sub

// So only do the whole UITrap and destructor work, if it is needed. 
// This would avoid a lot of ThreadUIAccessException.

Are you saying, or I’m not understanding, that Xojo sometimes could fire a destructor twice?
And one of those, on an already destructed object?

This is pseudo code.
The list box destructor does currently two things.
First it checks for main thread and raises an exception if needed.
Second it does the underlaying cleanup call to the framework destruction function.

My idea is that the main thread check can be skipped if the control is already destructed via window’s close method.

And than we may see less exceptions.

1 Like

Whatever a destructor of an object does, it exists to do it only once. After it, the object ceases to exist, doing whatever in their internals, usually releasing things as memory and resources, once, and not reentrantly, and due to it, it couldn’t called twice by design.

If that occurs, something very odd on Xojo design exists.

Yup. Especially, since the user got the error a second time already. For now I added a try/catch and added some logging so that I can see which line causes the exception.