Skip to content

Commit e4fc3db

Browse files
author
James William Pye
committed
Fix a resource warning caused by a forgotten socket.
The common situation occurred when connecting to 'localhost' where the addrinfo returns IPv6 addresses that aren't fully functional or in use.
1 parent b58dfd2 commit e4fc3db

3 files changed

Lines changed: 47 additions & 51 deletions

File tree

postgresql/driver/pq3.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2441,6 +2441,10 @@ def _establish(self):
24412441
self._receive_async(x)
24422442
# success!
24432443
break
2444+
elif pq.socket is not None:
2445+
# In this case, an application/protocol error occurred.
2446+
# Close out the sockets ourselves.
2447+
pq.socket.close()
24442448

24452449
if sslmode == 'prefer' and ssl is False and didssl is False:
24462450
# In this case, the server doesn't support SSL or it's
@@ -2640,6 +2644,7 @@ def __init__(self, connector, *args, **kw):
26402644
self.connector = connector
26412645
# raw notify messages
26422646
self._notifies = []
2647+
self.fileno = -1
26432648
self.typio = self.connector.driver.typio(self)
26442649
self.typio.set_encoding('ascii')
26452650
self.settings = Settings(self)

postgresql/protocol/client3.py

Lines changed: 41 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -155,60 +155,51 @@ def connect(self, ssl = None, timeout = None):
155155
))
156156
return
157157

158-
try:
159-
if ssl is not None:
160-
# if ssl is True, ssl is *required*
161-
# if ssl is False, ssl will be tried, but not required
162-
# if ssl is None, no SSL negotiation will happen
163-
self.ssl_negotiation = supported = self.negotiate_ssl()
164-
165-
# b'S' or b'N' was *not* received.
166-
if supported is None:
167-
# probably not PQv3..
168-
self.socket.close()
169-
self.xact.fatal = True
170-
self.xact.error_message = not_pq_error
171-
self.xact.state = xact.Complete
172-
return
158+
if ssl is not None:
159+
# if ssl is True, ssl is *required*
160+
# if ssl is False, ssl will be tried, but not required
161+
# if ssl is None, no SSL negotiation will happen
162+
self.ssl_negotiation = supported = self.negotiate_ssl()
163+
164+
# b'S' or b'N' was *not* received.
165+
if supported is None:
166+
# probably not PQv3..
167+
self.xact.fatal = True
168+
self.xact.error_message = not_pq_error
169+
self.xact.state = xact.Complete
170+
return
173171

174-
# b'N' was received, but ssl is required.
175-
if not supported and ssl is True:
176-
# ssl is required..
177-
self.socket.close()
172+
# b'N' was received, but ssl is required.
173+
if not supported and ssl is True:
174+
# ssl is required..
175+
self.xact.fatal = True
176+
self.xact.error_message = no_ssl_error
177+
self.xact.state = xact.Complete
178+
return
179+
180+
if supported:
181+
# Make an SSL connection.
182+
try:
183+
self.socket = self.socket_factory.secure(self.socket)
184+
except Exception as err:
185+
# Any exception marks a failure.
186+
self.xact.exception = err
178187
self.xact.fatal = True
179-
self.xact.error_message = no_ssl_error
180188
self.xact.state = xact.Complete
189+
self.xact.error_message = ssl_failed_error
181190
return
182-
183-
if supported:
184-
# Make an SSL connection.
185-
try:
186-
self.socket = self.socket_factory.secure(self.socket)
187-
except Exception as err:
188-
# Any exception marks a failure.
189-
self.socket.close()
190-
self.xact.exception = err
191-
self.xact.fatal = True
192-
self.xact.state = xact.Complete
193-
self.xact.error_message = ssl_failed_error
194-
return
195-
# time to negotiate
196-
negxact = self.xact
197-
self.complete()
198-
if negxact.state is xact.Complete and negxact.fatal is None:
199-
self.key = negxact.killinfo.key
200-
self.backend_id = negxact.killinfo.pid
201-
elif not hasattr(self.xact, 'error_message'):
202-
# if it's not complete, something strange happened.
203-
# make sure to clean up...
204-
self.socket.close()
205-
self.xact.fatal = True
206-
self.xact.state = xact.Complete
207-
self.xact.error_message = partial_connection_error
208-
except:
209-
if self.socket is not None:
210-
self.socket.close()
211-
raise
191+
# time to negotiate
192+
negxact = self.xact
193+
self.complete()
194+
if negxact.state is xact.Complete and negxact.fatal is None:
195+
self.key = negxact.killinfo.key
196+
self.backend_id = negxact.killinfo.pid
197+
elif not hasattr(self.xact, 'error_message'):
198+
# if it's not complete, something strange happened.
199+
# make sure to clean up...
200+
self.xact.fatal = True
201+
self.xact.state = xact.Complete
202+
self.xact.error_message = partial_connection_error
212203

213204
def negotiate_ssl(self) -> (bool, None):
214205
"""

postgresql/python/socket.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def __call__(self, timeout = None):
6666
s.settimeout(float(timeout) if timeout is not None else None)
6767
s.connect(self.socket_connect)
6868
s.settimeout(None)
69-
except Exception:
69+
except:
7070
s.close()
7171
raise
7272
return s

0 commit comments

Comments
 (0)