[project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-28]

fix lingering thread bug
this bug has been in there forever and i could never figure out a workaround
till now.

when the python interpreter exits, it doesn't necessarily destroy the
remaining objects or call __del__ on anything, and it will lock up until all
threads finish running.  how the threads are supposed to notice the exiting
interpreter has always been sort of a mystery to me.

tonight i figured out how to use the 'atexit' module to register a handler
that runs when the interpreter exits.  now we keep a list of active threads
and ask them all to exit on shutdown.  no more going to another shell to
kill -9 python!  yeah!!
This commit is contained in:
Robey Pointer 2004-03-08 09:47:47 +00:00
parent 3e31771637
commit c565d66e39
1 changed files with 11 additions and 0 deletions

View File

@ -76,6 +76,15 @@ except:
randpool.randomize() randpool.randomize()
# for thread cleanup
_active_threads = []
def _join_lingering_threads():
for thr in _active_threads:
thr.active = False
import atexit
atexit.register(_join_lingering_threads)
class BaseTransport (threading.Thread): class BaseTransport (threading.Thread):
""" """
Handles protocol negotiation, key exchange, encryption, and the creation Handles protocol negotiation, key exchange, encryption, and the creation
@ -788,6 +797,7 @@ class BaseTransport (threading.Thread):
def _run(self): def _run(self):
self.active = True self.active = True
_active_threads.append(self)
try: try:
# SSH-1.99-OpenSSH_2.9p2 # SSH-1.99-OpenSSH_2.9p2
self._write_all(self.local_version + '\r\n') self._write_all(self.local_version + '\r\n')
@ -838,6 +848,7 @@ class BaseTransport (threading.Thread):
self._log(DEBUG, 'Unknown exception: ' + str(e)) self._log(DEBUG, 'Unknown exception: ' + str(e))
self._log(DEBUG, tb_strings()) self._log(DEBUG, tb_strings())
self.saved_exception = e self.saved_exception = e
_active_threads.remove(self)
if self.active: if self.active:
self.active = False self.active = False
if self.completion_event != None: if self.completion_event != None: