Threading problems at program exit
Dave Cole
djc at object-craft.com.au
Fri Nov 29 18:53:32 EST 2002
The following program demonstrates a problem I am experiencing with
the threading module. I have an object (A) which holds a lock on
another object (B). When object A is deleted I want it to release any
lock it may still be holding on object B.
Everything works fine except when the program terminates.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
import sys
import threading
class Locked:
def __init__(self, lock):
self._lock = lock
self._lock_count = 0
self._thread = None
self._log = sys.stderr.write
self._current_thread = threading.currentThread
self.lock()
def lock(self):
self._log('locked in %s\n' % self._current_thread())
self._lock.acquire()
self._lock_count += 1
def unlock(self):
self._log('unlocked in %s\n' % self._current_thread())
self._lock_count -= 1
self._lock.release()
def __del__(self):
while self._lock_count:
self.unlock()
obj = Locked(threading.RLock())
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
When I run this program I get the following:
locked in <_MainThread(MainThread, started)>
unlocked in <_DummyThread(Dummy-1, started daemon)>
Exception exceptions.AssertionError: <exceptions.AssertionError instance at 0x814fbfc> in <bound method Locked.__del__ of <__main__.Locked instance at 0x816e5f4>> ignored
It looks like interpreter is deleting thread objects before objects
which hold locks in those threads. Is there any kosher way I can
avoid the problem?
The only way I can think to fix it is a bit non-kosher:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
import sys
import threading
class Locked:
def __init__(self, lock):
self._lock = lock
self._lock_count = 0
self._thread = None
self._log = sys.stderr.write
self._current_thread = threading.currentThread
self.lock()
def lock(self):
self._log('locked in %s\n' % self._current_thread())
self._lock.acquire()
self._lock_count += 1
def unlock(self):
self._log('unlocked in %s\n' % self._current_thread())
self._lock_count -= 1
self._lock.release()
def __del__(self):
if self._lock_count:
count, owner = self._lock._release_save()
self._log('owner was %s\n' % owner)
owner = self._current_thread()
self._log('owner is now %s\n' % owner)
self._lock._acquire_restore((count, owner))
while self._lock_count:
self.unlock()
obj = Locked(threading.RLock())
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
This prints the following:
locked in <_MainThread(MainThread, started)>
owner was <_MainThread(MainThread, stopped)>
owner is now <_DummyThread(Dummy-1, started daemon)>
unlocked in <_DummyThread(Dummy-1, started daemon)>
The trouble is that it requires the use of private methods of the
RLock class.
Is there a better or more kosher way?
- Dave
--
http://www.object-craft.com.au
More information about the Python-list
mailing list