Page 1 of 1

Debugger crashes with this code..

Posted: Wed Nov 27, 2019 6:41 am
by Rinzwind
Demo code factored down to show problem only and excluding other suspects:

Code: Select all

EnableExplicit


Procedure DoSomething() 
  ;Delay(20)
EndProcedure

Global NewList TestList(), TestListMutex = CreateMutex()
Global DoTaskSemaphore = CreateSemaphore(), _TaskBusy, _DoTaskThread, Quit

Procedure DoTask(i)
  ;Protected NewList _TestList()
  Repeat
    WaitSemaphore(DoTaskSemaphore)
    ;LockMutex(TestListMutex)
    ;CopyList(TestList(), _TestList())
    ;ClearList(TestList())
    ;UnlockMutex(TestListMutex)
    DoSomething()
;     ForEach _TestList()  
;       Select _TestList()
;         Case 1
;           DoSomething()
;       EndSelect
;     Next
  Until Quit
  _DoTaskThread = 0
EndProcedure

Procedure AddTask()
  ;LockMutex(TestListMutex)
  If AddElement(TestList())
    TestList() = 1
  EndIf
  ;UnlockMutex(TestListMutex)
EndProcedure


Procedure Test()
  Protected i
  For i = 1 To 500000
    ;LockMutex(TestListMutex)
    ;AddElement(TestList())
    ;TestList() = 1
    
    AddTask()  ;crashes
    
;   LockMutex(TestListMutex)
;   If AddElement(TestList())  ;works
;     TestList() = 1           ;works
;   EndIf                      ;works
;   UnlockMutex(TestListMutex)    
    
    ;UnlockMutex(TestListMutex)    
    SignalSemaphore(DoTaskSemaphore)
  Next
  
  MessageRequester("", "Done")
  
  
EndProcedure

Global WMain, b1, e
WMain = OpenWindow(#PB_Any, 0, 0, 300, 200, "Test", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
b1 = ButtonGadget(#PB_Any, 10, 10, 100, 30, "A")
_DoTaskThread = CreateThread(@DoTask(), 0)
Repeat
  e = WaitWindowEvent()
  Select e
    Case #PB_Event_Gadget
      Select EventGadget()
        Case b1
          Debug "b1"
          Test()
      EndSelect
  EndSelect
  
Until e = #PB_Event_CloseWindow

Quit = #True
SignalSemaphore(DoTaskSemaphore)
Without debugger no crash. With debugger, only crash when AddTask is called instead of the 3 commented lines with ;works... Other stuff is commented out to pinpoint apparent crash reason. When one commented out the call to DoSomething in DoTask it also stops crashing...

Hope this helps... in full application it kept on crashing randomly while debugging. I suspected a lot of things, but slowly came to this end result :?

Seems like a bug in procedure calling debugging. When both sides call into a procedure before/after signalsemaphore/waitsemaphore (or lockmutex/unlockmutex) (test or dotask) it will crash. Doesn't matter how the rest is implemented.

Another version using lockmutex/unlockmutex that shows same crash behavior:

Code: Select all

EnableExplicit


Procedure DoSomething() 
  ;Delay(20)
EndProcedure

Global NewList TestList(), TestListMutex = CreateMutex()
Global DoTaskSemaphore = CreateSemaphore(), _TaskBusy, _DoTaskThread, Quit

Procedure DoTask(i)
  ;Protected NewList _TestList()
  Repeat
    LockMutex(TestListMutex)
    If ListSize(TestList()) > 0
      UnlockMutex(TestListMutex)
      DoSomething()
      
    Else
      UnlockMutex(TestListMutex)
      Delay(20)
    EndIf
    
    ;WaitSemaphore(DoTaskSemaphore)
    ;LockMutex(TestListMutex)
    ;CopyList(TestList(), _TestList())
    ;ClearList(TestList())
    ;UnlockMutex(TestListMutex)
    ;Delay(20)
    ;DoSomething()
;     ForEach _TestList()  
;       Select _TestList()
;         Case 1
;           DoSomething()
;       EndSelect
;     Next
  Until Quit
  _DoTaskThread = 0
EndProcedure

Procedure AddTask(List lst())
  LockMutex(TestListMutex)
  If AddElement(lst())
    lst() = 1
  EndIf
  UnlockMutex(TestListMutex)
EndProcedure


Procedure Test()
  Protected i
  For i = 1 To 500000
    ;LockMutex(TestListMutex)
    ;AddElement(TestList())
    ;TestList() = 1
    
     AddTask(TestList())  ;crashes
    
;   LockMutex(TestListMutex)
;   If AddElement(TestList())  ;works
;     TestList() = 1           ;works
;   EndIf                      ;works
;   UnlockMutex(TestListMutex)    
    
    ;UnlockMutex(TestListMutex)    
    ;SignalSemaphore(DoTaskSemaphore)
  Next
  
  MessageRequester("", "Done")
  
  
EndProcedure

Global WMain, b1, e
WMain = OpenWindow(#PB_Any, 0, 0, 300, 200, "Test", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
b1 = ButtonGadget(#PB_Any, 10, 10, 100, 30, "A")
_DoTaskThread = CreateThread(@DoTask(), 0)
Repeat
  e = WaitWindowEvent()
  Select e
    Case #PB_Event_Gadget
      Select EventGadget()
        Case b1
          Debug "b1"
          Test()
      EndSelect
  EndSelect
  
Until e = #PB_Event_CloseWindow

Quit = #True
SignalSemaphore(DoTaskSemaphore)



Re: Debugger crashes with this code..

Posted: Thu Nov 28, 2019 6:51 am
by Danilo
It crashes here as well, but when I add the compiler option "[X] Create threadsafe executable" it works fine.

Did you activate 'threadsafe' when you use threads?

Re: Debugger crashes with this code..

Posted: Thu Nov 28, 2019 10:05 am
by Rinzwind
No, but that should not be necessary in this case, since no variables are accessed simultaneously or even accessed at all in the thread (only 'DoSomething' which does nothing).

Re: Debugger crashes with this code..

Posted: Thu Nov 28, 2019 11:06 am
by Danilo
Rinzwind wrote:No, but that should not be necessary in this case, since no variables are accessed simultaneously or even accessed at all in the thread (only 'DoSomething' which does nothing).
It looks like the debugger is not thread-safe without the threadsafe compiler switch.

Re: Debugger crashes with this code..

Posted: Thu Nov 28, 2019 11:35 am
by wilbert
Danilo wrote:It looks like the debugger is not thread-safe without the threadsafe compiler switch.
I think you are right.

If you disable the debugger for the DoSomething procedure, it seems to work without crashing.

Code: Select all

DisableDebugger
Procedure DoSomething() 
  ;Delay(20)
EndProcedure
EnableDebugger

Re: Debugger crashes with this code..

Posted: Fri Nov 29, 2019 12:11 pm
by Rinzwind
Well, even with thread safe on the debugger can't be used in the thread. Just put a breakpoint at DoSomething() and run. It freezes/hangs the debugger...

Also interestingly, in 5.70 it won't crash with threadsafe off/debug on, but still can't actually use breakpoints (freezes with treadsafe on, crashes after step with treadsafe off).