Skip to content

Commit

Permalink
Merge pull request #1345 from cisagov/za/fix-test-connection
Browse files Browse the repository at this point in the history
Connection Pool - Close dangling test_connection sockets
  • Loading branch information
zandercymatics authored Nov 16, 2023
2 parents 652086a + cc132cd commit e0e0950
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 10 deletions.
6 changes: 5 additions & 1 deletion src/epplibwrapper/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def _send(self, command):
# Flag that the pool is frozen,
# then restart the pool.
self.pool_status.pool_hanging = True
logger.error("Pool timed out")
self.start_connection_pool()
except (ValueError, ParsingError) as err:
message = f"{cmd_type} failed to execute due to some syntax error."
Expand Down Expand Up @@ -174,6 +175,7 @@ def get_pool(self):

def _create_pool(self, client, login, options):
"""Creates and returns new pool instance"""
logger.info("New pool was created")
return EPPConnectionPool(client, login, options)

def start_connection_pool(self, restart_pool_if_exists=True):
Expand All @@ -187,7 +189,7 @@ def start_connection_pool(self, restart_pool_if_exists=True):
# Since we reuse the same creds for each pool, we can test on
# one socket, and if successful, then we know we can connect.
if not self._test_registry_connection_success():
logger.warning("Cannot contact the Registry")
logger.warning("start_connection_pool() -> Cannot contact the Registry")
self.pool_status.connection_success = False
else:
self.pool_status.connection_success = True
Expand All @@ -197,6 +199,7 @@ def start_connection_pool(self, restart_pool_if_exists=True):
if self._pool is not None and restart_pool_if_exists:
logger.info("Connection pool restarting...")
self.kill_pool()
logger.info("Old pool killed")

self._pool = self._create_pool(self._client, self._login, self.pool_options)

Expand All @@ -221,6 +224,7 @@ def _test_registry_connection_success(self):
credentials are valid, and/or if the Registrar
can be contacted
"""
# This is closed in test_connection_success
socket = Socket(self._client, self._login)
can_login = False

Expand Down
21 changes: 12 additions & 9 deletions src/epplibwrapper/socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def __exit__(self, *args, **kwargs):

def connect(self):
"""Use epplib to connect."""
logger.info("Opening socket on connection pool")
self.client.connect()
response = self.client.send(self.login)
if self.is_login_error(response.code):
Expand All @@ -40,11 +41,13 @@ def connect(self):

def disconnect(self):
"""Close the connection."""
logger.info("Closing socket on connection pool")
try:
self.client.send(commands.Logout())
self.client.close()
except Exception:
except Exception as err:
logger.warning("Connection to registry was not cleanly closed.")
logger.error(err)

def send(self, command):
"""Sends a command to the registry.
Expand Down Expand Up @@ -77,23 +80,23 @@ def test_connection_success(self):
try:
self.client.connect()
response = self.client.send(self.login)
except LoginError as err:
if err.should_retry() and counter < 10:
except (LoginError, OSError) as err:
logger.error(err)
should_retry = True
if isinstance(err, LoginError):
should_retry = err.should_retry()
if should_retry and counter < 3:
counter += 1
sleep((counter * 50) / 1000) # sleep 50 ms to 150 ms
else: # don't try again
return False
# Occurs when an invalid creds are passed in - such as on localhost
except OSError as err:
logger.error(err)
return False
else:
self.disconnect()

# If we encounter a login error, fail
if self.is_login_error(response.code):
logger.warning("A login error was found in test_connection_success")
return False

# Otherwise, just return true
return True
finally:
self.disconnect()
2 changes: 2 additions & 0 deletions src/epplibwrapper/utility/pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def kill_all_connections(self):
"""Kills all active connections in the pool."""
try:
if len(self.conn) > 0 or len(self.greenlets) > 0:
logger.info("Attempting to kill connections")
gevent.killall(self.greenlets)

self.greenlets.clear()
Expand All @@ -107,6 +108,7 @@ def kill_all_connections(self):

# Clear the semaphore
self.lock = BoundedSemaphore(self.size)
logger.info("Finished killing connections")
else:
logger.info("No connections to kill.")
except Exception as err:
Expand Down

0 comments on commit e0e0950

Please sign in to comment.