Skip to content

Commit 004379f

Browse files
authored
Added channel lock (#324)
* Added channel lock * Updated changelog
1 parent a98114e commit 004379f

File tree

2 files changed

+10
-4
lines changed

2 files changed

+10
-4
lines changed

Changelog.rst

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Fixes
1717
-----
1818

1919
* ``HostOutput`` would have empty host on some exceptions when ``stop_on_errors`` is ``False`` - #297
20+
* Race condition when forcefully closing channel via ``SSHClient.close_channel`` while channel data was left unread.
2021

2122
2.6.0
2223
+++++

pssh/clients/native/single.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from warnings import warn
2222

2323
from gevent import sleep, spawn, get_hub
24+
from gevent.lock import RLock
2425
from ssh2.error_codes import LIBSSH2_ERROR_EAGAIN
2526
from ssh2.exceptions import SFTPHandleError, SFTPProtocolError, \
2627
Timeout as SSH2Timeout
@@ -127,6 +128,7 @@ def __init__(self, host,
127128
identity_auth=identity_auth,
128129
)
129130
proxy_host = '127.0.0.1'
131+
self._chan_lock = RLock()
130132
super(SSHClient, self).__init__(
131133
host, user=user, password=password, port=port, pkey=pkey,
132134
num_retries=num_retries, retry_delay=retry_delay,
@@ -291,10 +293,12 @@ def execute(self, cmd, use_pty=False, channel=None):
291293
def _read_output_to_buffer(self, read_func, _buffer):
292294
try:
293295
while True:
294-
size, data = read_func()
296+
with self._chan_lock:
297+
size, data = read_func()
295298
while size == LIBSSH2_ERROR_EAGAIN:
296299
self.poll()
297-
size, data = read_func()
300+
with self._chan_lock:
301+
size, data = read_func()
298302
if size <= 0:
299303
break
300304
_buffer.write(data)
@@ -325,8 +329,9 @@ def wait_finished(self, host_output, timeout=None):
325329
self.close_channel(channel)
326330

327331
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)
330335

331336
def _eagain(self, func, *args, **kwargs):
332337
return self._eagain_errcode(func, LIBSSH2_ERROR_EAGAIN, *args, **kwargs)

0 commit comments

Comments
 (0)