mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 01:59:26 +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:
parent
71284cb496
commit
a8163551ed
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user