From 70cc67c3e6a123cf8210c041e5d23cbc30594ced Mon Sep 17 00:00:00 2001 From: Zeke Brechtel <5767468+zkl2@users.noreply.github.com> Date: Sat, 25 Sep 2021 14:43:28 -0400 Subject: [PATCH] Handle SSL SYSCALL error: Bad Address in postgresql/pyscopg2 Added a "disconnect" condition for the "SSL SYSCALL error: Bad address" error message as reported by psycopg2. Pull request courtesy Zeke Brechtel. Fixes: #5387 Closes: #7087 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/7087 Pull-request-sha: 66af76a107a22d9119edc8edcacc1e4ef66dc50d Change-Id: Ia4afc9683b8175a8ca282e07e0f83c65657544ab --- doc/build/changelog/unreleased_14/5387.rst | 6 ++++ .../dialects/postgresql/psycopg2.py | 3 +- test/dialect/postgresql/test_dialect.py | 36 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 doc/build/changelog/unreleased_14/5387.rst diff --git a/doc/build/changelog/unreleased_14/5387.rst b/doc/build/changelog/unreleased_14/5387.rst new file mode 100644 index 0000000000..a08c169afe --- /dev/null +++ b/doc/build/changelog/unreleased_14/5387.rst @@ -0,0 +1,6 @@ +.. change:: + :tags: bug, postgresql + :tickets: 5387 + + Added a "disconnect" condition for the "SSL SYSCALL error: Bad address" + error message as reported by psycopg2. Pull request courtesy Zeke Brechtel. diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg2.py b/lib/sqlalchemy/dialects/postgresql/psycopg2.py index a5a56cb6b0..a71bdf7606 100644 --- a/lib/sqlalchemy/dialects/postgresql/psycopg2.py +++ b/lib/sqlalchemy/dialects/postgresql/psycopg2.py @@ -1046,10 +1046,11 @@ class PGDialect_psycopg2(PGDialect): "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 error: decryption failed or bad record mac", "SSL SYSCALL error: Operation timed out", + "SSL SYSCALL error: Bad address", ]: idx = str_e.find(msg) if idx >= 0 and '"' not in str_e[:idx]: diff --git a/test/dialect/postgresql/test_dialect.py b/test/dialect/postgresql/test_dialect.py index 155019aaea..c0eb4410cf 100644 --- a/test/dialect/postgresql/test_dialect.py +++ b/test/dialect/postgresql/test_dialect.py @@ -255,6 +255,42 @@ $$ LANGUAGE plpgsql;""" eq_(cargs, []) eq_(cparams["host"], "hostA:portA,hostB,hostC") + def test_psycopg2_disconnect(self): + class Error(Exception): + pass + + dbapi = mock.Mock() + dbapi.Error = Error + + dialect = psycopg2_dialect.dialect(dbapi=dbapi) + + for error 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/conenction.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", + ]: + eq_(dialect.is_disconnect(Error(error), None, None), True) + + eq_(dialect.is_disconnect("not an error", None, None), False) + class PGCodeTest(fixtures.TestBase): __only_on__ = "postgresql" -- 2.47.3