Hi Oleg

[EMAIL PROTECTED] schrieb am 05.07.2007
11:31:56:

> On Thu, Jul 05, 2007 at 11:22:36AM +0200, [EMAIL PROTECTED] wrote:
> > The accesses are made in different threads, to objects of the same
class
> > (MyClass in my example). One locks while resolving a ForeignKey in
> > _SO_foreignKey(), one locks in _SO_finishCreate() and the third one in
the
> > selectresult's __iter__().
>
>    Can you do an experiment - create objects of OtherClass outside of
> _create() and assign them to foreign keys after the object has been fully
> created?
>

I've tried to produce an isolated example of my problem. I'm not yet sure
if everything's needed in here, I'm still trying to buil it further down.

Things I noticed so far:

 - The _create seems not to have anything to do with it, as it locks even
without one.
 - A higher number of threads increase the possibility for deadlocks.
 - I need to have two classes, MyClass1 and MyClass2, in order for the
deadlock to occur.

To the code:
 - On my machine, the code deadlocks after some 10s of objects created.
 - The threadframe module may be downloaded here:
http://www.majid.info/mylos/stories/2004/06/10/threadframe.html. Maybe you
have some clever debugger that can do that for you... :-)

Thanks!
Bernhard

#****************************************************

import sqlobject
import threading
import time

sqlobject.sqlhub.processConnection =
sqlobject.connectionForURI('mysql://XXX')


class Attribute(sqlobject.SQLObject):
    """
    Attribute class
    """
    attributeSet = sqlobject.ForeignKey('AttributeSet')

    name = sqlobject.StringCol(default = '')
    value = sqlobject.StringCol(default = '')

class AttributeSet(sqlobject.SQLObject):
    """
    Attribute set class, contains attributes
    """
    attributes  = sqlobject.SQLMultipleJoin('Attribute')

    def _set_attributes(self, attrs):
        # First clear...
        for attr in self.attributes: attr.destroySelf()

        # ... then set.
        for k, v in attrs.items():
            Attribute(attributeSet = self, name = k, value = v)

    def _get_attributes(self):
        attrs = {}
        for attribute in list(self._SO_get_attributes()):
            attrs[attribute.name] = attribute.value
        return attrs


class MyClass1(sqlobject.SQLObject):
    """
    First class that uses an attribute set.
    """
    attrSet = sqlobject.ForeignKey('AttributeSet', default = None)

    # I would want to create the attribute set here, but for
    # Oleg's suggestion, I'm doing it from the calling class.

    #def _create(self, *args, **kw):
        #super(MyClass1, self)._create(*args, **kw)

        #self.attrSet = AttributeSet()
        #self.attrSet.attributes = dict(foo = 1, bar = 2)


class MyClass2(sqlobject.SQLObject):
    """
    Second class that uses an attribute set.
    """
    attrSet = sqlobject.ForeignKey('AttributeSet', default = None)

    #def _create(self, *args, **kw):
        #super(MyClass2, self)._create(*args, **kw)

        #self.attrSet = AttributeSet()
        #self.attrSet.attributes = dict(foo = 1, bar = 2)

# Create tables.
Attribute.createTable(ifNotExists = True)
AttributeSet.createTable(ifNotExists = True)
MyClass1.createTable(ifNotExists = True)
MyClass2.createTable(ifNotExists = True)


class MyThread(threading.Thread):
    """
    A thread that produces instances of MyClass1 or Myclass2.
    """
    def __init__(self, Klass):
        super(MyThread, self).__init__()
        self._Klass = Klass

    def run(self):
        print '%02d %02d %20s : Started' % (time.localtime().tm_min,
time.localtime().tm_sec, threading.currentThread().getName())
        for i in range(100):
            mc = self._Klass()
            mc.attrSet = AttributeSet()
            mc.attrSet.attributes = dict(foo = 1, bar = 2)

            # Accessing these will result in a deadlock
            for key, value in mc.attrSet.attributes.items():
                pass

            if i % 10 == 0:
                print '%02d %02d %20s : %s' % (time.localtime().tm_min,
time.localtime().tm_sec, threading.currentThread().getName(), i)


# Create some threads
threads = [MyThread(MyClass1) for i in range(10)] + [MyThread(MyClass2) for
i in range(10)]

print 'Starting threads'

for t in threads: t.start()

time.sleep(10)
import threadframe, traceback, sys
frames = threadframe.threadframe()

print '-' * 72

for frame in frames:
    print '-' * 72
    print 'frame ref count = %d' % sys.getrefcount(frame)
    traceback.print_stack(frame, file=sys.stdout)

for t in threads: t.join()

print 'Done'

#****************************************************


___________________________________________________________________

Disclaimer:


Diese Mitteilung ist nur fuer die Empfaengerin / den Empfaenger bestimmt.

Fuer den Fall, dass sie von nichtberechtigten Personen empfangen wird,
bitten wir diese hoeflich, die Mitteilung an die ZKB zurueckzusenden und
anschliessend die Mitteilung mit allen Anhaengen sowie allfaellige Kopien
zu vernichten bzw. zu loeschen. Der Gebrauch der Information ist verboten.


This message is intended only for the named recipient and may contain
confidential or privileged information.

If you have received it in error, please advise the sender by return e-mail
and delete this message and any attachments. Any unauthorised use or
dissemination of this information is strictly prohibited.
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
sqlobject-discuss mailing list
sqlobject-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss

Reply via email to