Skip to content

Commit b15db24

Browse files
committed
Improve handling of KeyboardInterrupt and task cancellation in SCP
This commit makes sure to re-raise CancelledError when an SCP operation is cancelled, letting the calling code sees the exception and can decide whether to cancel future operations or not. Thanks go to Viktor Kertesz for reporting this issue and helping to understand the behavior in various versions of Python. This also includes a small change to abort an SCP session when KeyboardInterrupt is raised, closing the session more quickly.
1 parent 5f3bf9d commit b15db24

File tree

2 files changed

+9
-5
lines changed

2 files changed

+9
-5
lines changed

asyncssh/scp.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -579,8 +579,9 @@ async def run(self, srcpath: _SCPPath) -> None:
579579
for name in await SFTPGlob(self._fs).match(srcpath):
580580
await self._send_files(cast(bytes, name.filename),
581581
b'', name.attrs)
582-
except asyncio.CancelledError:
582+
except (KeyboardInterrupt, asyncio.CancelledError):
583583
cancelled = True
584+
raise
584585
except (OSError, SFTPError) as exc:
585586
self.handle_error(exc)
586587
finally:
@@ -745,8 +746,9 @@ async def run(self, dstpath: _SCPPath) -> None:
745746
dstpath))
746747
else:
747748
await self._recv_files(b'', dstpath)
748-
except asyncio.CancelledError:
749+
except (KeyboardInterrupt, asyncio.CancelledError):
749750
cancelled = True
751+
raise
750752
except (OSError, SFTPError, ValueError) as exc:
751753
self.handle_error(exc)
752754
finally:
@@ -911,8 +913,9 @@ async def run(self) -> None:
911913

912914
try:
913915
await self._copy_files()
914-
except asyncio.CancelledError:
916+
except (KeyboardInterrupt, asyncio.CancelledError):
915917
cancelled = True
918+
raise
916919
except (OSError, SFTPError) as exc:
917920
self._handle_error(exc)
918921
finally:

tests/test_sftp.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5047,9 +5047,10 @@ def _cancel(_srcpath, _dstpath, _bytes_copied, _total_bytes):
50475047
self._create_file('src', 1024*8192 * 'a')
50485048

50495049
coro = scp(src, dst, block_size=8192, progress_handler=_cancel)
5050-
50515050
task = asyncio.create_task(coro)
5052-
await task
5051+
5052+
with self.assertRaises(asyncio.CancelledError):
5053+
await task
50535054
finally:
50545055
remove('src dst')
50555056

0 commit comments

Comments
 (0)