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

fix race in transport thread startup
set active=True from the methods that start the main transport thread, right
before actually starting the thread.  this avoids a race where the main
thread could be started, but the original thread could wake up from the
event.wait(0.1) before the new thread actually set the transport active.
impossible, you say?  no machines so slow exist?  au contraire, my sad
little linux box faced this problem earlier today.
This commit is contained in:
Robey Pointer 2005-02-28 07:16:22 +00:00
parent 4b8a9d3b7a
commit 246f3d46a2
1 changed files with 10 additions and 5 deletions

View File

@ -269,7 +269,7 @@ class BaseTransport (threading.Thread):
@rtype: str @rtype: str
""" """
out = '<paramiko.BaseTransport at %s' % hex(id(self)) out = '<paramiko.BaseTransport at %s' % hex(long(id(self)) & 0xffffffffL)
if not self.active: if not self.active:
out += ' (unconnected)' out += ' (unconnected)'
else: else:
@ -320,6 +320,7 @@ class BaseTransport (threading.Thread):
@type event: threading.Event @type event: threading.Event
""" """
self.completion_event = event self.completion_event = event
self.active = True
self.start() self.start()
def start_server(self, event=None, server=None): def start_server(self, event=None, server=None):
@ -360,6 +361,7 @@ class BaseTransport (threading.Thread):
self.server_mode = True self.server_mode = True
self.server_object = server self.server_object = server
self.completion_event = event self.completion_event = event
self.active = True
self.start() self.start()
def add_server_key(self, key): def add_server_key(self, key):
@ -708,7 +710,7 @@ class BaseTransport (threading.Thread):
event = threading.Event() event = threading.Event()
self.start_client(event) self.start_client(event)
while 1: while True:
event.wait(0.1) event.wait(0.1)
if not self.active: if not self.active:
e = self.get_exception() e = self.get_exception()
@ -887,7 +889,7 @@ class BaseTransport (threading.Thread):
while len(out) > 0: while len(out) > 0:
try: try:
n = self.sock.send(out) n = self.sock.send(out)
except: except Exception, x:
# could be: (32, 'Broken pipe') # could be: (32, 'Broken pipe')
n = -1 n = -1
if n < 0: if n < 0:
@ -1062,10 +1064,13 @@ class BaseTransport (threading.Thread):
return self._cipher_info[name]['class'].new(key, self._cipher_info[name]['mode'], iv) return self._cipher_info[name]['class'].new(key, self._cipher_info[name]['mode'], iv)
def _run(self): def _run(self):
self.active = True # active=True occurs before the thread is launched, to avoid a race
_active_threads.append(self) _active_threads.append(self)
if self.server_mode:
self._log(DEBUG, 'starting thread (server mode): %s' % hex(long(id(self)) & 0xffffffffL))
else:
self._log(DEBUG, 'starting thread (client mode): %s' % hex(long(id(self)) & 0xffffffffL))
try: try:
# SSH-1.99-OpenSSH_2.9p2
self._write_all(self.local_version + '\r\n') self._write_all(self.local_version + '\r\n')
self._check_banner() self._check_banner()
self._send_kex_init() self._send_kex_init()