Конференция "KOL" » race condition bug in TThread.WaitFor [Delphi]
 
  • boguslaw (10.05.09 11:25) [0]
    I think there is a bug in TThread implementation in KOL (ver 2.88)
    Try to use WaitFor when in thread Execute there is at least one Synchronize method. It will stuck.
    btw. Terminate method is using dangerous TerminateThread winAPI (memory leak is probable)

    Please check it maybe it is fixed already, maybe my solution is not good, just look at it.

    I remember that I fixed (or made workaround) that by allowing to set Terminated from outside of thread and using

     if not FTerminated then
     begin
       Terminate;
       WaitFor;
     end;

    inside TThread.Destroy then a check in Synchronize removed infinite loop.

    I'm sorry I can't provide a diff.

    Look at code below and compare to official:

    //[destructor TThread.Destroy]
    {$IFDEF ASM_VERSION}
    {$ELSE ASM_VERSION} //Pascal
    destructor TThread.Destroy;
    begin
     RefInc;
     if not FTerminated then
     begin
       Terminate;
       WaitFor;
     end;
     if (FHandle <> 0) then
       CloseHandle(FHandle);
     {$IFDEF PSEUDO_THREADS}
     if StackBottom <> nil then
       FreeMem( StackBottom );
     if MainThread = @ Self then
     begin
       TimeEndPeriod( 10 );
       AllThreads.Free;
     end
       else
     if MainThread <> nil then
     begin
       MainThread.AllThreads.Remove( @ Self );
       if MainThread.AllThreads.Count <= 1 then
         Free_And_Nil( MainThread );
     end;
     {$ENDIF}
     inherited;
    end;
    {$ENDIF ASM_VERSION}

    //*
    //[procedure TThread.Synchronize]
    procedure TThread.Synchronize(Method: TThreadMethod);
    begin
     {$IFDEF PSEUDO_THREADS}
     Method;
    {$ELSE}
    if Terminated then Exit;
    FMethod := Method;
    if Applet <> nil then
     SendMessage( Applet.fHandle, CM_EXECPROC, 0, Integer( @Self ) );
    {$ENDIF}
    end;

    //[procedure TThread.SynchronizeEx]
    procedure TThread.SynchronizeEx( Method: TThreadMethodEx; Param: Pointer );
    begin
    Assert( Param <> nil, 'Parameter must not be NIL' );
    {$IFDEF PSEUDO_THREADS}
    Method( TMethod( Method ).Data, Param );
    {$ELSE}
    if Terminated then Exit;
     FMethodEx := Method;
     SendMessage( Applet.fHandle, CM_EXECPROC, Integer( Param ), Integer( @Self ) );
     {$ENDIF}
    end;

    //*
    //[procedure TThread.Terminate]
    procedure TThread.Terminate;
    begin
    {$IFDEF PSEUDO_THREADS}
    if Assigned( MainThread ) then
    if MainThread.CurrentThread = @ Self then
     MainThread.NextThread;
    {$ELSE}
    Suspend;
    FTerminated := true;
    if Suspended then Resume;
    Waitfor;
     //TerminateThread(FHandle,0);
     //FTerminated := True;
    {$ENDIF}
    end;

    //*
    //[function TThread.WaitFor]
    function TThread.WaitFor: Integer;
    begin
     RefInc;
     Result := -1;
     {$IFDEF PSEUDO_THREADS}
     while not Terminated do
       Resume;
     if Terminated then
       Result := FResult;
     {$ELSE}
     if FHandle = 0 then Exit;
     WaitForSingleObject(FHandle, INFINITE);
     GetExitCodeThread(FHandle, DWORD(Result));
     {$ENDIF}
     RefDec;
    end;

    function TThread.WaitForTime(T: DWORD): Integer;
    {$IFDEF PSEUDO_THREADS}
     var LimitTime: DWORD;
    {$ENDIF}
    begin
     {$IFDEF PSEUDO_THREADS}
     LimitTime := GetTickCount + T;
     RefInc;
     while not Terminated and (GetTickCount < LimitTime) do
       Resume;
     Result := -1;
     if Terminated then
       Result := FResult;
     RefDec;
     {$ELSE}
     Result := WAIT_OBJECT_0;
     RefInc;
     if FHandle = 0 then Exit;
     Result := WaitForSingleObject(FHandle, T);
     if Result = WAIT_OBJECT_0 then
       GetExitCodeThread(FHandle, T);
     RefDec;
     {$ENDIF}
    end;
 
Конференция "KOL" » race condition bug in TThread.WaitFor [Delphi]
Есть новые Нет новых   [134431   +12][b:0][p:0]