[Python-bugs-list] [ python-Bugs-788520 ] Queue class has logic error when non-blocking

SourceForge.net noreply at sourceforge.net
Sun Aug 17 14:50:11 EDT 2003


Bugs item #788520, was opened at 2003-08-14 00:57
Message generated for change (Comment added) made by tim_one
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=788520&group_id=5470

Category: Threads
Group: Python 2.2.2
Status: Open
Resolution: None
Priority: 5
Submitted By: Gary Donovan (gazzadee)
Assigned to: Nobody/Anonymous (nobody)
Summary: Queue class has logic error when non-blocking

Initial Comment:
Looking at the Queue class, I noticed that it might
incorrectly raise a Full/Empty Exception when called
with block=False.

This leads to the following undesirable behaviour:
 * Full exception raised when Queue not full
 * Full exception raised when Queue has no maxsize

Here's my logic (for put(), but get() is similar):

First part of code for put, in Queue.py:
    def put(self, item, block=1):
        if block:
            self.fsema.acquire()
        elif not self.fsema.acquire(0):
            raise Full

Now, for the purposes of raising a Full exception, we
are assuming that fsema is locked if and only if the
Queue is full.

BUT, it seems that fsema is locked every time an item
is added to the Queue, even if that item would not make
the Queue full.

Hence, it might be possible for a Full exception to be
raised, when fsema is locked due to adding an item that
would not  actually make the Queue full. 

An example...

 * Queue with maxsize 10, currently 5 objects in it.
 * Threads T1 and T2, both trying to add an item with
Queue.put(item, block=True).
 * This should obviously be fine, resulting in a Queue
with 7 items.
 [1] Call T1.put(item1, block=True)
 [2] Call T2.put(item2, block=True)
 [3] T1 grabs fsema and mutex, but then the current
thread changes before they are released...
 [4] T2 cannot acquire fsema (since T1 currently has
it), and so raises the Full exception (incorrectly)

Of course, I may have misunderstood something, since I
haven't been able to consistently reproduce the problem
(threading errors are so vexing).

I have no easy solution to this issue (redo the class
using a threading.BoundedSemaphore to count the Queue
length?).

My python version:
Python 2.2.2 (#1, Feb 24 2003, 17:36:09)
[GCC 3.0.4 (Mandrake Linux 8.2 3.0.4-2mdk)] on linux2

----------------------------------------------------------------------

>Comment By: Tim Peters (tim_one)
Date: 2003-08-17 16:50

Message:
Logged In: YES 
user_id=31435

Yes, but unless it's a screamingly obvious non-bug I like to 
wait at least a week to see whether somebody else has a 
clever approach that works as well but without the surprising 
parts.  The docs in this case aren't terribly clear, because 
they really can't explain the whole truth without explaining 
the implementation.

----------------------------------------------------------------------

Comment By: Raymond Hettinger (rhettinger)
Date: 2003-08-17 16:30

Message:
Logged In: YES 
user_id=80475

Can this be closed as invalid?

----------------------------------------------------------------------

Comment By: Tim Peters (tim_one)
Date: 2003-08-14 10:59

Message:
Logged In: YES 
user_id=31435

As the docs say (ALL CAPS emphasis added),

"""
exception Full 

Exception raised when non-blocking put() (or put_nowait()) is 
called on a Queue object which is full OR LOCKED. 
"""

and similarly for Empty.  The primary point of a non-blocking 
call is never to block, and that's why "or locked" is in the 
docs.  A BoundedSemaphore (or any other "reliable" 
synchronization gimmick) could block, so cannot be used.

In practice, it doesn't matter:  a Queue user who wants to 
use non-blocking calls has to be prepared for Full or Empty 
exceptions, and that's the end of it.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=788520&group_id=5470



More information about the Python-bugs-list mailing list