At 09:21 PM 16/7/2003 +0200, you wrote:
Etienne Labuschagne wrote at 2003-7-16 00:48 +0200:
... The above is abbreviated, but I can send you a more verbose list with stack traces for each step. I printed out the threading.currentThread().getName()s every step to check which threads are doing what.
I am not really interested in a detailed log :-)
"Storage._transaction" is set in "tpc_begin" and reset in "tpc_abort" and "tpc_finish".
When the check "transaction is self._transaction" fails, look at "self._transaction". When is is None, then someone (maybe a different thread) called "tpc_abort" or "tpc_finish" or (not likely "tpc_begin" was not executed). When it is not None, then its value specifies the transaction that most recently executed "tpc_begin". This must be a different thread (since there is one transaction per thread and "transaction" is ours).
Dieter
Hi there, Thanks again for the pointers above - I helped me find my problem. I made one critically wrong assumption: I assumed a piece of code that I called doesn't change any ZODB objects, so I need not call get_transaction().commit() or abort(). Well, the code DID change a Zope object! This had the wonderful side effect that the object stayed in the Transaction object. This would probably have the effect of causing a memory leak, but for one thing: since Transactions are identified according to thread ids, and thread ids are re-used after previous threads using them exited (well, in Windows anyway), new threads ended up using Transaction objects which still have uncommitted objects in them. These objects are then mixed with the new thread's changed objects which has the same effect as changing ZODB objects from multiple threads - (so you WERE right saying I changed objects from multiple threads! ;) I assume it is safe to call get_transaction().abort() if I'm not sure if the code changed anything and doesn't care if changes are lost? This is probably better than having unfinished transactions lurking around to bite me. Thanks again! Etienne