Преглед изворни кода

Fixed crash in case # of "sendEvent" calls exceeds thread pool size.

The ctkEALinkedQueue class deleted the wrong node element. Further,
clean up code for memory handling of ctkEARunnable objects.
Sascha Zelzer пре 13 година
родитељ
комит
22d496e556

+ 3 - 1
Plugins/org.commontk.eventadmin/dispatch/ctkEALinkedQueue.cpp

@@ -87,6 +87,7 @@ ctkEARunnable* ctkEALinkedQueue::take()
       catch(const ctkEAInterruptedException& ex)
       catch(const ctkEAInterruptedException& ex)
       {
       {
         --waitingForTake_;
         --waitingForTake_;
+        if (x && x->autoDelete() && !--x->ref) delete x;
         putLockWait_.wakeOne();
         putLockWait_.wakeOne();
         throw ex;
         throw ex;
       }
       }
@@ -144,6 +145,7 @@ ctkEARunnable* ctkEALinkedQueue::poll(long msecs)
     catch(const ctkEAInterruptedException& ex)
     catch(const ctkEAInterruptedException& ex)
     {
     {
       --waitingForTake_;
       --waitingForTake_;
+      if (x && x->autoDelete() && !--x->ref) delete x;
       putLockWait_.wakeOne();
       putLockWait_.wakeOne();
       throw ex;
       throw ex;
     }
     }
@@ -176,8 +178,8 @@ ctkEARunnable* ctkEALinkedQueue::extract()
     {
     {
       x = first->value;
       x = first->value;
       first->value = 0;
       first->value = 0;
+      delete head_;
       head_ = first;
       head_ = first;
-      delete first;
     }
     }
     return x;
     return x;
   }
   }

+ 1 - 1
Plugins/org.commontk.eventadmin/dispatch/ctkEALinkedQueue_p.h

@@ -48,7 +48,7 @@ struct ctkEALinkedNode
   {
   {
     if (value && value->autoDelete())
     if (value && value->autoDelete())
     {
     {
-      if (!--value->ref) delete value;
+      !--value->ref;
     }
     }
   }
   }
 
 

+ 15 - 4
Plugins/org.commontk.eventadmin/dispatch/ctkEAPooledExecutor.cpp

@@ -379,7 +379,9 @@ ctkEAPooledExecutor::DiscardOldestWhenBlocked::DiscardOldestWhenBlocked(ctkEAPoo
 
 
 bool ctkEAPooledExecutor::DiscardOldestWhenBlocked::blockedAction(ctkEARunnable* command)
 bool ctkEAPooledExecutor::DiscardOldestWhenBlocked::blockedAction(ctkEARunnable* command)
 {
 {
-  pe->handOff_->poll(0);
+  ctkEARunnable* tmp = pe->handOff_->poll(0);
+  if (tmp && tmp->autoDelete() && !--tmp->ref) delete tmp;
+
   if (!pe->handOff_->offer(command, 0))
   if (!pe->handOff_->offer(command, 0))
   {
   {
     const bool autoDelete = command->autoDelete();
     const bool autoDelete = command->autoDelete();
@@ -393,7 +395,7 @@ void ctkEAPooledExecutor::addThread(ctkEARunnable* command)
 {
 {
   Worker* worker = new Worker(this, command);
   Worker* worker = new Worker(this, command);
   ++worker->ref;
   ++worker->ref;
- ctkEAInterruptibleThread* thread = getThreadFactory()->newThread(worker);
+  ctkEAInterruptibleThread* thread = getThreadFactory()->newThread(worker);
   threads_.insert(worker, thread);
   threads_.insert(worker, thread);
   ++poolSize_;
   ++poolSize_;
 
 
@@ -426,8 +428,17 @@ void ctkEAPooledExecutor::workerDone(Worker* w)
     try
     try
     {
     {
       ctkEARunnable* r = handOff_->poll(0);
       ctkEARunnable* r = handOff_->poll(0);
-      if (r != 0 && !shutdown_) // just consume task if shut down
-        addThread(r);
+      if (r != 0)
+      {
+        if(shutdown_) // just consume task if shut down
+        {
+          if (r->autoDelete() && !r->ref) delete r;
+        }
+        else
+        {
+          addThread(r);
+        }
+      }
     }
     }
     catch(const ctkEAInterruptedException& ) {
     catch(const ctkEAInterruptedException& ) {
       return;
       return;