[fpc-pascal] Re: Multi-threaded project with few locks (no Thread.waitfor). Memory consumption keeps increasing on Ubuntu 10.10 x64

Vinzent Höfler JeLlyFish.software at gmx.net
Fri Oct 15 17:57:54 CEST 2010


On Fri, 15 Oct 2010 16:45:04 +0200, Andrew Brunner
<andrew.t.brunner at gmail.com> wrote:

> It was also suggested that PThread's Suspend and Resume may not do
> anything.  What I would do (if that is the case), is try to find where
> PThread has access to the Semaphore  or CriticalSection it has on that
> thread...

Huh? Why should the pthreads library have a semaphore or similar on each
thread?

> IMO. You must assume that all variables of the TThread descendant have
> already been assigned and are valid.

Yes, but you can't. Even if you assign all values before calling the
inherited Create, there is a hidden function called "AfterConstruction"
which gets executed out of the threads context, so for instance the
thread id may not be set yet (actually, the thread id is returned
earliest when Execute gets called, so there's no way to retrieve it
*before*). If you access it inside the execute method, you more or
less crash (or at least leak memory).

It took me a couple of days to find the reason for our application
crashing and I believe that was fixed quite a while ago. (Somewhere
around 2.0.4, IIRC). Jonas may remember.

Excerpt from the workaround I had written then:


type
    //-- @abstract(Thread  class circumventing a race condition in thread
    //--           creation present in the fpc 2.0.x tree.)
    //-- The workaround works by starting the thread routine in suspended
    //-- mode  and  waking  it  up after the constructor is known to have
    //-- finished initializing all needed instance internals.
    tThread = class (Classes.tThread)
    public
       {/= Create =====================================================\}
       {                                                                }
       {\==============================================================/}
       //-- @abstract(The usual thread constructor.)
       //-- Overwritten to ensure it starts in suspended state,  woken up
       //-- by @link(AfterConstruction) a little moment later.
       constructor Create;

       {$IFDEF UNIX}
       {/= Destroy ====================================================\}
       {                                                                }
       {\==============================================================/}
       //-- @abstract(Destroys  the  thread  and  does a "best effort" to
       //--           avoid  memory  leaks  by deciding if it should call
       //--           pthread_detach or pthread_join (WaitFor).)
       destructor Destroy; override;
       {$ENDIF UNIX}

       {/= AfterConstruction ==========================================\}
       {                                                                }
       {\==============================================================/}
       //-- @abstract(Resumes the suspended thread.)
       //-- This  ensures  that  the  constructor completed before @code(
       //-- Execute) is actually running.
       procedure AfterConstruction; override;

    end {tThread};

A similar workaround got into FPC a while later and it *was* for a
good reason: Safety.

> There is no need to block the thread from execution.

Actually there currently is. Otherwise you ask for trouble.

> That is unless they are asking to have it
> suspended on creation.  And if that is the case... We need to tie into
> PThread's Semaphore or Event or CriticalSection and exploit that.

What do you want to tie into there?


Vinzent.



More information about the fpc-pascal mailing list