D-Bus testing: further fixes for running under valgrind

The timeout of 5 seconds before hard killing the daemon was
too low when running it under valgrind. valgrind's leak checking
may take longer than that. Increased to one minute.

The timeout also sometimes was too low without valgrind. Increased
to 10 seconds.

Killing valgrindcheck.sh + syncevo-dbus-server is now more reliable
thanks to creating and killing a separate process group. Previously
a fatal SIGKILL was only delivered to valgrindcheck.sh and syncevo-dbus-server
kept running, breaking the following tests because the daemon
couldn't register itself with D-Bus.

Also ensure that the process group always gets a SIGKILL, even if the
main process we were waiting for has quit. Nightly testing sometimes
got stuck because a forked (?) process was still running. This might
point to a problem with process handling, but as that is going to change
anyway (fork+exec), don't bother now.
This commit is contained in:
Patrick Ohly 2011-12-06 16:51:08 +00:00
parent cd7cc5e7bc
commit d37fd5f6a3
1 changed files with 20 additions and 25 deletions

View File

@ -284,37 +284,24 @@ def TryKill(pid, signal):
def ShutdownSubprocess(popen, timeout):
start = time.time()
if popen.poll() == None:
# kill process and process group, in case that process has
# forked children (valgrindcheck.sh + syncevo-dbus-server
# case or syncevo-dbus-server + local sync)
TryKill(popen.pid, signal.SIGTERM)
TryKill(-popen.pid, signal.SIGTERM)
while popen.poll() == None and start + timeout >= time.time():
time.sleep(0.01)
if popen.poll() == None:
TryKill(popen.pid, signal.SIGKILL)
TryKill(-popen.pid, signal.SIGKILL)
while popen.poll() == None and start + timeout + 1 >= time.time():
time.sleep(0.01)
return False
return True
def TryKill(pid, signal):
try:
os.kill(pid, signal)
except OSError, ex:
# might have quit in the meantime, deal with the race
# condition
if ex.errno != 3:
raise ex
def ShutdownSubprocess(popen, timeout):
start = time.time()
if popen.poll() == None:
TryKill(popen.pid, signal.SIGTERM)
while popen.poll() == None and start + timeout >= time.time():
time.sleep(0.01)
if popen.poll() == None:
TryKill(popen.pid, signal.SIGKILL)
while popen.poll() == None and start + timeout + 1 >= time.time():
time.sleep(0.01)
return False
return True
else:
# there shouldn't be any processes in the process group left now
# because the parent process has quit normally, but make sure anyway
TryKill(-popen.pid, signal.SIGKILL)
return True
class DBusUtil(Timeout):
"""Contains the common run() method for all D-Bus test suites
@ -423,6 +410,7 @@ class DBusUtil(Timeout):
logfile.flush()
size = os.path.getsize(syncevolog)
DBusUtil.pserver = subprocess.Popen(args,
preexec_fn=lambda: os.setpgid(0, 0),
env=env,
stdout=logfile,
stderr=subprocess.STDOUT)
@ -470,8 +458,15 @@ class DBusUtil(Timeout):
# allow debugger to run as long as it is needed
DBusUtil.pserver.communicate()
else:
# force shutdown in 5 seconds
if not ShutdownSubprocess(DBusUtil.pserver, 5):
# Force shutdown after a certain delay: how much time we grant
# the process depends on how much work it still needs to do
# after being asked to quit. valgrind leak checking can take
# a while.
if usingValgrind():
delay = 60
else:
delay = 20
if not ShutdownSubprocess(DBusUtil.pserver, delay):
print " syncevo-dbus-server had to be killed with SIGKILL"
result.errors.append((self,
"syncevo-dbus-server had to be killed with SIGKILL"))