Re: TThread and ROOT-5.08 (fwd)

From: Joern Adamczewski <J.Adamczewski_at_gsi.de>
Date: Wed, 8 Feb 2006 13:27:44 +0100


Hallo ROOT TThread users,

maybe the problem you observe is related to some crucial part of the ROOT TThread classes concerning the TThread::Delete and Cleanup() methods.

We observed a similar case last year, but it seemed to depend on the compiler/system environment and the application if this causes a crash. I must admit that I did not report and discuss this with ROOT team more early, sorry...

In dtor of your example code you do:
> > > TThread::Printf("Now deleting");
> > > TThread::Delete(th1);
> > > delete th1; // not really needed
Actually, the outside pointer th1 (to TThread*) is not necessarily reset to 0 by TThread::Delete (which invokes TThread::CleanUp() and TThread destructor) So delete th1 should not be used after Delete! The reason is some slight problem when passing the pointer th1 over to TThread classes (please correct me if I totally misunderstood this):

In method:
Int_t TThread::Delete(TThread *th)
{

   // Static method to delete the specified thread.

   if (!th) return 0;
   th->fHolder = &th;
...
}
the address of the pointer th is passed to member fHolder; this variable is later used in CleanUp and TThread dtor:

Int_t TThread::CleanUp()
{

   // Static method to cleanup the calling thread.

   TThread *th = Self();
   if (!th) return 13;

   fgThreadImp->CleanUp(&(th->fClean));
   fgMainMutex->CleanUp();
   fgXActMutex->CleanUp();
   if (th->fHolder)
      delete th;

   return 0;
}
If CleanUp is called and fHolder is existing, thread object is deleted. OK. (note that pointer th here is different from th in Delete()!)

Now the dtor as executed in delete:

TThread::~TThread()
{

   // Cleanup the thread.

.....
.....

   if (fHolder) *fHolder = 0;
}
The last line intends to reset outside pointer, so outside "delete th1" will see 0 and knows that thread is already gone. However, fHolder has address of local variable th in TThread::Delete, but is not necessarily pointing to outside variable (in your example th1)!. By passing arguments to methods, just the values are copied, i.e. th has the same value as th1, but is not the identical pointer! So I guess the last line of thread dtor will fail here.

To achieve what I think was intended here, the Delete method should better look like:



TThread::Delete(TThread** pptr)
{
        TThread* th=*pptr;      
        th->fHolder=pptr;

...
}

However, this would require a change of the TThread API itself. All users would then be forced to write
TThread::Delete(&th1) instead TThread::Delete(th1) (for your example). This would affect all existing code.

Perhaps somebody else has another idea what to do here?

For now, best advice maybe is to recommend not deleting threads manually after calling the TThread::Delete...

Best regards,

Joern

-- 
/////////////////////////////////////////////////////////////////////
// Dr. J"orn Adamczewski                    (J.Adamczewski_at_gsi.de) // 
// GO4 project team / data processing group Tel: +49-6159-71-1337  //
// Experiment Electronics department (EE)   FAX: +49-6159-71-2986  //
// Ges. f. SchwerIonenforschung, Planckstr.1,  D-64291 Darmstadt   //
Received on Wed Feb 08 2006 - 13:28:01 MET

This archive was generated by hypermail 2.2.0 : Mon Jan 01 2007 - 16:31:57 MET