Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Delphi 2009 wait chain traversal available in Windows 7 installations?

According to the "What's New in Delphi 2009," there is a new debugger features called "wait chain traversal." It specifically says "A Wait Chain Traversal feature has been added to help you resolve thread contention or deadlock issues. The feature relies on a facility added to the Windows Vista operating system that provides information to the debugger about the wait status of your application's threads in the form of a wait chain."

Delphi 2009 was released when Windows Vista was the current operating system. From my experience, most of the features introduced in Vista are also available in Windows 7. However, I do not see this feature anywhere in my Delphi 2009 through Delphi XE installations (all on Windows 7).

I am looking for this feature on the debugger's Threads pane.

  1. Am I looking for wait chain traversal in the correct place?

  2. Is it a features truly only available in Windows Vista, and not in Windows 7?

David M provided a nice and clear answer, but I still don't get the Wait Chain column in the Threads pane. Here is some code.

Main Form:

unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, SyncObjs, RanThread;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure ThreadDone(Sender: TObject);
  end;

var
  Form1: TForm1;
  RanGenThread: TRandomizer;

implementation

uses LoadThread;

{$R *.dfm}

{ TForm1 }

procedure TForm1.ThreadDone(Sender: TObject);
begin
  RanGenThread.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
ListBox1.Sorted := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Thread: TLoader;
begin
ListBox1.Items.Clear;
ListBox1.Sorted := False;
RanGenThread := TRandomizer.Create(True);
RanGenThread.ArraySize := 1000;
Thread := TLoader.Create(True);
with Thread do
begin
  RanGenThread.WaitThread := Thread;
  FreeOnTerminate := True;
  OnTerminate := ThreadDone;
  WaitForThread := RanGenThread;
  //Use Start in Delphi 2010 or later, where Resume is deprecated
  Resume;
end;
RanGenThread.Resume;
end;

initialization
  Randomize;

end.

TRandomizer:

unit RanThread;

interface

uses
  Classes, Math, SyncObjs;

type
  TRandomizer = class(TThread)
  private
    { Private declarations }
    FArraySize: Integer;
  protected
    procedure Execute; override;
  public
    WaitThread: TThread;
    RandNumbers: array of Integer;
    property ArraySize: Integer read FArraySize write FArraySize;

  end;

implementation

uses Main;

procedure TRandomizer.Execute;
var
  i: Integer;
  LowNum, HighNum: Integer;
  RandNum: Integer;
begin
if FArraySize = 0 then
  begin
    Exit;
  end;
SetLength(RandNumbers, FArraySize);
LowNum := Low(RandNumbers);
HighNum := High(RandNumbers);
//initialize the array
for i := LowNum to HighNum do
  RandNumbers[i] := -1;
// generate the random order
for i := LowNum to HighNum do
  while True do
    begin
      RandNum := RandomRange(LowNum, HighNum + 1);
      if RandNumbers[RandNum] = -1 then
      begin
        RandNumbers[RandNum] := i + 1;
        break;
      end; // if
    end; // while
    WaitThread.WaitFor;
end;

end.

TLoader:

unit LoadThread;

interface

uses
  Classes, SyncObjs, Dialogs, SysUtils, RanThread;

type
  TLoader = class(TThread)
  private
    FWaitForThread: TRandomizer;
    procedure UpdateList;
    { Private declarations }
  protected
    procedure Execute; override;
  public
    property WaitForThread: TRandomizer
      read FWaitForThread write FWaitForThread;
  end;

implementation

uses Main;

procedure TLoader.UpdateList;
var
 i: Integer;
begin
for i := Low(FWaitForThread.RandNumbers) to
  High(FWaitForThread.RandNumbers) do
  Form1.ListBox1.Items.Add(IntToStr(FWaitForThread.RandNumbers[i]));
end;

procedure TLoader.Execute;
begin
if WaitForThread <> nil then
begin
  FWaitForThread.WaitFor;
  Synchronize(UpDateList)
end;
end;

end.

According to the wait chain traversal document that David M linked to, WTC is available for the following synchronization objects:

  • ALPC
  • COM
  • Critical sections
  • Mutexes
  • SendMessage
  • Wait operations on processes and threads

My code waits on a thread, but it is a TThread, and not directly a native thread. This evening I will modify my code example to deadlock on waiting for a Mutex, and see if that results in the Wait Chain column appearing in the Thread pane.

OK. Finally found time for the next test. Created an application that took ownership of a Mutex upon startup. Created a worker thread that used OpenMutex to get a handle to that Mutex and then called WaitForsingleObject(handle, INFINITE). Still no Wait Chain column in the Threads pane.

like image 711
Cary Jensen Avatar asked Nov 09 '10 01:11

Cary Jensen


1 Answers

  1. Yes. Write a program with two threads that deadlock. You will see, on the Threads pane, the right-hand column (labeled "Wait Chain") will say something like "Waiting for lock held by thread 12345." I'm not completely certain of the exact phrase since I don't have any deadlocks in my current program right now :) If you don't see it, scroll right. If the column simply doesn't exist, that's very strange - please say so in a comment.

  2. No. Wait chain traversal was introduced in Vista (and Server 2008) and is also available on Windows 7. You can see this by reading the MSDN documentation on wait chain traversal and looking at some of the core functions, which all have comments in the table at the bottom saying "Minimum supported client: Windows Vista". It would say if it was removed in a later version of Windows - the way it's phrased is exactly the way it is for any number of other functions. Also, a colleague using Windows 7 (I have Vista) has this feature.

Edit: I tried your example code in Delphi 2010 (I don't have 2009 I'm afraid) on my Vista machine. I clicked Button1 and Button2, and then switched to the Threads view without pausing the program. The Threads pane had a 'Wait Chain' column, which contained text for the two non-main-thread threads 'Blocked waiting for Thread 11968' or '14416'.

Here's a screenshot:

Wait chain screenshot

So that's what you should get in your IDE if this feature is working.

When you try this, do you get the other columns but not the Wait Chain column? If so I admit I'm a bit puzzled, and I think the next step might be to contact Embarcadero or at least post on one of their forums, probably this one. I did look up what permissions are required for the wait chain functions to work, but it seems like you don't even need SE_DEBUG_NAME if you're working with a process owned by the current user. (I'm not completely certain that's a valid interpretation of the documentation, but...)

I don't suppose your IDE is running under odd privileges or in XP compatibility mode or anything? Edit 4: This is the answer. See Cary's comment below, the shortcut was running in XP compatibility mode.

Edit 2: I thought I'd do a sanity check and look up what their help file says. I can't find the 2009 help online, but the 2010 help says 'Wait Chain: (For Windows Vista and 7 only)'. Cool. Then I looked at the XE help, and it says 'Wait Chain: (For Windows Vista only)'. Very strange.

I suspect this is a documentation bug and it is supposed to work on Windows 7, because I also came across this Delphi 2009 hotfix for wait chain traversal running on Windows 7. Sounds pretty supported to me! There is no way, surely, they'd remove a feature like this in the newest version of their product for the newest version of Windows... is there? Even if they did you're using a version it's documented to work in.

Edit 3: I asked my Windows 7-using colleague to try your example code too. This is what he got:

Wait chain traversal on Windows 7

At this point I admit I'm a bit puzzled. All I can say is that works using RAD Studio 2010 on Windows 7 and, as far as I can tell, should work for you. If it's not I have no more suggestions beyond the few vague ideas above at the moment!

like image 142
David Avatar answered Oct 07 '22 12:10

David