From c9ab27e2814dffdc1845669b1ec1e8a5ff2d3484 Mon Sep 17 00:00:00 2001 From: MUHAMED FAZAL PS Date: Tue, 23 Jun 2026 21:38:39 +0530 Subject: [PATCH] fix(ftp): close FTP client connection and protocol on all code paths FTPDownloadHandler.download_request() creates an FTPClient via ClientCreator.connectTCP() but never calls loseConnection(), leaking the TCP connection. Additionally, the ReceivedDataProtocol is not closed on the CommandFailed error path, leaking file handles or memory buffers. Move protocol.close() into a finally block and add client.loseConnection() there so both resources are always cleaned up regardless of success or failure. Fixes #7602 --- scrapy/core/downloader/handlers/ftp.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scrapy/core/downloader/handlers/ftp.py b/scrapy/core/downloader/handlers/ftp.py index 6258067c1..0aa6e025a 100644 --- a/scrapy/core/downloader/handlers/ftp.py +++ b/scrapy/core/downloader/handlers/ftp.py @@ -119,7 +119,9 @@ class FTPDownloadHandler(BaseDownloadHandler): httpcode = self.CODE_MAPPING.get(ftpcode, self.CODE_MAPPING["default"]) return Response(url=request.url, status=httpcode, body=message.encode()) raise - protocol.close() + finally: + protocol.close() + client.loseConnection() headers = {"local filename": protocol.filename or b"", "size": protocol.size} body = protocol.filename or protocol.body.read() respcls = responsetypes.from_args(url=request.url, body=body)