mirror of
				https://github.com/ARM-software/devlib.git
				synced 2025-11-04 16:01:20 +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:
		
				
					committed by
					
						
						Marc Bonnici
					
				
			
			
				
	
			
			
			
						parent
						
							31f7c1e8f9
						
					
				
				
					commit
					6cabad14d0
				
			@@ -105,12 +105,20 @@ class BackgroundCommand(ABC):
 | 
			
		||||
        """
 | 
			
		||||
        self.send_signal(signal.SIGKILL)
 | 
			
		||||
 | 
			
		||||
    @abstractmethod
 | 
			
		||||
    def cancel(self, kill_timeout=_KILL_TIMEOUT):
 | 
			
		||||
        """
 | 
			
		||||
        Try to gracefully terminate the process by sending ``SIGTERM``, then
 | 
			
		||||
        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
 | 
			
		||||
    def wait(self):
 | 
			
		||||
@@ -209,7 +217,7 @@ class PopenBackgroundCommand(BackgroundCommand):
 | 
			
		||||
    def poll(self):
 | 
			
		||||
        return self.popen.poll()
 | 
			
		||||
 | 
			
		||||
    def cancel(self, kill_timeout=_KILL_TIMEOUT):
 | 
			
		||||
    def _cancel(self, kill_timeout):
 | 
			
		||||
        popen = self.popen
 | 
			
		||||
        os.killpg(os.getpgid(popen.pid), signal.SIGTERM)
 | 
			
		||||
        try:
 | 
			
		||||
@@ -266,7 +274,7 @@ class ParamikoBackgroundCommand(BackgroundCommand):
 | 
			
		||||
        else:
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
    def cancel(self, kill_timeout=_KILL_TIMEOUT):
 | 
			
		||||
    def _cancel(self, kill_timeout):
 | 
			
		||||
        self.send_signal(signal.SIGTERM)
 | 
			
		||||
        # Check if the command terminated quickly
 | 
			
		||||
        time.sleep(10e-3)
 | 
			
		||||
@@ -340,7 +348,7 @@ class AdbBackgroundCommand(BackgroundCommand):
 | 
			
		||||
    def poll(self):
 | 
			
		||||
        return self.adb_popen.poll()
 | 
			
		||||
 | 
			
		||||
    def cancel(self, kill_timeout=_KILL_TIMEOUT):
 | 
			
		||||
    def _cancel(self, kill_timeout):
 | 
			
		||||
        self.send_signal(signal.SIGTERM)
 | 
			
		||||
        try:
 | 
			
		||||
            self.adb_popen.wait(timeout=_KILL_TIMEOUT)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user