[Ace-users] Possible bug in ACE_Task_Base::cleanup.

Krivenok Dmitry krivenok.dmitry at gmail.com
Wed Jul 11 13:50:13 CDT 2007


    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?



More information about the Ace-users mailing list