> On Fri, Jul 06, 2007 at 02:46:38PM +0200, [EMAIL PROTECTED] wrote:
> > I think I found the cause of my deadlock, which is (if I'm right that
is),
> > located in main.py:912:
> >
> > val = cache.get(id, cls)
> > if val is None:
> > try:
> > val = cls(_SO_fetch_no_create=1)
> >
> > We reach this place e.g. by resolving a foreign key through
> > _SO_foreignKey() and get().
> >
> > If I read the code correctly, the cache's lock is acquired in
cache.get()
> > (but not released, which would be done in cache.finishPut(cls)), if the
> > object doesn't already exist. cls(_SO_fetch_no_create=1) then acquires
the
> > class' lock through the threadSafeMethod() wrapper in declarative.py.
> >
> > On the other hand, if I'm creating an object of the same type, at
exactly
> > the time between the cache.get() and cls() calls, I'll be able to
acquire
> > the class' lock and then pend on the cache's lock, through threadSafe
> > __init__(), then _create(), then _SO_finishCreate(),
cacheSet.created(),
> > CacheFactory.created() and finally CashFactory.cull().
> >
> > This leaves us with the first thread having acquired the cache's lock
while
> > pending for the class' lock, and the second thread having acquired the
> > class' lock and pending for the cache's lock -> deadlock. The situation
can
> > only occur, if the creation of the object triggers a cache.cull(). In
any
> > other case, the cache isn't locked and thus there are no problems.
> >
> > Does this all make sense?
>
> Absolutely. Thank you for the excellent analysis! But could the cache
> release the lock before the new row (SQLObject) is put to the cache? I
> doubt it.
I'm not (yet) an expert on sqlobject's inner goings, but I'd say the same.
Otherwise it would be possible for some other thread to start fetching the
same object again.
My hacky solution is to not acquire the class's lock in __init__(), when in
the process of fetching an instance:
def threadSafeMethod(lock):
def decorator(fn):
def _wrapper(self, *args, **kwargs):
if '_SO_fetch_no_create' in kwargs:
return fn(self, *args, **kwargs)
[...]
If I see that correctly, the class lock isn't really needed in __init__()
while fetching. But there should certainly be nicer way to do that.
Bernhard
___________________________________________________________________
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