gh-140691: urllib.request: Close FTP control socket if data socket can't connect (GH-140835)

Co-authored-by: codenamenam <bluetire27@gmail.com>
This commit is contained in:
Petr Viktorin 2025-11-05 11:52:11 +01:00 committed by GitHub
parent 335d83ec04
commit f2bce51b98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 70 additions and 19 deletions

View file

@ -1535,6 +1535,7 @@ def ftp_open(self, req):
dirs, file = dirs[:-1], dirs[-1]
if dirs and not dirs[0]:
dirs = dirs[1:]
fw = None
try:
fw = self.connect_ftp(user, passwd, host, port, dirs, req.timeout)
type = file and 'I' or 'D'
@ -1552,8 +1553,12 @@ def ftp_open(self, req):
headers += "Content-length: %d\n" % retrlen
headers = email.message_from_string(headers)
return addinfourl(fp, headers, req.full_url)
except ftplib.all_errors as exp:
raise URLError(f"ftp error: {exp}") from exp
except Exception as exp:
if fw is not None and not fw.keepalive:
fw.close()
if isinstance(exp, ftplib.all_errors):
raise URLError(f"ftp error: {exp}") from exp
raise
def connect_ftp(self, user, passwd, host, port, dirs, timeout):
return ftpwrapper(user, passwd, host, port, dirs, timeout,
@ -1577,14 +1582,15 @@ def setMaxConns(self, m):
def connect_ftp(self, user, passwd, host, port, dirs, timeout):
key = user, host, port, '/'.join(dirs), timeout
if key in self.cache:
self.timeout[key] = time.time() + self.delay
else:
self.cache[key] = ftpwrapper(user, passwd, host, port,
dirs, timeout)
self.timeout[key] = time.time() + self.delay
conn = self.cache.get(key)
if conn is None or not conn.keepalive:
if conn is not None:
conn.close()
conn = self.cache[key] = ftpwrapper(user, passwd, host, port,
dirs, timeout)
self.timeout[key] = time.time() + self.delay
self.check_cache()
return self.cache[key]
return conn
def check_cache(self):
# first check for old ones