Fixed #33715 -- Allowed keyboard interrupt to abort queries in MySQL dbshell.
This commit is contained in:
parent
e89f957135
commit
1a78ef2b85
|
@ -1,3 +1,5 @@
|
|||
import signal
|
||||
|
||||
from django.db.backends.base.client import BaseDatabaseClient
|
||||
|
||||
|
||||
|
@ -58,3 +60,13 @@ class DatabaseClient(BaseDatabaseClient):
|
|||
args += [database]
|
||||
args.extend(parameters)
|
||||
return args, env
|
||||
|
||||
def runshell(self, parameters):
|
||||
sigint_handler = signal.getsignal(signal.SIGINT)
|
||||
try:
|
||||
# Allow SIGINT to pass to mysql to abort queries.
|
||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
super().runshell(parameters)
|
||||
finally:
|
||||
# Restore the original SIGINT handler.
|
||||
signal.signal(signal.SIGINT, sigint_handler)
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import os
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from unittest import mock, skipUnless
|
||||
|
||||
from django.db import connection
|
||||
from django.db.backends.mysql.client import DatabaseClient
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
|
@ -218,3 +221,19 @@ class MySqlDbshellCommandTestCase(SimpleTestCase):
|
|||
with self.assertRaises(subprocess.CalledProcessError) as ctx:
|
||||
subprocess.run(args, check=True, env=env)
|
||||
self.assertNotIn("somepassword", str(ctx.exception))
|
||||
|
||||
@skipUnless(connection.vendor == "mysql", "Requires a MySQL connection")
|
||||
def test_sigint_handler(self):
|
||||
"""SIGINT is ignored in Python and passed to mysql to abort queries."""
|
||||
|
||||
def _mock_subprocess_run(*args, **kwargs):
|
||||
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.run", new=_mock_subprocess_run):
|
||||
connection.client.runshell([])
|
||||
# dbshell restores the original handler.
|
||||
self.assertEqual(sigint_handler, signal.getsignal(signal.SIGINT))
|
||||
|
|
Loading…
Reference in New Issue