Preemptive Threads and Listboxes Don't Play Nice

I’m seeing an issues where when I am running multiple preemptive threads and then doing paints in a listbox (main thread mind you), I get ThreadAccessingUI exceptions thrown. NONE of my threads are doing anything with the UI. Zero. They have nothing to do with this listbox save that some of the objects running the threads are properties of the listbox.

I know it’s a framework issue as I had a Framework Assertion get thrown.

Seems like there’s still quite a few potential problems with preemptive threads…

Can you create Issue with a sample project?

1 Like

An issues was automatically created when the framework threw the assertion. An example project is not really possible.

So they are linked in some way. Without a sample it will be hard to see what was the conflict.

It’s an error in the framework as the framework throws an assertion.

And no they are not connected other than the fact that the objects running the threads are also properties in the listbox. The threads don’t touch the UI period.

And it’s simply not possible to put it in an example and it happens at random.

You know the drill: either you make an example of the problem won’t get fixed. It sounds like you have to the “best” troubleshooting technique. You have to reduce the full project by removing classes and functionality until the remaining classes show the problem. It’s utterly annoying and hugely time consuming. So I do this only very rarely.

I don’t see anything in that report that would help point to the issue because there isn’t any detail.

If you can’t create an example, perhaps you can submit the original project privately with steps to reproduce.

Don’t you get to find out where the ThreadAccessingUI exceptions happen?

1 Like

Is is really both? If so, I’m assuming the exception is thrown, your code just ignores it with a try-catch and then the assertion?

The ThreadAccessingUI Exception has always been “special” in that it’s not really a recoverable situation and when you get one, you really need to refactor your code to prevent it. Toss in the complexity of preemptive threads and yes, you’re going to assert or crash. I would guess that the assertion you’re tripping over is a check to make sure your code is running on the main thread, which would say that it’s not a bug in the framework.

Here’s what I suggest…in the place where the ThreadAccessingUI exception breaks into the debugger, write the stack to a file (or use app.UnhandledException). I’d also use introspection to write out the name of the thread if there is one. Those two things should give you some insight into what’s going on.

If you can make a small sample simulation showing your problem, I probably can make a small refactoring showing it working. My guess is that you made something unprotected being used at the same time by the listbox and some thread, and could not figure out what it is and how to protected it, but it’s there. So no framework things, just a code needing a bit more expertise on concurrency, probably.

Thanks everyone for the suggestions. I really can’t submit an example project because this is what I am doing (and this is quite long FYI):

  • Connecting to video hardware using either a URLConnection or a TCPSocket depending on the model of the device.
  • Sending commands to capture either a JPEG or Bitmap from the devices depending on the model
  • Taking the received string data and converting it into a memory block (I’ve also had problems with doing too many string operations in preemptive threads). I then start the thread.
  • In the thread I am Validating that the data in the memory block is valid and converting it into a picture.
  • Calling the UserInterfaceUpdate of the thread. If I have a picture passed I then loop through a dictionary of all the UI canvases that are registered to receive image data. I then call an interface method to send the picture to the canvases and they then paint the data.
  • I then call the method that starts the whole process over again.

I have about 16 devices I am doing this to simultaneously. I’m pulling about 500 Mb/s of data across my network doing this. This is all I am doing in the thread:

Private Sub HandleImageThreadRun(t as thread)
  
  Dim p As Picture
  PicDataSemaphore.Signal
  
  If IsMaxColor Then
    #Pragma BreakOnExceptions Off
    Try
      p = Picture.FromData(HTMLContent)
      'p = JPEGStringToPictureMBS(mcontent)
    Catch
    End Try
    #Pragma BreakOnExceptionsOn
    
  Else
    // Need to validate that this is proper Bitmap file.  BMP data has a file size value that is 4 bytes at offset 2
    // Read that from the memory block and compare it to the size of the memory block.
    Dim psize As Integer = HTMLContent.Int32Value(2)
    If HTMLContent.Size = psize Then
      p = Picture.FromData(HTMLContent)
    End If
  End If
  
  PicDataSemaphore.Release
  
  If p <> Nil Then
    
    Select Case VideoRotation
      
    Case JAPDevice.Rotation.VerticalMirror
      p = p.VMirrorMBS
    Case JAPDevice.Rotation.HorizontalMirror
      p = p.HMirrorMBS
    Case JAPDevice.Rotation.Rotate180Degrees
      p = p.RotateMBS(180)
    Case JAPDevice.Rotation.Rotate90DegreesClockwise
      p = p.RotateMBS(90)
    Case JAPDevice.Rotation.Rotate90DegreesClockwiseAndHorizontalMirror
      p = p.RotateMBS(90)
      p = p.HMirrorMBS
    Case JAPDevice.Rotation.Rotate270DegreesClockwise
      p = p.RotateMBS(270)
    Case JAPDevice.Rotation.Rotate270DegreesClockwiseAndHorizontalMirror
      p = p.RotateMBS(270)
      p = p.HMirrorMBS
    End Select
    
    // Going to assume the image needs to be 16:9 Aspect ratio
    // Correct it if not
    If p.height/p.width <> 16/9 Then
      
      Dim ppHeight As Integer = p.Height
      Dim ppWidth As Integer = p.width
      
      If p.Height > p.width Then
        ppWidth = ppHeight*(16/9)
      Else
        ppHeight = ppWidth*(9/16)
      End If
      
      Dim pp1 As New Picture(ppWidth,ppHeight)
      pp1.Graphics.DrawPicture(p,0,0,ppWidth,ppHeight,0,0,p.Width,p.Height)
      p = pp1
    End If
    
    // Call the InterfaceUpdate so the main thread can send the image data to UI Controls
    ImageThread.AddUserInterfaceUpdate("pic":p)
  Else
    
    // No picture - Raise the InterfaceUpdate but send nothing
    // Then we can restart the process
    Try
      ImageThread.AddUserInterfaceUpdate(Nil:Nil)
    Catch
    End Try
    
  End If
  
  
End Sub

There’s nothing there that is tied remotely to anything used by the UI. I left in one of the commented out commands I had been using from MonkeyBread. I was using string data but seeing random crashes. Not sure if Christian’s method is preemptive thread safe or not. But since I started using MemoryBlocks, I’m not having any issues on that side of things.

Now in the ContentReceived event of the URLConnection I have the following code:

Public Sub MaxColorURLConnectionContentReceived(u as urlconnection, URL as string, HTTPStatus as Integer, content as String)
  
  
  PicDataSemaphore.Signal
  HTMLContent = New MemoryBlock(content.Length)
  HTMLContent.StringValue(0,content.Length)=content
  PicDataSemaphore.Release
  
  Dim i As Integer = 0
  While ImageThread.ThreadState <> Thread.ThreadStates.NotRunning
    If i < 100 Then
      Thread.SleepCurrent(2)
    Else
      ImageThread.stop
      Exit While
    End If
    i=i+1
  Wend
  
  If Not DontStartImageThread Then
    ImageThread.Start
  End If
  
End Sub

I won’t paste the TCPSocket DataAvailable code as it’s basically the same thing. The only objects that are being accessed by both the main thread and the preemptive thread are the memory block HTMLContent and the resulting picture. And both are protected by semaphores in each place.

Now, @Greg_O you said I should save the stack to a file when the exception happens. Been doing that for years! :smiley: Here you go:

ThreadAccessingUIException
RuntimeRaiseException
REALbasic._UITrap
ListColumn.__Exit%%o
RuntimeUnlockObject
RuntimeLockUnlockObjects
JAPDevice.HandleImageThreadRun%%oo
Delegate.IM_Invoke%%o
threadRun
ZN4xojo11SpawnThreadEmPFvPvES0
_pthread_start
2024 4.8.0.782

Exact same stack every time.

Now I don’t know what ListColumn._Exit is. I am assuming that’s a Framework method.

Now here is some information I pulled from some of the crash reports.

First Report

Here is the thread that crashed:

Thread 18 Crashed:
0   libsystem_kernel.dylib        	       0x1981f2a60 __pthread_kill + 8
1   libsystem_pthread.dylib       	       0x19822ac20 pthread_kill + 288
2   libsystem_c.dylib             	       0x198137a30 abort + 180
3   libsystem_malloc.dylib        	       0x198047dc4 malloc_vreport + 896
4   libsystem_malloc.dylib        	       0x19804b430 malloc_report + 64
5   libsystem_malloc.dylib        	       0x198065494 find_zone_and_free + 528
6   XojoFramework                 	       0x1037c44c4 0x103554000 + 2557124
7   XojoFramework                 	       0x1037c4628 RuntimeLockUnlockObjects + 108
8   MediaSwitcher                 	       0x101a5cbb8 JAPDevice.HandleImageThreadRun%%o<JAPDevice>o<Thread> + 5040
9   MediaSwitcher                 	       0x100d79560 Delegate.IM_Invoke%%o<Thread> + 60
10  XojoFramework                 	       0x1037d12fc 0x103554000 + 2609916
11  XojoFramework                 	       0x103693c90 0x103554000 + 1309840
12  libsystem_pthread.dylib       	       0x19822af94 _pthread_start + 136
13  libsystem_pthread.dylib       	       0x198225d34 thread_start + 8

And here’s what was going on in the main thread:

Thread 0::  Dispatch queue: com.apple.main-thread
0   XojoFramework                 	       0x1037d2298 0x103554000 + 2613912
1   XojoFramework                 	       0x1037cfac8 0x103554000 + 2603720
2   XojoFramework                 	       0x1036c731c RuntimeBackgroundTask + 68
3   MediaSwitcher                 	       0x1015fb45c DeviceMaintWindow.DeviceMaintWindow.ScrollBarHorizontalVisible.Get%b%o<DeviceMaintWindow.DeviceMaintWindow>i4 + 720
4   MediaSwitcher                 	       0x1015adf64 DeviceMaintWindow.DeviceMaintWindow.DeviceList_CellTextPaint%%o<DeviceMaintWindow.DeviceMaintWindow>o<ListBoxPopup>o<Graphics>i8i8i8i8 + 4532
5   MediaSwitcher                 	       0x100e0d6b0 Delegate.IM_Invoke%%o<ListBoxPopup>o<Graphics>i8i8i8i8 + 100
6   MediaSwitcher                 	       0x100e0d74c AddHandler.Stub.51%%o<Graphics>i8i8i8i8 + 136
7   MediaSwitcher                 	       0x100eb0ea4 ListBoxPopup.Event_cellTextPaint%b%o<ListBoxPopup>o<Graphics>i8i8i8i8 + 1588
8   MediaSwitcher                 	       0x100e463b4 AlternatingList.Event_CellTextPaint%b%o<AlternatingList>o<Graphics>i8i8i8i8 + 200
9   XojoFramework                 	       0x10376315c RuntimeListbox::DrawCellText(Graphics*, xojo::Rect<xojo::Points> const*, CellEntry*, int, int, bool, bool, int) + 560
10  XojoFramework                 	       0x103761fb0 RuntimeListbox::DrawCell(Graphics*, xojo::Rect<xojo::Points> const*, RowEntry*, CellEntry*, int, int, unsigned char) + 1016
11  XojoFramework                 	       0x1037619f0 RuntimeListbox::HandleDrawRow(Graphics*, int, xojo::Rect<xojo::Points> const&, unsigned char, std::__1::vector<xojo::Rect<xojo::Points>, std::__1::allocator<xojo::Rect<xojo::Points>>> const&) + 524
12  XojoFramework                 	       0x103760ec0 RuntimeListbox::RedrawCore(Graphics*, std::__1::vector<xojo::Rect<xojo::Points>, std::__1::allocator<xojo::Rect<xojo::Points>>> const&) + 536
13  XojoFramework                 	       0x1037611d0 RuntimeListbox::Redraw(Graphics*, std::__1::vector<xojo::Rect<xojo::Points>, std::__1::allocator<xojo::Rect<xojo::Points>>> const&) + 220
14  XojoFramework                 	       0x10364f4e0 0x103554000 + 1029344
15  AppKit                        	       0x19bc817d4 _NSViewDrawRect + 124
16  AppKit                        	       0x19c612cf0 -[NSView _recursive:displayRectIgnoringOpacity:inContext:stopAtLayerBackedViews:] + 1088
17  AppKit                        	       0x19c612e88 -[NSView _recursive:displayRectIgnoringOpacity:inContext:stopAtLayerBackedViews:] + 1496
18  AppKit                        	       0x19bc811d8 -[NSView(NSLayerKitGlue) _drawViewBackingLayer:inContext:drawingHandler:] + 556
19  AppKit                        	       0x19c1b5f80 -[NSViewBackingLayer drawInContext:] + 56

Second Report

Here’s the second report thread that crashed and this looks to be all MacOS framework…

Thread 10 Crashed::  Dispatch queue: com.apple.CFNetwork.Connection
0   libsystem_kernel.dylib        	       0x1981f2a60 __pthread_kill + 8
1   libsystem_pthread.dylib       	       0x19822ac20 pthread_kill + 288
2   libsystem_c.dylib             	       0x198137a30 abort + 180
3   libsystem_malloc.dylib        	       0x198047dc4 malloc_vreport + 896
4   libsystem_malloc.dylib        	       0x19804b430 malloc_report + 64
5   libsystem_malloc.dylib        	       0x198065494 find_zone_and_free + 528
6   Network                       	       0x19f6907a4 -[NWConcrete_nw_parameters dealloc] + 36
7   libobjc.A.dylib               	       0x197e5fe3c object_cxxDestructFromClass(objc_object*, objc_class*) + 116
8   libobjc.A.dylib               	       0x197e57688 objc_destructInstance + 80
9   libobjc.A.dylib               	       0x197e57634 _objc_rootDealloc + 80
10  Network                       	       0x19fb70a8c -[NWConcrete_nw_path dealloc] + 100
11  Network                       	       0x19fd26ea4 nw_association_update_paths + 284
12  Network                       	       0x19fb81b34 nw_path_necp_update_evaluator + 1512
13  Network                       	       0x19fb7faa8 nw_path_necp_check_for_updates + 3832
14  Network                       	       0x19fba1adc nw_path_evaluator_force_update + 104
15  Network                       	       0x19fd2d2b0 nw_association_force_update + 100
16  Network                       	       0x19fc8b664 nw_endpoint_flow_setup_channel(NWConcrete_nw_endpoint_handler*) + 2212
17  Network                       	       0x19fcaa0b0 -[NWConcrete_nw_endpoint_flow startWithHandler:] + 3664
18  Network                       	       0x19f7cde30 nw_endpoint_handler_path_change(NWConcrete_nw_endpoint_handler*) + 7280
19  Network                       	       0x19f7d73ec nw_endpoint_handler_start + 1624
20  Network                       	       0x19f729c64 __nw_connection_start_block_invoke + 980
21  Network                       	       0x19f729630 nw_connection_start + 508
22  CFNetwork                     	       0x19d692ac4 0x19d545000 + 1366724
23  CFNetwork                     	       0x19d68acc4 0x19d545000 + 1334468
24  CFNetwork                     	       0x19d68bc54 0x19d545000 + 1338452
25  CFNetwork                     	       0x19d6dae74 0x19d545000 + 1662580
26  CFNetwork                     	       0x19d68a898 0x19d545000 + 1333400
27  CFNetwork                     	       0x19d56b7dc 0x19d545000 + 157660
28  CFNetwork                     	       0x19d6da348 0x19d545000 + 1659720
29  CFNetwork                     	       0x19d6da4e4 0x19d545000 + 1660132
30  libdispatch.dylib             	       0x198078750 _dispatch_call_block_and_release + 32
31  libdispatch.dylib             	       0x19807a3e8 _dispatch_client_callout + 20
32  libdispatch.dylib             	       0x198081a14 _dispatch_lane_serial_drain + 748
33  libdispatch.dylib             	       0x198082578 _dispatch_lane_invoke + 432
34  libdispatch.dylib             	       0x198083898 _dispatch_workloop_invoke + 1756
35  libdispatch.dylib             	       0x19808d2d0 _dispatch_root_queue_drain_deferred_wlh + 288
36  libdispatch.dylib             	       0x19808cb44 _dispatch_workloop_worker_thread + 404
37  libsystem_pthread.dylib       	       0x19822700c _pthread_wqthread + 288
38  libsystem_pthread.dylib       	       0x198225d28 start_wqthread + 8

There’s not much in the main thread on this one unfortunately…This is just the Xojo related part where the exception is thrown

37  XojoFramework                 	       0x1078c6b40 0x1077e0000 + 944960
38  XojoFramework                 	       0x1078c6bc8 0x1077e0000 + 945096
39  MediaSwitcher                 	       0x1045caae8 Application._CallFunctionWithExceptionHandling%%o<Application>p + 164
40  XojoFramework                 	       0x107a4d930 CallFunctionWithExceptionHandling(void (*)()) + 180
41  XojoFramework                 	       0x1078c6b64 0x1077e0000 + 944996
42  AppKit                        	       0x19bb5b09c -[NSApplication run] + 476
43  XojoFramework                 	       0x107a4c0b0 RuntimeRun + 60
44  MediaSwitcher                 	       0x10475da74 REALbasic._RuntimeRun + 28
45  MediaSwitcher                 	       0x105d49908 _Main + 476
46  MediaSwitcher                 	       0x105d4643c main + 36
47  dyld                          	       0x197ea20e0 start + 2360

Now what’s odd is that both of these crashes happened on my Mac Mini running a compiled version of my app. I left the app running last night on my laptop in the debugger and it’s still running solid since 5PM yesterday. Hasn’t crashed and I haven’t been able to make it crash…

Here’s the code that is in the CellTextPaint event of the listbox. The “JAPDevice” (JAP = Just Add Power - the name of the company who makes the devices I work with) is the object in code representing the physical hardware. This is the object running the threads in question.

Sub CellTextPaint(g as graphics, row as integer, column as integer, x as integer, y as integer) Handles CellTextPaint
  Dim ln As Integer
  
  DIm ErrorItem as string
  
  If  row < 0 or column < 0 Then
    Return
  End If
  
  Dim j as JAPDevice
  ln = 12
  If me.RowTag(row) <> Nil AND me.RowTag(row) IsA JAPDevice Then
    j = JAPDevice(me.RowTag(row))
  End If
  ln =16
  Dim mwidths as String = me.ColumnWidths
  Dim widths() As String = mwidths.Split(",")
  
  If me.CellItalic(row,column) And column <> 0 Then
    g.ForeColor = &c008040
  End If
  
  ln = 24
  Select Case Column
    
  Case 0
    
    If me.RowIsFolder(row) Then
      g.TextSize = 12
      g.Bold = True
      g.Underline = True
      g.Italic = True
    End If
    
    ln = 36
    
  Case 2
    
    ln = 40
    If j <> Nil Then
      
      Dim colwidth as integer = val(widths(2))
      ln=44
      If Not ScrollBarHorizontalVisible Then
        colwidth = ((colwidth/100)*Me.Width)
      End If
      
      Dim usethis As Integer = If(colwidth < Me.RowHeight, colwidth, Me.RowHeight)
      Dim mx as integer = Abs((colwidth-usethis)/2)
      ln = 51
      Dim p as Picture
      
      If j.Connected Then
        p = GreenDot
        If p = Nil Then
          ErrorItem = "GreenDot + P Nil"
        Else
          ErrorItem = "GreenDot"
        End If
        
      Elseif j.AttemptingLogin Then
        
        p = BallYellow
        
        If p = Nil Then
          ErrorItem = "BallYellow + P Nil"
        Else
          ErrorItem = "Ball Yellow"
        End IF
        
      Else 
        p = RedDot
        
        If p = Nil Then
          ErrorItem = "RedDot + P Nil" 
        Else
          ErrorItem = "BallRed"
        End If
        
        ln = 63
        Me.cell(row,6) = ""
        Me.Cell(row,7) = ""
        Me.Cell(row,8) = ""
        Me.cell(row,8) = ""
        
        If j.Rebooting Then
          Me.Cell(row,10) = "Rebooting"
        Else
          Me.Cell(row,10) = ""
        End If
        
        Dim mSerialModes As MyPopup
        ln=77
        
        If DeviceList.CellTag(row,11) <> NIl Then
          mSerialModes = MyPopUp(DeviceList.CellTag(row,11))
        End If
        
        ln=86
        If mSerialModes <> Nil Then
          mSerialModes.ListIndex = -1
        End If
        
        me.Cell(row,11) = ""
      End If
      ln=93
      
      If p = nil Then ErrorItem = ErrorItem+ " P is Nil"
      if g = nil Then ErrorItem = ErrorItem+ " G is Nil"
      
      g.DrawPicture(p,mx,0,usethis,usethis,0,0,p.Width,p.Height)
      
    End If
    
    
  Case 4
    
    If me.ScrollBarHorizontal Then
      Dim zzz as INteger = 0
    End If
    ln=104
    Dim colwidth As Integer = Val(widths(4))
    
    If Not ScrollBarHorizontalVisible Then
      colwidth = ((colwidth/100)*Me.Width)
    End If
    
    Dim usethis As Integer = If (colwidth < Me.RowHeight, colwidth, Me.RowHeight)
    Dim mx As Integer = Abs((colwidth-usethis)/2)
    ln=110
    Dim p As Picture
    
    If j = Nil OR Not j.Connected Then
      Me.cell(row,column) = ""
      Return
    End If
    
    ln=118
    If j <> Nil And  j.StatusDictionary <> Nil Then
      
      Dim srvon As Boolean = j.StatusDictionary.Lookup("srv_on",false)
      ln=122
      If srvon Then
        p= CheckboxFull
      Else
        p = CheckboxEmpty
      End If
      
    Else
      p = CheckboxEmpty
    End If
    ln=132
    
    g.DrawPicture(p,mx,0,usethis,usethis,0,0,p.Width,p.Height)
    
  Case 5
    ln=137
    Dim colwidth As Integer = Val(widths(4))
    
    If Not ScrollBarHorizontalVisible Then
      colwidth = ((colwidth/100)*Me.Width)
    End If
    ln=143
    Dim usethis As Integer = If (colwidth < Me.RowHeight, colwidth, Me.RowHeight)
    Dim mx As Integer = Abs((colwidth-usethis)/2)
    
    If j= Nil or Not j.Connected Or j.TX Then
      Me.cell(row,column) = ""
      Return
    End If
    ln=151
    Dim p As Picture
    
    If j <> Nil and j.StatusDictionary <> Nil Then
      ln=156
      Dim Attached As Boolean = j.StatusDictionary.Lookup("attached",False)
      ln=157
      If Attached Then
        p= CheckboxFull
      Else
        p = CheckboxEmpty
      End If
      
    Else
      p = CheckboxEmpty
    End If
    ln=167
    g.DrawPicture(p,mx,0,usethis,usethis,0,0,p.Width,p.Height)
    
    
  Case 8
    ln=172
    If j = Nil or Not j.Connected Then
      Me.Cell(row,8) = ""
      Return
    End If
    
    
    If j.StatusDictionary <> Nil Then
      ln=180
      If j.StatusDictionary.HasKey("StartDate_TimeUp") Then
        ln=182
        Dim StartDate as DateTime = j.StatusDictionary.Value("StartDate_TimeUp")
        Dim UpTime As DateInterval = DateTime.Now-StartDate
        Dim UpStr as string = str(UpTime.Days)+"d "+str(UpTime.Hours)+"h "+str(UpTime.Minutes)+"m "+str(UpTime.Seconds)+"s"
        Me.Cell(row,8) = UpStr
        ln=187
         
      End If
    End If
    
  End Select
  ln=201
  
  Exception e as RuntimeException
    
    Static MyLn as Integer = -1
    Static MyRow as Integer = -1
    Static MyCol as Integer = -1
    
    Dim t As Xojo.Introspection.TypeInfo = Xojo.Introspection.GetType(e)
    
    Dim eName as String
    If t <> Nil Then
      eName = t.FullName
    End If
    
    If MyLn <> ln And MyRow <> row and MyCol <> column Then
      MyLn = Ln
      MyRow = Row
      MyCol = column
      
      SendErrorEmail("Exception of Type  "+ename+" has occured near Line Number "+Str(ln))
    End If
    
End Sub

Yes I am touching the device that is running the thread. I’m accessing properties of the code object. The code object is pulling other data from the device over different TCPSockets or URLConnections, etc. But nothing is messing with the thread. Maybe there’s just a lot going on and I should semaphore the entire code object and not do any operations while the thread is running?

This is what the listbox looks like:

And what the whole screen running everything looks like:

OK. Here’s something I just realized and is perhaps this where I could be going off course? I had removed the semaphores around the code on the main thread protecting the picture I generated. The reason is that the thread processing the images is always complete by that time. But…If I send the image to a canvas and the canvas refreshes - that could happen in a different clock cycle and not in the same stack. So perhaps theoretically the thread could be running and modifying the picture object while the canvas is painting it. I assume that could cause a ThreadAccessingUI exception, but then why would that now show as happening in a canvas? If the canvas paint event was shown in the crash reports or the stack then I could understand it but it’s not.

Regardless, I’m adding the protection with the semaphores back in.

Preemptive threads definitely have some weird bugs, here’s one I just reported where the the framework crashes https://tracker.xojo.com/xojoinc/xojo/-/issues/77696 but it only happens if the main thread completes an event; if the main thread is stuck in a loop there is no crash.

  1. Did you set the semaphore type after you created it?

  2. Have you tried a critical section instead of a semaphore?

1.) Yes
2.) No. Basically it’s the same thing.

I wonder if your issue might be connected to what I (still) see here – thought it was fixed, but it isn’t. As I have to use Rosetta to access the Intel API, my thoughts were rather tending towards that reason. But the similarity is both are triggered by an exit – in your case the listbox, for me DeclareLibraryMBS. And it’s happening on exit, even when the thread itself is not running anymore.

I’ve solved this possible crash by creating a copy of the picture that the thread creates. Doing this in the main thread. Then I send the copy to the canvases. That way the picture being created by the thread and the picture being painted are not the same object.

Excellent detective work.

It does still seem like the ThreadAccessingUI exception is misleading here. Perhaps Xojo could come up with a more accurate way to describe this error. Since you’ve positively identified the problem, a sample project with the issue readily reproducible would be helpful for them to consider a new classification of exception.

Well I don’t know if that is the problem. Only long term testing will tell. But it’s elimination of a source of a problem. :grinning:

Yeah, that didn’t do it… :frowning:

Same issue in the crash. Same spot…

Termination Reason:    Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process:   exc handler [46545]

VM Region Info: 0x7b is not in any region.  Bytes before following region: 4374101893
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  
      __TEXT                      104b78000-106748000    [ 27.8M] r-x/r-x SM=COW  /Users/USER/Desktop/*/MediaSwitcher 11.app/Contents/MacOS/MediaSwitcher

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   XojoFramework                 	       0x10827c3e8 0x10800c000 + 2556904
1   XojoFramework                 	       0x10827c134 RuntimeUnlockObject + 120
2   MediaSwitcher                 	       0x106069468 DeviceMaintWindow.DeviceMaintWindow.DeviceList_CellTextPaint%%o<DeviceMaintWindow.DeviceMaintWindow>o<ListBoxPopup>o<Graphics>i8i8i8i8 + 17568
3   MediaSwitcher                 	       0x1058c58c8 Delegate.IM_Invoke%%o<ListBoxPopup>o<Graphics>i8i8i8i8 + 100
4   MediaSwitcher                 	       0x1058c5964 AddHandler.Stub.51%%o<Graphics>i8i8i8i8 + 136
5   MediaSwitcher                 	       0x1059690bc ListBoxPopup.Event_cellTextPaint%b%o<ListBoxPopup>o<Graphics>i8i8i8i8 + 1588
6   MediaSwitcher                 	       0x1058fe5cc AlternatingList.Event_CellTextPaint%b%o<AlternatingList>o<Graphics>i8i8i8i8 + 200
7   XojoFramework                 	       0x10821b15c RuntimeListbox::DrawCellText(Graphics*, xojo::Rect<xojo::Points> const*, CellEntry*, int, int, bool, bool, int) + 560
8   XojoFramework                 	       0x108219fb0 RuntimeListbox::DrawCell(Graphics*, xojo::Rect<xojo::Points> const*, RowEntry*, CellEntry*, int, int, unsigned char) + 1016
9   XojoFramework                 	       0x1082199f0 RuntimeListbox::HandleDrawRow(Graphics*, int, xojo::Rect<xojo::Points> const&, unsigned char, std::__1::vector<xojo::Rect<xojo::Points>, std::__1::allocator<xojo::Rect<xojo::Points>>> const&) + 524
10  XojoFramework                 	       0x108218ec0 RuntimeListbox::RedrawCore(Graphics*, std::__1::vector<xojo::Rect<xojo::Points>, std::__1::allocator<xojo::Rect<xojo::Points>>> const&) + 536
11  XojoFramework                 	       0x1082191d0 RuntimeListbox::Redraw(Graphics*, std::__1::vector<xojo::Rect<xojo::Points>, std::__1::allocator<xojo::Rect<xojo::Points>>> const&) + 220
12  XojoFramework                 	       0x1081074e0 0x10800c000 + 1029344
13  AppKit                        	       0x19bc817d4 _NSViewDrawRect + 124