Bug 1124695 - [mozrunner] and/or [mozprocess] should send SIGTERM before sending SIGKILL by default; r=ahal

This commit is contained in:
Julien Pagès 2015-02-27 15:11:14 -05:00
parent 7121f5da60
commit 4e1bef3f06
3 changed files with 66 additions and 9 deletions

View File

@ -65,6 +65,7 @@ class ProcessHandlerMixin(object):
MAX_IOCOMPLETION_PORT_NOTIFICATION_DELAY = 180
MAX_PROCESS_KILL_DELAY = 30
TIMEOUT_BEFORE_SIGKILL = 1.0
def __init__(self,
args,
@ -144,16 +145,32 @@ class ProcessHandlerMixin(object):
if err is not None:
raise OSError(err)
else:
sig = sig or signal.SIGKILL
if not self._ignore_children:
try:
os.killpg(self.pid, sig)
except BaseException, e:
if getattr(e, "errno", None) != 3:
# Error 3 is "no such process", which is ok
print >> sys.stdout, "Could not kill process, could not find pid: %s, assuming it's already dead" % self.pid
def send_sig(sig):
if not self._ignore_children:
try:
os.killpg(self.pid, sig)
except BaseException, e:
if getattr(e, "errno", None) != 3:
# Error 3 is "no such process", which is ok
print >> sys.stdout, "Could not kill process, could not find pid: %s, assuming it's already dead" % self.pid
else:
os.kill(self.pid, sig)
if sig is None and isPosix:
# ask the process for termination and wait a bit
send_sig(signal.SIGTERM)
limit = time.time() + self.TIMEOUT_BEFORE_SIGKILL
while time.time() <= limit:
if self.poll() is not None:
# process terminated nicely
break
time.sleep(0.02)
else:
# process did not terminate - send SIGKILL to force
send_sig(signal.SIGKILL)
else:
os.kill(self.pid, sig)
# a signal was explicitly set or not posix
send_sig(sig or signal.SIGKILL)
self.returncode = self.wait()
self._cleanup()

View File

@ -0,0 +1,18 @@
import threading
import time
import sys
import signal
if 'deadlock' in sys.argv:
lock = threading.Lock()
def trap(sig, frame):
lock.acquire()
# get the lock once
lock.acquire()
# and take it again on SIGTERM signal: deadlock.
signal.signal(signal.SIGTERM, trap)
while 1:
time.sleep(1)

View File

@ -4,6 +4,7 @@ import os
import time
import unittest
import proctest
import signal
from mozprocess import processhandler
here = os.path.dirname(os.path.abspath(__file__))
@ -80,5 +81,26 @@ class ProcTestKill(proctest.ProcTest):
p.didTimeout,
expectedfail=('returncode',))
@unittest.skipUnless(processhandler.isPosix, "posix only")
def test_process_kill_with_sigterm(self):
script = os.path.join(here, 'infinite_loop.py')
p = processhandler.ProcessHandler([self.python, script])
p.run()
p.kill()
self.assertEquals(p.proc.returncode, -signal.SIGTERM)
@unittest.skipUnless(processhandler.isPosix, "posix only")
def test_process_kill_with_sigint_if_needed(self):
script = os.path.join(here, 'infinite_loop.py')
p = processhandler.ProcessHandler([self.python, script, 'deadlock'])
p.run()
time.sleep(1)
p.kill()
self.assertEquals(p.proc.returncode, -signal.SIGKILL)
if __name__ == '__main__':
unittest.main()