]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Fixed ipc/Queue notification race leading to stuck, overflowing queues.
authorAlex Rousskov <rousskov@measurement-factory.com>
Fri, 21 Jun 2013 00:50:35 +0000 (18:50 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Fri, 21 Jun 2013 00:50:35 +0000 (18:50 -0600)
The writer calling OneToOneUniQueue::push() must tell readers if it places the
first item into a previously empty queue. We used to determine emptiness prior
to incrementing queue size. That created a window between wasEmpty calculation
and queuing the new item (by incrementing the queue size). During that window,
the readers could pop() all previously queued items (resulting in an empty
queue) but since that happened after wasEmpty was computed to be false, the
writer would not notify them about the new item it just placed, and they will
get stuck, eventually resulting in queue overflow errors.

The fix attempts to increment the queue size and extract the previous size
value atomically.

src/ipc/Queue.h

index 47e0de618527dc919c0b4a8023c34baad87445f4..f3e196d00a6a423678b5bdee94683b0c6a5676a6 100644 (file)
@@ -397,10 +397,9 @@ OneToOneUniQueue::push(const Value &value, QueueReader *const reader)
     if (full())
         throw Full();
 
-    const bool wasEmpty = empty();
     const unsigned int pos = theIn++ % theCapacity * theMaxItemSize;
     memcpy(theBuffer + pos, &value, sizeof(value));
-    ++theSize;
+    const bool wasEmpty = !theSize++;
 
     return wasEmpty && (!reader || reader->raiseSignal());
 }