Fixed #27954 -- Allowed keyboard interrupt to abort queries in PostgreSQL dbshell.
Thanks Tim Martin for review.
This commit is contained in:
parent
7bbb5161ea
commit
66150f7cf6
|
@ -1,4 +1,5 @@
|
||||||
import os
|
import os
|
||||||
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from django.core.files.temp import NamedTemporaryFile
|
from django.core.files.temp import NamedTemporaryFile
|
||||||
|
@ -34,6 +35,7 @@ class DatabaseClient(BaseDatabaseClient):
|
||||||
args += [dbname]
|
args += [dbname]
|
||||||
|
|
||||||
temp_pgpass = None
|
temp_pgpass = None
|
||||||
|
sigint_handler = signal.getsignal(signal.SIGINT)
|
||||||
try:
|
try:
|
||||||
if passwd:
|
if passwd:
|
||||||
# Create temporary .pgpass file.
|
# Create temporary .pgpass file.
|
||||||
|
@ -54,8 +56,12 @@ class DatabaseClient(BaseDatabaseClient):
|
||||||
# If the current locale can't encode the data, we let
|
# If the current locale can't encode the data, we let
|
||||||
# the user input the password manually.
|
# the user input the password manually.
|
||||||
pass
|
pass
|
||||||
|
# Allow SIGINT to pass to psql to abort queries.
|
||||||
|
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||||
subprocess.check_call(args)
|
subprocess.check_call(args)
|
||||||
finally:
|
finally:
|
||||||
|
# Restore the orignal SIGINT handler.
|
||||||
|
signal.signal(signal.SIGINT, sigint_handler)
|
||||||
if temp_pgpass:
|
if temp_pgpass:
|
||||||
temp_pgpass.close()
|
temp_pgpass.close()
|
||||||
if 'PGPASSFILE' in os.environ: # unit tests need cleanup
|
if 'PGPASSFILE' in os.environ: # unit tests need cleanup
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import os
|
import os
|
||||||
|
import signal
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from django.db.backends.postgresql.client import DatabaseClient
|
from django.db.backends.postgresql.client import DatabaseClient
|
||||||
|
@ -99,3 +100,17 @@ class PostgreSqlDbshellCommandTestCase(SimpleTestCase):
|
||||||
pgpass_string,
|
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))
|
||||||
|
|
Loading…
Reference in New Issue