2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 10:10:06 +00:00

Use context managers as suggested by PyLint 2.8.2

PyLint 2.8.2 reports the following suggestions for two Python scripts
used in the system test suite:

    ************* Module tests_rndc_deadlock
    bin/tests/system/addzone/tests_rndc_deadlock.py:71:4: R1732: Consider using 'with' for resource-allocating operations (consider-using-with)
    ************* Module tests-shutdown
    bin/tests/system/shutdown/tests-shutdown.py:68:4: R1732: Consider using 'with' for resource-allocating operations (consider-using-with)
    bin/tests/system/shutdown/tests-shutdown.py:154:8: R1732: Consider using 'with' for resource-allocating operations (consider-using-with)

Implement the above suggestions by using
concurrent.futures.ThreadPoolExecutor() and subprocess.Popen() as
context managers.
This commit is contained in:
Michał Kępień 2021-05-18 10:53:17 +02:00
parent 71284cb496
commit a8163551ed
2 changed files with 95 additions and 103 deletions

View File

@ -68,23 +68,22 @@ def test_rndc_deadlock():
test_state = {'finished': False}
# Create 4 worker threads running "rndc" commands in a loop.
executor = concurrent.futures.ThreadPoolExecutor()
for i in range(1, 5):
domain = 'example%d' % i
executor.submit(rndc_loop, test_state, domain)
with concurrent.futures.ThreadPoolExecutor() as executor:
for i in range(1, 5):
domain = 'example%d' % i
executor.submit(rndc_loop, test_state, domain)
# Run "rndc status" in 1-second intervals for a maximum of 10 seconds. If
# any "rndc status" command fails, the loop will be interrupted.
server_is_responsive = True
attempts = 10
while server_is_responsive and attempts > 0:
server_is_responsive = check_if_server_is_responsive()
attempts -= 1
time.sleep(1)
# Run "rndc status" in 1-second intervals for a maximum of 10 seconds.
# If any "rndc status" command fails, the loop will be interrupted.
server_is_responsive = True
attempts = 10
while server_is_responsive and attempts > 0:
server_is_responsive = check_if_server_is_responsive()
attempts -= 1
time.sleep(1)
# Signal worker threads that the test is finished.
test_state['finished'] = True
executor.shutdown()
# Signal worker threads that the test is finished.
test_state['finished'] = True
# Check whether all "rndc status" commands succeeded.
assert server_is_responsive

View File

@ -65,65 +65,63 @@ def do_work(named_proc, resolver, rndc_cmd, kill_method, n_workers, n_queries):
# We're going to execute queries in parallel by means of a thread pool.
# dnspython functions block, so we need to circunvent that.
executor = ThreadPoolExecutor(n_workers + 1)
with ThreadPoolExecutor(n_workers + 1) as executor:
# Helper dict, where keys=Future objects and values are tags used
# to process results later.
futures = {}
# Helper dict, where keys=Future objects and values are tags used
# to process results later.
futures = {}
# 50% of work will be A queries.
# 1 work will be rndc stop.
# Remaining work will be rndc status (so we test parallel control
# connections that were crashing named).
shutdown = True
for i in range(n_queries):
if i < (n_queries // 2):
# Half work will be standard A queries.
# Among those we split 50% queries relname='www',
# 50% queries relname=random characters
if random.randrange(2) == 1:
tag = "good"
relname = "www"
else:
tag = "bad"
length = random.randint(4, 10)
relname = "".join(letters[
random.randrange(len(letters))] for i in range(length))
qname = relname + ".test"
futures[executor.submit(resolver.query, qname, 'A')] = tag
elif shutdown: # We attempt to stop named in the middle
shutdown = False
if kill_method == "rndc":
futures[executor.submit(launch_rndc, ['stop'])] = 'stop'
else:
futures[executor.submit(named_proc.terminate)] = 'kill'
# 50% of work will be A queries.
# 1 work will be rndc stop.
# Remaining work will be rndc status (so we test parallel control
# connections that were crashing named).
shutdown = True
for i in range(n_queries):
if i < (n_queries // 2):
# Half work will be standard A queries.
# Among those we split 50% queries relname='www',
# 50% queries relname=random characters
if random.randrange(2) == 1:
tag = "good"
relname = "www"
else:
tag = "bad"
length = random.randint(4, 10)
relname = "".join(letters[
random.randrange(len(letters))] for i in range(length))
# We attempt to send couple rndc commands while named is
# being shutdown
futures[executor.submit(launch_rndc, ['status'])] = 'status'
qname = relname + ".test"
futures[executor.submit(resolver.query, qname, 'A')] = tag
elif shutdown: # We attempt to stop named in the middle
shutdown = False
if kill_method == "rndc":
futures[executor.submit(launch_rndc, ['stop'])] = 'stop'
else:
futures[executor.submit(named_proc.terminate)] = 'kill'
ret_code = -1
for future in as_completed(futures):
try:
result = future.result()
# If tag is "stop", result is an instance of
# subprocess.CompletedProcess, then we check returncode
# attribute to know if rncd stop command finished successfully.
#
# if tag is "kill" then the main function will check if
# named process exited gracefully after SIGTERM signal.
if futures[future] == "stop":
ret_code = result
else:
# We attempt to send couple rndc commands while named is
# being shutdown
futures[executor.submit(launch_rndc, ['status'])] = 'status'
except (dns.resolver.NXDOMAIN, dns.exception.Timeout):
pass
ret_code = -1
for future in as_completed(futures):
try:
result = future.result()
# If tag is "stop", result is an instance of
# subprocess.CompletedProcess, then we check returncode
# attribute to know if rncd stop command finished successfully.
#
# if tag is "kill" then the main function will check if
# named process exited gracefully after SIGTERM signal.
if futures[future] == "stop":
ret_code = result
except (dns.resolver.NXDOMAIN, dns.exception.Timeout):
pass
if kill_method == "rndc":
assert ret_code == 0
executor.shutdown()
if kill_method == "rndc":
assert ret_code == 0
@pytest.mark.dnspython
@ -149,14 +147,6 @@ def test_named_shutdown(named_port, control_port):
rndc_cmd = [rndc, "-c", rndc_cfg, "-p", str(control_port),
"-s", "10.53.0.3"]
# Helper function, launch named without blocking.
def launch_named():
proc = subprocess.Popen([named, "-c", cfg_file, "-f"], cwd=cfg_dir)
# Ensure named is running
assert proc.poll() is None
return proc
# We create a resolver instance that will be used to send queries.
resolver = dns.resolver.Resolver()
resolver.nameservers = ['10.53.0.3']
@ -167,38 +157,41 @@ def test_named_shutdown(named_port, control_port):
# Method 2: killing with SIGTERM
# In both methods named should exit gracefully.
for kill_method in ("rndc", "sigterm"):
named_proc = launch_named()
# wait for named to finish loading
for _ in range(10):
try:
resolver.query('version.bind', 'TXT', 'CH')
break
except (dns.resolver.NoNameservers, dns.exception.Timeout):
time.sleep(1)
named_cmdline = [named, "-c", cfg_file, "-f"]
with subprocess.Popen(named_cmdline, cwd=cfg_dir) as named_proc:
# Ensure named is running
assert named_proc.poll() is None
# wait for named to finish loading
for _ in range(10):
try:
resolver.query('version.bind', 'TXT', 'CH')
break
except (dns.resolver.NoNameservers, dns.exception.Timeout):
time.sleep(1)
do_work(named_proc, resolver, rndc_cmd,
kill_method, n_workers=12, n_queries=16)
do_work(named_proc, resolver, rndc_cmd,
kill_method, n_workers=12, n_queries=16)
# Wait named to exit for a maximum of MAX_TIMEOUT seconds.
MAX_TIMEOUT = 10
is_dead = False
for _ in range(MAX_TIMEOUT):
if named_proc.poll() is not None:
is_dead = True
break
time.sleep(1)
if not is_dead:
named_proc.send_signal(signal.SIGABRT)
# Wait named to exit for a maximum of MAX_TIMEOUT seconds.
MAX_TIMEOUT = 10
is_dead = False
for _ in range(MAX_TIMEOUT):
if named_proc.poll() is not None:
is_dead = True
break
time.sleep(1)
if not is_dead:
named_proc.kill()
assert is_dead
# Ensures that named exited gracefully.
# If it crashed (abort()) exitcode will be non zero.
assert named_proc.returncode == 0
if not is_dead:
named_proc.send_signal(signal.SIGABRT)
for _ in range(MAX_TIMEOUT):
if named_proc.poll() is not None:
is_dead = True
break
time.sleep(1)
if not is_dead:
named_proc.kill()
assert is_dead
# Ensures that named exited gracefully.
# If it crashed (abort()) exitcode will be non zero.
assert named_proc.returncode == 0