mirror of
https://github.com/ARM-software/devlib.git
synced 2025-01-31 02:00:45 +00:00
connection: Make ConnectionBase.cancel() more robust
Check with poll() if the command is already finished first, to avoid sending SIGKILL to unrelated processes due to PID recycling. The race window still exists between the call to poll() and _cancel(), but is reduced a great deal.
This commit is contained in:
parent
31f7c1e8f9
commit
6cabad14d0
@ -105,12 +105,20 @@ class BackgroundCommand(ABC):
|
|||||||
"""
|
"""
|
||||||
self.send_signal(signal.SIGKILL)
|
self.send_signal(signal.SIGKILL)
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def cancel(self, kill_timeout=_KILL_TIMEOUT):
|
def cancel(self, kill_timeout=_KILL_TIMEOUT):
|
||||||
"""
|
"""
|
||||||
Try to gracefully terminate the process by sending ``SIGTERM``, then
|
Try to gracefully terminate the process by sending ``SIGTERM``, then
|
||||||
waiting for ``kill_timeout`` to send ``SIGKILL``.
|
waiting for ``kill_timeout`` to send ``SIGKILL``.
|
||||||
"""
|
"""
|
||||||
|
if self.poll() is None:
|
||||||
|
self._cancel(kill_timeout=kill_timeout)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def _cancel(self, kill_timeout):
|
||||||
|
"""
|
||||||
|
Method to override in subclasses to implement :meth:`cancel`.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def wait(self):
|
def wait(self):
|
||||||
@ -209,7 +217,7 @@ class PopenBackgroundCommand(BackgroundCommand):
|
|||||||
def poll(self):
|
def poll(self):
|
||||||
return self.popen.poll()
|
return self.popen.poll()
|
||||||
|
|
||||||
def cancel(self, kill_timeout=_KILL_TIMEOUT):
|
def _cancel(self, kill_timeout):
|
||||||
popen = self.popen
|
popen = self.popen
|
||||||
os.killpg(os.getpgid(popen.pid), signal.SIGTERM)
|
os.killpg(os.getpgid(popen.pid), signal.SIGTERM)
|
||||||
try:
|
try:
|
||||||
@ -266,7 +274,7 @@ class ParamikoBackgroundCommand(BackgroundCommand):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def cancel(self, kill_timeout=_KILL_TIMEOUT):
|
def _cancel(self, kill_timeout):
|
||||||
self.send_signal(signal.SIGTERM)
|
self.send_signal(signal.SIGTERM)
|
||||||
# Check if the command terminated quickly
|
# Check if the command terminated quickly
|
||||||
time.sleep(10e-3)
|
time.sleep(10e-3)
|
||||||
@ -340,7 +348,7 @@ class AdbBackgroundCommand(BackgroundCommand):
|
|||||||
def poll(self):
|
def poll(self):
|
||||||
return self.adb_popen.poll()
|
return self.adb_popen.poll()
|
||||||
|
|
||||||
def cancel(self, kill_timeout=_KILL_TIMEOUT):
|
def _cancel(self, kill_timeout):
|
||||||
self.send_signal(signal.SIGTERM)
|
self.send_signal(signal.SIGTERM)
|
||||||
try:
|
try:
|
||||||
self.adb_popen.wait(timeout=_KILL_TIMEOUT)
|
self.adb_popen.wait(timeout=_KILL_TIMEOUT)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user