Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/RTL/Delphi/Thread support    [ Add a report in this area ]  
Report #:  67726   Status: Closed
AV on closing after calling CurrentThread
Project:  Delphi Build #:  12.0.3197.17370
Version:    12.3 Submitted By:   Francois GAILLARD
Report Type:  Crash / Data loss / Total failure Date Reported:  10/9/2008 11:36:55 AM
Severity:    Serious / Highly visible problem Last Updated: 3/20/2012 2:24:39 AM
Platform:    All platforms Internal Tracking #:   265786
Resolution: Fixed (Resolution Comments) Resolved in Build: : 14.0.3455.22156
Duplicate of:  None
Voting and Rating
Overall Rating: (1 Total Rating)
4.00 out of 5
Total Votes: 12
Description
None
Steps to Reproduce:
drop a button on a VCL Forms application with this code:

procedure TForm1.Button1Click(Sender: TObject);
begin
if TThread.CurrentThread.ThreadID = System.MainThreadID then
  ShowMessage('current thread = main thread');
end;

Run the application,
Click the button.
On closing the application you get an AV:

---------------------------
Application Error
---------------------------
Exception EAccessViolation in module ntdll.dll at 0001B1FA.

Access violation at address 7C91B1FA in module 'ntdll.dll'. Write of address 00000010.



Workarounds
None
Attachment
None
Comments

Francois GAILLARD at 10/9/2008 11:43:11 AM -
it seems like a bug linked to the call order of the finalization section in the Classes unit:

DoneThreadSynchronization clears the ThreadLock structure, then
FreeExternalThreads wants to destroy the Thread object you just created when calling CurrentThread, and
that requires the ThreadLock to be already initialized in the call to
EnterCriticalSection(ThreadLock) in TThread.RemoveQueuedEvents...

Primoz Gabrijelcic at 10/10/2008 9:00:42 AM -
For a temporary workaround just 'use' the following unit anywhere in your code.

{:Fix Delphi 2009's invalid finalization order in Classes.pas.
  Written by Primoz Gabrijelcic, http://gp.17slon.com.
  No rights reserved - released to public domain.
}
unit FixD2009Classes;

interface

implementation

uses
  Windows,
  SysUtils,
  Classes;

type
  TCode = array [0..109] of byte;

{$WARN SYMBOL_PLATFORM OFF}

procedure PatchClasses;
{$IFDEF ConditionalExpressions}
{$IF RTLVersion = 20}
var
  i         : integer;
  oldProtect: cardinal;
  pCode     : ^TCode;
  tmp       : DWORD;
const
  COffsets_Call: array [1..12] of integer = (0, 15, 24, 34, 49, 59, 69, 79, 89, 94, 99, 109);
  COffset_UnRegisterModuleClasses = 106;
  COffset_DoneThreadSynchronization = 94;
  COffset_FreeExternalThreads = 99;
  CCallDelta = COffset_FreeExternalThreads - COffset_DoneThreadSynchronization;
{$IFEND}
{$ENDIF}
begin
{$IFDEF ConditionalExpressions}
{$IF RTLVersion = 20}
  pCode := pointer(cardinal(@TStreamReader.ReadToEnd) + COffset_UnRegisterModuleClasses);
  Win32Check(VirtualProtect(pCode, COffsets_Call[High(COffsets_Call)], PAGE_READWRITE, oldProtect));
  try
    for i := Low(COffsets_Call) to High(COffsets_Call) do
      if pCode^[COffsets_Call[i]] <> $E8 then
        raise Exception.Create('Unexpected version of Classes - cannot patch');
    tmp := PDword(@pCode^[COffset_DoneThreadSynchronization+1])^;
    PDword(@pCode^[COffset_DoneThreadSynchronization+1])^ :=
      PDword(@pCode^[COffset_FreeExternalThreads+1])^ + CCallDelta;
    PDword(@pCode^[COffset_FreeExternalThreads+1])^ := tmp - CCallDelta;
  finally VirtualProtect(pCode, COffsets_Call[High(COffsets_Call)], oldProtect, oldProtect); end;
{$IFEND}
{$ENDIF}
end;

initialization
  PatchClasses;
end.

amos szust at 5/29/2009 1:34:53 PM -
this workaround doesnt work after update 4... is it still needed?
thanks

amos szust at 5/16/2009 10:03:37 AM -
does someone know why this patch/fix was not applied into update 1 or 2 of D2009?
thanks

Pera Detlic at 4/10/2009 11:23:29 PM -
Same error is present if you write simple Halt(0) and any of FibPlus components is present.

Roddy Pratt at 2/9/2009 1:41:59 PM -
I just spent a couple of hours bashing my head against this - thanks for reporting it.

Server Response from: ETNACODE01