Page 1 of 1

GetThreadStackTrace returns nothing - Delphi XE3/XE5 64bit

PostPosted: Thu Oct 31, 2013 5:38 pm
by PavKa
Hi,
I have madCollection 4.0.8.1 installed.
Delphi XE3 or XE5 - one form VCL forms application.
madExcept.GetThreadStackTrace(); returns empty string if compiler target platform is Windows 64 bit
and returns proper stack trace if compiler target platform is Windows 32 bit

procedure TForm1.Button1Click(Sender: TObject);
begin
Vcl.Dialogs.ShowMessage(madExcept.GetThreadStackTrace());
end;

Please advise on the issue.

Thank you,
Pavel

Re: GetThreadStackTrace returns nothing - Delphi XE3/XE5 64b

PostPosted: Thu Oct 31, 2013 7:49 pm
by madshi
I've double and triple checked my code, changed a few things, but the underlying API (StackWalk64) doesn't seem to work right. I'm not sure why. From what I can see, I'm calling it correctly.

A google search seems to recommend raising a dummy exception to do a stack trace for the current thread. That seems to work nicely:

Code: Select all
function GetThreadStackTrace_Hacked() : UnicodeString;
begin
  try
    integer(nil^) := 0;
  except
    result := GetCrashStackTrace();
  end;
end;

Ugly, but I don't have a better solution at the moment.

Re: GetThreadStackTrace returns nothing - Delphi XE3/XE5 64b

PostPosted: Thu Oct 31, 2013 9:10 pm
by PavKa
Thank you for the quick answer - we will use recommended hack for now.

Also I am not sure, but should Wow64GetThreadContext be used for win64 instead of GetThreadContext in GetThreadInfos (madexcept.pas)?

Thank you,
Pavel

Re: GetThreadStackTrace returns nothing - Delphi XE3/XE5 64b

PostPosted: Thu Oct 31, 2013 9:16 pm
by madshi
The information returned by GetThreadContext() is not actually used for the x64 stack trace. Actually for the stack trace I'm using RtlCaptureContext(), which is the recommended method to initialize the context for x64 stack walking.

Re: GetThreadStackTrace returns nothing - Delphi XE3/XE5 64b

PostPosted: Fri Dec 29, 2017 12:55 pm
by jmarder
> but I don't have a better solution at the moment.

I wonder if anything has improved in the past 4 years regarding this issue?
Otherwise it could make sense to at least add the workaround to MadExcept.

Re: GetThreadStackTrace returns nothing - Delphi XE3/XE5 64b

PostPosted: Fri Dec 29, 2017 1:09 pm
by madshi
I haven't tested if the problem is gone in newer OSs or not. If not, the workaround should still work. I'm not eager to add the workaround to madExcept because if I do, even if the underlying problem gets fixed in a future OS version, the dummy exception would always stay in madExcept.

Re: GetThreadStackTrace returns nothing - Delphi XE3/XE5 64b

PostPosted: Fri Dec 29, 2017 1:16 pm
by jmarder
> I'm not eager to add the workaround to madExcept

So you think it is better if many of your customers run into that issue, spend time in analyzing the issue and seeking a workaround, and then all copy this workaround to their projects?


> the dummy exception would always stay in madExcept.

It should be fairly easy to use it only below a certain Windows build number.

Re: GetThreadStackTrace returns nothing - Delphi XE3/XE5 64b

PostPosted: Fri Dec 29, 2017 4:37 pm
by PavKa
I've just retested it with Tokyo 10.2 Update 1 - it does not work (still returns empty stack trace).

for years we use workaround:

Code: Select all
function GetStackTrace: string;

  // Re: GetThreadStackTrace returns nothing - Delphi XE3/XE5 64b
  // http://forum.madshi.net/viewtopic.php?f=4&t=27637&p=46729#p46729
  // Unread postby madshi ยป Thu Oct 31, 2013 7:49 pm
  // I've double and triple checked my code, changed a few things, but the underlying API (StackWalk64) doesn't seem to work right. I'm not sure why. From what I can see, I'm calling it correctly.
  // A google search seems to recommend raising a dummy exception to do a stack trace for the current thread. That seems to work nicely:
  function _GetThreadStackTrace_Hacked: UnicodeString;
  var
    vPos: integer;
  begin
    try
      Abort;
    except
      Result := madExcept.GetCrashStackTrace;
      // remove part of the stack generated by this call
      vPos := pos('GetStackTrace', Result);
      if vPos <> -1  then
        Result := copy(Result, vPos + 14);
    end;
  end;

begin
  // in case of exception need a crash stack - otherwise just current stack
  if ExceptAddr <> nil then
    Result := madExcept.GetCrashStackTrace
  else
    Result := _GetThreadStackTrace_Hacked;
end;


Thank you,
Pavel

Re: GetThreadStackTrace returns nothing - Delphi XE3/XE5 64b

PostPosted: Wed Jul 18, 2018 11:56 pm
by leolam
you have to suspend the thread to get it to work.

Re: GetThreadStackTrace returns nothing - Delphi XE3/XE5 64b

PostPosted: Thu Jul 19, 2018 6:49 am
by madshi
This thread is about getting the callstack of the current thread. If you suspend your own thread, you're dead.