diff --git a/django/db/backends/postgresql/client.py b/django/db/backends/postgresql/client.py index 005f43ddb8..466c2986d2 100644 --- a/django/db/backends/postgresql/client.py +++ b/django/db/backends/postgresql/client.py @@ -1,4 +1,5 @@ import os +import signal import subprocess from django.core.files.temp import NamedTemporaryFile @@ -34,6 +35,7 @@ class DatabaseClient(BaseDatabaseClient): args += [dbname] temp_pgpass = None + sigint_handler = signal.getsignal(signal.SIGINT) try: if passwd: # Create temporary .pgpass file. @@ -54,8 +56,12 @@ class DatabaseClient(BaseDatabaseClient): # If the current locale can't encode the data, we let # the user input the password manually. pass + # Allow SIGINT to pass to psql to abort queries. + signal.signal(signal.SIGINT, signal.SIG_IGN) subprocess.check_call(args) finally: + # Restore the orignal SIGINT handler. + signal.signal(signal.SIGINT, sigint_handler) if temp_pgpass: temp_pgpass.close() if 'PGPASSFILE' in os.environ: # unit tests need cleanup diff --git a/tests/dbshell/test_postgresql_psycopg2.py b/tests/dbshell/test_postgresql_psycopg2.py index 26090fb7f1..a229e13a47 100644 --- a/tests/dbshell/test_postgresql_psycopg2.py +++ b/tests/dbshell/test_postgresql_psycopg2.py @@ -1,4 +1,5 @@ import os +import signal from unittest import mock from django.db.backends.postgresql.client import DatabaseClient @@ -99,3 +100,17 @@ class PostgreSqlDbshellCommandTestCase(SimpleTestCase): pgpass_string, ) ) + + def test_sigint_handler(self): + """SIGINT is ignored in Python and passed to psql to abort quries.""" + def _mock_subprocess_call(*args): + handler = signal.getsignal(signal.SIGINT) + self.assertEqual(handler, signal.SIG_IGN) + + sigint_handler = signal.getsignal(signal.SIGINT) + # The default handler isn't SIG_IGN. + self.assertNotEqual(sigint_handler, signal.SIG_IGN) + with mock.patch('subprocess.check_call', new=_mock_subprocess_call): + DatabaseClient.runshell_db({}) + # dbshell restores the orignal handler. + self.assertEqual(sigint_handler, signal.getsignal(signal.SIGINT))