Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

threading bugfix for socket closure #156

Closed
wants to merge 2 commits into from
Closed

Commits on Apr 11, 2013

  1. transport: Wait for thread termination before closing the socket

    Make sure the Thread.run() method has terminated before closing the
    socket. Currently, the socket is closed through Packetizer.close(),
    which happens too early. Move the socket.close() into Transport.close()
    and after the Thread.join() call.
    
    While at it, modify the stop_thread() method and use it in
    Transport.close() to avoid code duplication. Use join() with a timeout
    to make it possible to terminate the main thread with KeyboardInterrupt.
    Also, remove the now obsolete socket.close() from Transport.atfork().
    
    This fixes a potential infinite loop if paramiko.SSHClient is connected
    through a paramiko.Channel instead of a regular socket (tunneling).
    
    Details:
    
    Using a debug patch to dump the current stack of the thread every
    couple of seconds while trying to close it, I've seen the following
    over and over again:
    
    Thread could not be stopped, still running.
    Current traceback (most recent call last):
      File "/usr/lib/python2.7/threading.py", line 524, in __bootstrap
        self.__bootstrap_inner()
      File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
        self.run()
      File ".../paramiko/transport.py", line 1564, in run
        self._channel_handler_table[ptype](chan, m)
      File ".../paramiko/channel.py", line 1102, in _handle_close
        self.transport._send_user_message(m)
      File ".../paramiko/transport.py", line 1418, in _send_user_message
        self._send_message(data)
      File ".../paramiko/transport.py", line 1398, in _send_message
        self.packetizer.send_message(data)
      File ".../paramiko/packet.py", line 319, in send_message
        self.write_all(out)
      File ".../paramiko/packet.py", line 248, in write_all
        n = self.__socket.send(out)
      File ".../paramiko/channel.py", line 732, in send
        self.lock.release()
    
    The thread was running Packetizer.write_all() in an endless loop:
    
    while len(out) > 0:
        ...
        n = Channel.send(out) # n == 0 because channel got closed
        ...
        out = out[n:]         # essentially out = out
    
    Signed-off-by: Frank Arnold <farnold@amazon.com>
    Frank Arnold authored and Steven Noonan committed Apr 11, 2013
    Copy the full SHA
    068bf63 View commit details
    Browse the repository at this point in the history
  2. un-break Python 2.5 compatibility by using isAlive() instead of is_al…

    …ive()
    
    Python's documentation has a bug[1], in that it doesn't correctly annotate
    is_alive as being a function introduced in Python 2.6.
    
    [1] http://bugs.python.org/issue15126
    
    Signed-off-by: Steven Noonan <snoonan@amazon.com>
    Steven Noonan committed Apr 11, 2013
    Copy the full SHA
    5c124cb View commit details
    Browse the repository at this point in the history