Forum > Debugger

Debugging problem on Windows 11 ARM

<< < (3/9) > >>

Martin_fr:
Ouch, when I compared the timestamps
814140
814401

I somehow -in my mind  - swapped some digits around, and saw 1 sec difference.... My bad.
So then, all the "access denied" is fine. That is when you stop the app. And expected.

Let's look again.

Martin_fr:
OK, so indeed the app is just kept suspended....

I have 2 ideas. I added a lot of debug output.

Here the patch (or attached the complete file, based on 2.2)

--- Code: Diff  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---diff --git a/components/fpdebug/fpdbgwinclasses.pas b/components/fpdebug/fpdbgwinclasses.pasindex 9d5094a167..9b3b757500 100644--- a/components/fpdebug/fpdbgwinclasses.pas+++ b/components/fpdebug/fpdbgwinclasses.pas@@ -722,6 +722,11 @@ class function TDbgWinProcess.isSupported(ATargetInfo: TTargetDescriptor             (ATargetInfo.machineType in [mt386, mtX86_64]); end; +function dbgsThread(AThread: TDbgThread): string;+begin+  if AThread = nil then result := 'nil' else Result := IntToStr(AThread.ID);+end;+ function TDbgWinProcess.Continue(AProcess: TDbgProcess; AThread: TDbgThread;   SingleStep: boolean): boolean; @@ -740,7 +745,7 @@ function TDbgWinProcess.Continue(AProcess: TDbgProcess; AThread: TDbgThread; var   EventThread, t: TDbgThread; begin-debugln(FPDBG_WINDOWS, ['TDbgWinProcess.Continue ',SingleStep]);+debugln(FPDBG_WINDOWS, ['TDbgWinProcess.Continue ',SingleStep, ' ',DbgSTime, ' thread=',dbgsThread(AThread), ' event-tid=', MDebugEvent.dwThreadId]);   if assigned(AThread) and not FThreadMap.HasId(AThread.ID) then begin     AThread := nil;   end;@@ -804,6 +809,7 @@ function TDbgWinProcess.Continue(AProcess: TDbgProcess; AThread: TDbgThread;     if SingleStep then       TDbgWinThread(AThread).SetSingleStep;   end;+debugln('go before continue');   AProcess.ThreadsBeforeContinue; if AThread<>nil then debugln(FPDBG_WINDOWS, ['## ath.iss ',AThread.NextIsSingleStep]); @@ -811,13 +817,18 @@ function TDbgWinProcess.Continue(AProcess: TDbgProcess; AThread: TDbgThread;     case MDebugEvent.Exception.ExceptionRecord.ExceptionCode of      EXCEPTION_BREAKPOINT, STATUS_WX86_BREAKPOINT,      EXCEPTION_SINGLE_STEP, STATUS_WX86_SINGLE_STEP: begin+debugln(['GOING TO RUN: DBG_CONTINUE ',MDebugEvent.dwThreadId]);        result := Windows.ContinueDebugEvent(MDebugEvent.dwProcessId, MDebugEvent.dwThreadId, DBG_CONTINUE);      end-    else-      result := Windows.ContinueDebugEvent(MDebugEvent.dwProcessId, MDebugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);+     else begin+debugln(['GOING TO RUN: DBG_EXCEPTION_NOT_HANDLED ',MDebugEvent.dwThreadId]);+        result := Windows.ContinueDebugEvent(MDebugEvent.dwProcessId, MDebugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);+    end;     end-  else+  else begin+debugln(['GOING TO RUN: DBG_CONTINUE ',MDebugEvent.dwThreadId]);     result := Windows.ContinueDebugEvent(MDebugEvent.dwProcessId, MDebugEvent.dwThreadId, DBG_CONTINUE);+  end;   DebugLn((FPDBG_WINDOWS or DBG_WARNINGS) and (not Result), 'ContinueDebugEvent failed: %d', [Windows.GetLastError]);   result := true;   MDebugEvent.dwProcessId := 0; // Flag as running // for assert in ReadThreadState@@ -1562,6 +1573,7 @@ procedure TDbgWinThread.Suspend; var   r: DWORD; begin+debugln(['About to suspend ', id, ' already=', FIsSuspended, ' skip break=',FIsSkippingBreakPoint]);   if FIsSuspended then     exit;   r := SuspendThread(Handle);@@ -1586,6 +1598,7 @@ procedure TDbgWinThread.Resume; begin   if not FIsSuspended then     exit;+debugln(['About to Resume', id]);   r := ResumeThread(Handle);   FIsSuspended := not(r <> DWORD(-1));   debugln(DBG_WARNINGS and (r = DWORD(-1)), 'Failed to resume Thread %d (handle: %d). Error: %s', [Id, Handle, GetLastErrorText]);@@ -1609,11 +1622,17 @@ procedure TDbgWinThread.SetSingleStep;     if not ReadThreadState then       exit;   {$ifdef cpux86_64}-  if (TDbgWinProcess(Process).FBitness = b32) then+  if (TDbgWinProcess(Process).FBitness = b32) then begin+debugln(['Settig single step flag ', id, '  current = ', FCurrentContext^.WOW.EFlags or FLAG_TRACE_BIT]);     FCurrentContext^.WOW.EFlags := FCurrentContext^.WOW.EFlags or FLAG_TRACE_BIT // TODO WOW_FLAG....-  else+  end+  else begin   {$endif}+debugln(['Settig single step flag ', id, '  current = ', FCurrentContext^.def.EFlags or FLAG_TRACE_BIT]);     FCurrentContext^.def.EFlags := FCurrentContext^.def.EFlags or FLAG_TRACE_BIT;+  {$ifdef cpux86_64}+  end;+  {$endif}   FThreadContextChanged:=true; end; @@ -1681,8 +1700,9 @@ function TDbgWinThread.DetectHardwareWatchpoint: Pointer;  procedure TDbgWinThread.BeforeContinue; begin+debugln(['TDbgWinThread.BeforeContinue ', id, ' / ',FThreadContextChanged, '  susp=',FIsSuspended]);   if ID = MDebugEvent.dwThreadId then begin-    inherited;+    inherited;  ///////////////////////////// MOVE this up, outside the "IF"      {$ifdef cpux86_64}     if (TDbgWinProcess(Process).FBitness = b32) then begin 

Once you reproduced the error, and have a log for it, find the line

--- Code: Text  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---   inherited;  ///////////////////////////// MOVE this up, outside the "IF"And move it to the begin of the procedure, so it is unconditionally executed (that is actually already done in git main, but apparently wasn't merged.

And depending, on if that helps or not, you could also follow my earlier suggestion:
(if either of my 2 ideas is correct, this should make the issue go away...)

--- Quote ---   components\fpdebug\fpdbgwinclasses.pas
   line 1600

--- Code: Text  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---    procedure TDbgWinThread.Suspend;         ...         procedure TDbgWinThread.Resume;      
In both procedures insert an "exit;" as very first statement. So both functions will exit without doing anything at all.
--- End quote ---


A bit of background.
So the process is not started again. Well it is "started/continued", but it then does not execute a single asm instruction. So it might be started suspended.
And that is where I can think of 2 ways this could happen.

FpDebug suspends some of the threads, while it has to temporarily remove the breakpoint. If it wouldn't suspend the other threads, they could run that code, and would never hit the (temp removed) breakpoint.

1) Maybe FpDebug somehow suspends all threads - the new log will hopefully tell me.

2) When a breakpoint is hit, it's possible the OS creates a temporary thread. Then maybe if that is suspended (depending on some timing), it will hold the main thread too....
Actually, I don't see that on my Windows 10....
But I did see threads starting and stopping in your log - they may of course be something else entirely.

On that note, could you open the "thread window" and when it hangs provide a snapshot?
The log doesn't have the names of the procedures (will be somewhere in the kernel), and the thread window may show those names.


Thanks for helping.

Luc:
Thanks Martin,
I will have a look tomorrow

Luc:
Hi Martin,

Problem has gone away :)

Not really as this is done by bypassing some procedures but I applied all the patches an it doesn't hang anymore.

A: I started by replacing fpdbgwinclasses.pas by the one you provided, recompiling the fpDebug package and rebuilding the IDE
Result : no change, debugger hangs

B: I moved the "inherited" on top of IF statement and rebuilt fpDebug + IDE
Result: no change, debugger hangs

C: I added Exit; on Supend and Resume procedures and rebuilt fpDebug + IDE
Result: Everything is fine, no more "hang" 

I guess you found the code causing the issue.
I can revert back to step B or A to help find the problematic code if you need so.   

Martin_fr:

--- Quote from: Luc on June 28, 2022, 09:27:04 am ---A: I started by replacing fpdbgwinclasses.pas by the one you provided, recompiling the fpDebug package and rebuilding the IDE
Result : no change, debugger hangs

--- End quote ---

Expected. But could I have the logs for that run please?

And could I have a screenshot of the "threads window" while the debugger hangs?



--- Quote ---C: I added Exit; on Supend and Resume procedures and rebuilt fpDebug + IDE
Result: Everything is fine, no more "hang" 
--- End quote ---
Ok, at least something to go on.


If you want to use FpDebug, you can use it with those 2 "exit" in place. It should be stable.

The only difference will be:
- If you have more than one thread.
- If at least 2 of them run the same code (i.e. Both of them run through the procedure "DoSomeStuff"
- You have a breakpoint in "DoSomeStuff"
- One thread stopped at that breakpoint

Now you continue (step or run) => the one thread must go over the breakpoint. For this the debugger needs to temporarily remove that breakpoint.

If the other thread reaches the place of that breakpoint, just in that tiny moment, then the other thread will pass the breakpoint without entering pause.

Example, if you have code like

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---for i := 0 to 9999999999 do begin  x := data[i];  if x = val then    CallFoo;  // breakpoint hereend;
And you have several threads running that loop at the same time (each with its own "data"). Then one (or more) of the threads could enter "CallFoo" without stopping at the breakpoint.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version