From: Alex Rousskov Date: Fri, 21 Jun 2013 00:50:35 +0000 (-0600) Subject: Fixed ipc/Queue notification race leading to stuck, overflowing queues. X-Git-Tag: SQUID_3_5_0_1~444^2~58 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ad40da437bb8429db775e34bbfa861b9ed501da4;p=thirdparty%2Fsquid.git Fixed ipc/Queue notification race leading to stuck, overflowing queues. 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. --- diff --git a/src/ipc/Queue.h b/src/ipc/Queue.h index 47e0de6185..f3e196d00a 100644 --- a/src/ipc/Queue.h +++ b/src/ipc/Queue.h @@ -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()); }