From: David H. Irving Date: Sun, 23 Jun 2024 09:37:24 +0000 (-0400) Subject: Handle "SSL SYSCALL error: Success" in psycopg2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=03d2832fbfd053b6f58f0879e823920ca9d71cbb;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Handle "SSL SYSCALL error: Success" in psycopg2 Added "SSL SYSCALL error: Success" to the list of exceptions that are considered a "disconnect" in psycopg2. Fixes: #11522 Closes: #11523 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/11523 Pull-request-sha: 63ad54e49dc3daa459caa29da8cffcb3e47a3f8c Change-Id: I0db49d5c4db418a8e634f5370c76b99aaa3d3af6 --- diff --git a/doc/build/changelog/unreleased_20/11522.rst b/doc/build/changelog/unreleased_20/11522.rst new file mode 100644 index 0000000000..279197a779 --- /dev/null +++ b/doc/build/changelog/unreleased_20/11522.rst @@ -0,0 +1,7 @@ +.. change:: + :tags: bug, postgresql + :tickets: 11522 + + It is now considered a pool-invalidating disconnect event when psycopg2 + throws an "SSL SYSCALL error: Success" error message, which can occur when + the SSL connection to Postgres is terminated abnormally. \ No newline at end of file diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg2.py b/lib/sqlalchemy/dialects/postgresql/psycopg2.py index 6c492a5b25..fc05aca907 100644 --- a/lib/sqlalchemy/dialects/postgresql/psycopg2.py +++ b/lib/sqlalchemy/dialects/postgresql/psycopg2.py @@ -844,33 +844,43 @@ class PGDialect_psycopg2(_PGDialect_common_psycopg): # checks based on strings. in the case that .closed # didn't cut it, fall back onto these. str_e = str(e).partition("\n")[0] - for msg in [ - # these error messages from libpq: interfaces/libpq/fe-misc.c - # and interfaces/libpq/fe-secure.c. - "terminating connection", - "closed the connection", - "connection not open", - "could not receive data from server", - "could not send data to server", - # psycopg2 client errors, psycopg2/connection.h, - # psycopg2/cursor.h - "connection already closed", - "cursor already closed", - # not sure where this path is originally from, it may - # be obsolete. It really says "losed", not "closed". - "losed the connection unexpectedly", - # these can occur in newer SSL - "connection has been closed unexpectedly", - "SSL error: decryption failed or bad record mac", - "SSL SYSCALL error: Bad file descriptor", - "SSL SYSCALL error: EOF detected", - "SSL SYSCALL error: Operation timed out", - "SSL SYSCALL error: Bad address", - ]: + for msg in self._is_disconnect_messages: idx = str_e.find(msg) if idx >= 0 and '"' not in str_e[:idx]: return True return False + @util.memoized_property + def _is_disconnect_messages(self): + return ( + # these error messages from libpq: interfaces/libpq/fe-misc.c + # and interfaces/libpq/fe-secure.c. + "terminating connection", + "closed the connection", + "connection not open", + "could not receive data from server", + "could not send data to server", + # psycopg2 client errors, psycopg2/connection.h, + # psycopg2/cursor.h + "connection already closed", + "cursor already closed", + # not sure where this path is originally from, it may + # be obsolete. It really says "losed", not "closed". + "losed the connection unexpectedly", + # these can occur in newer SSL + "connection has been closed unexpectedly", + "SSL error: decryption failed or bad record mac", + "SSL SYSCALL error: Bad file descriptor", + "SSL SYSCALL error: EOF detected", + "SSL SYSCALL error: Operation timed out", + "SSL SYSCALL error: Bad address", + # This can occur in OpenSSL 1 when an unexpected EOF occurs. + # https://www.openssl.org/docs/man1.1.1/man3/SSL_get_error.html#BUGS + # It may also occur in newer OpenSSL for a non-recoverable I/O + # error as a result of a system call that does not set 'errno' + # in libc. + "SSL SYSCALL error: Success", + ) + dialect = PGDialect_psycopg2 diff --git a/test/dialect/postgresql/test_dialect.py b/test/dialect/postgresql/test_dialect.py index eae1b55d6e..3f55c085fb 100644 --- a/test/dialect/postgresql/test_dialect.py +++ b/test/dialect/postgresql/test_dialect.py @@ -365,6 +365,7 @@ $$ LANGUAGE plpgsql;""" "SSL SYSCALL error: EOF detected", "SSL SYSCALL error: Operation timed out", "SSL SYSCALL error: Bad address", + "SSL SYSCALL error: Success", ]: eq_(dialect.is_disconnect(Error(error), None, None), True)