[ace-users] Possible bug in ACE_Task_Base::cleanup.
Douglas C. Schmidt
schmidt at dre.vanderbilt.edu
Wed Jul 11 15:38:07 CDT 2007
Hi Folks,
This seems like it's becoming a FAQ ;-) Dmitry, please take a look at
chapter 9 of C++NPv1 <www.cs.wustl.edu/~schmidt/ACE/book1> and chapter 6
of C++NPv2 <www.cs.wustl.edu/~schmidt/ACE/book2> for information on
how/why to wait for threads before exiting main().
Thanks,
Doug
> Hi,
>
> Thanks for using the PRF form. The thread exits when svc returns, so the
> thread count could be correct. Before exiting main you should wait until all
> threads have finished.
>
> Regards,
>
> Johnny Willemsen
> Remedy IT
> Postbus 101
> 2650 AC Berkel en Rodenrijs
> The Netherlands
> www.theaceorb.nl / www.remedy.nl
>
> *** Integrated compile and test statistics see
> http://scoreboard.theaceorb.nl ***
> *** Commercial service and support for ACE/TAO/CIAO ***
> *** See http://www.theaceorb.nl/en/support.html ***
>
> "Krivenok Dmitry" <krivenok.dmitry at gmail.com> wrote in message
> news:<1184179813.151737.56650 at g4g2000hsf.googlegroups.com>...
> > ACE VERSION: 5.5.8
> >
> > HOST MACHINE and OPERATING SYSTEM:
> > 1) Machine : AMD Athlon 64 3500+, 512Mb RAM
> > 2) OS: Gentoo Linux
> > Kernel : 2.6.20
> > Glibc : 2.5-r3
> >
> > COMPILER NAME AND VERSION (AND PATCHLEVEL):
> > olimpico ~ # gcc --version
> > gcc (GCC) 4.1.2 (Gentoo 4.1.2)
> >
> > AREA/CLASS/EXAMPLE AFFECTED:
> > I've wrote very simple program that demonstrates the problem:
> >
> > ################## Simple example #########################
> >
> > #include "ace/Task.h"
> > #include <list>
> >
> > // Active object.
> > class Job : public ACE_Task_Base
> > {
> > public:
> > Job()
> > {
> > // Do nothing
> > }
> >
> > virtual ~Job()
> > {
> > // Do nothing
> > }
> >
> > virtual int svc(void)
> > {
> > // Do nothing
> > }
> > };
> >
> >
> > int main()
> > {
> > std::list<Job*> jobs;
> >
> > const int threads_number = 10000;
> >
> > for(int k=0; k<threads_number; ++k)
> > {
> > // Deleting all jobs that have already finished.
> > typedef std::list<Job*>::iterator IT;
> > for(IT i=jobs.begin(); i!=jobs.end(); /* NOP */)
> > {
> > // This condition isn't the same that active
> > // object has become passive ...
> > if( (*i)->thr_count() == 0 )
> > {
> > delete *i; // and hence BOOM !!!
> > jobs.erase(i++);
> > }
> > else ++i;
> > }
> >
> > // Creating new job.
> > Job* job = new Job;
> > jobs.push_back(job);
> >
> > // Activating job (note: detached mode).
> > assert(job->activate(THR_NEW_LWP |
> > THR_DETACHED |
> > THR_INHERIT_SCHED) != -1);
> > }
> > return 0;
> > }
> >
> > ####################### Makefile ###########################
> > BINARY=trouble
> >
> > all:
> > g++ -g main.cpp -lACE -pthread -o $(BINARY)
> > clean:
> > rm -f $(BINARY)
> > ############################################################
> >
> >
> > DOES THE PROBLEM AFFECT:
> > Execution only.
> >
> > SYNOPSIS:
> > Sometimes ACE_Task_Base::thr_count() returns 0 even if the
> > object is still active!
> >
> > DESCRIPTION:
> > Documentation says about ACE_Task_Base::thr_count():
> > Returns the number of threads currently running within a task.
> > If we're a passive object this value is 0, else it's greater than 0.
> >
> > The problem lies in that sometimes ACE_Task_Base::thr_count()
> > returns 0 even if the object is still active!
> >
> > Look at the code of ACE_Task_Base::cleanup (with my comments):
> >
> > 00227 {
> > 00228 ACE_Task_Base *t = (ACE_Task_Base *) object;
> > 00229
> > 00230 // The thread count must be decremented first in case the
> > <close>
> > 00231 // hook does something crazy like "delete this".
> > 00232 {
> > 00233 ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, t->lock_));
> > Threads counter is decremented here!
> > 00234 t->thr_count_--;
> > 00235 if (0 == t->thr_count_)
> > 00236 t->last_thread_id_ = ACE_Thread::self ();
> > After this line the lock will be released.
> > 00237 }
> > Suppose that another thread (for example main thread in my program)
> > is checking object's state (active or passive) right now.
> > It calls thr_count() that returns 0, since we have just decremented
> > the value of thr_count_.
> > So, if the object is in passive mode it's safe to delete them.
> > Am I right?
> > And another thread deletes active object using delete operator.
> > 00238
> > 00239 // @@ Is it possible to pass in the exit status somehow?
> > However this object is still active.
> > The problem is that it has been already destroyed by another thread!!!
> > What happens at this line?
> > 00240 t->close ();
> > Segmentation fault in my case!!!
> > 00241 // t is undefined here. close() could have deleted it.
> > 00242 }
> >
> > REPEAT BY:
> > I run my test program several times as follows:
> > for ((i=1;i<100;i++)) do echo $i ; ./trouble ; done
> > 1
> > 2
> > 3
> > ...
> > ...
> > ...
> > 91
> > 92
> > 93
> > Segmentation fault (core dumped)
> > 94
> > 95
> > 96
> > 97
> > 98
> > 99
> >
> >
> > What you think about this problem?
> > Is it a bug of ACE_Task_Base class?
> >
>
> _______________________________________________
> ace-users mailing list
> ace-users at mail.cse.wustl.edu
> http://mail.cse.wustl.edu/mailman/listinfo/ace-users
More information about the Ace-users
mailing list