|  | 
| 21 | 21 | from warnings import warn | 
| 22 | 22 | 
 | 
| 23 | 23 | from gevent import sleep, spawn, get_hub | 
|  | 24 | +from gevent.lock import RLock | 
| 24 | 25 | from ssh2.error_codes import LIBSSH2_ERROR_EAGAIN | 
| 25 | 26 | from ssh2.exceptions import SFTPHandleError, SFTPProtocolError, \ | 
| 26 | 27 |     Timeout as SSH2Timeout | 
| @@ -127,6 +128,7 @@ def __init__(self, host, | 
| 127 | 128 |                 identity_auth=identity_auth, | 
| 128 | 129 |             ) | 
| 129 | 130 |             proxy_host = '127.0.0.1' | 
|  | 131 | +        self._chan_lock = RLock() | 
| 130 | 132 |         super(SSHClient, self).__init__( | 
| 131 | 133 |             host, user=user, password=password, port=port, pkey=pkey, | 
| 132 | 134 |             num_retries=num_retries, retry_delay=retry_delay, | 
| @@ -291,10 +293,12 @@ def execute(self, cmd, use_pty=False, channel=None): | 
| 291 | 293 |     def _read_output_to_buffer(self, read_func, _buffer): | 
| 292 | 294 |         try: | 
| 293 | 295 |             while True: | 
| 294 |  | -                size, data = read_func() | 
|  | 296 | +                with self._chan_lock: | 
|  | 297 | +                    size, data = read_func() | 
| 295 | 298 |                 while size == LIBSSH2_ERROR_EAGAIN: | 
| 296 | 299 |                     self.poll() | 
| 297 |  | -                    size, data = read_func() | 
|  | 300 | +                    with self._chan_lock: | 
|  | 301 | +                        size, data = read_func() | 
| 298 | 302 |                 if size <= 0: | 
| 299 | 303 |                     break | 
| 300 | 304 |                 _buffer.write(data) | 
| @@ -325,8 +329,9 @@ def wait_finished(self, host_output, timeout=None): | 
| 325 | 329 |         self.close_channel(channel) | 
| 326 | 330 | 
 | 
| 327 | 331 |     def close_channel(self, channel): | 
| 328 |  | -        logger.debug("Closing channel") | 
| 329 |  | -        self._eagain(channel.close) | 
|  | 332 | +        with self._chan_lock: | 
|  | 333 | +            logger.debug("Closing channel") | 
|  | 334 | +            self._eagain(channel.close) | 
| 330 | 335 | 
 | 
| 331 | 336 |     def _eagain(self, func, *args, **kwargs): | 
| 332 | 337 |         return self._eagain_errcode(func, LIBSSH2_ERROR_EAGAIN, *args, **kwargs) | 
|  | 
0 commit comments