Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2017030b authored by David Pursell's avatar David Pursell Committed by Android Git Automerger
Browse files

am d9076f21: Merge "adb: Kill subprocess when the client exits."

* commit 'd9076f21':
  adb: Kill subprocess when the client exits.
parents a3ef4fad d9076f21
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -413,6 +413,14 @@ void Subprocess::PassDataStreams() {
            D("closing FD %d", dead_sfd->fd());
            FD_CLR(dead_sfd->fd(), &master_read_set);
            FD_CLR(dead_sfd->fd(), &master_write_set);
            if (dead_sfd == &protocol_sfd_) {
                // Using SIGHUP is a decent general way to indicate that the
                // controlling process is going away. If specific signals are
                // needed (e.g. SIGINT), pass those through the shell protocol
                // and only fall back on this for unexpected closures.
                D("protocol FD died, sending SIGHUP to pid %d", pid_);
                kill(pid_, SIGHUP);
            }
            dead_sfd->Reset();
        }
    }
+29 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import posixpath
import random
import shlex
import shutil
import signal
import subprocess
import tempfile
import unittest
@@ -196,6 +197,34 @@ class ShellTest(DeviceTest):
        self.assertEqual('foo' + self.device.linesep, result[1])
        self.assertEqual('bar' + self.device.linesep, result[2])

    def test_non_interactive_sigint(self):
        """Tests that SIGINT in a non-interactive shell kills the process.

        This requires the shell protocol in order to detect the broken
        pipe; raw data transfer mode will only see the break once the
        subprocess tries to read or write.

        Bug: http://b/23825725
        """
        if self.device.SHELL_PROTOCOL_FEATURE not in self.device.features:
            raise unittest.SkipTest('shell protocol unsupported on this device')

        # Start a long-running process.
        sleep_proc = subprocess.Popen(
                self.device.adb_cmd + shlex.split('shell echo $$; sleep 60'),
                stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT)
        remote_pid = sleep_proc.stdout.readline().strip()
        self.assertIsNone(sleep_proc.returncode, 'subprocess terminated early')
        proc_query = shlex.split('ps {0} | grep {0}'.format(remote_pid))

        # Verify that the process is running, send signal, verify it stopped.
        self.device.shell(proc_query)
        os.kill(sleep_proc.pid, signal.SIGINT)
        sleep_proc.communicate()
        self.assertEqual(1, self.device.shell_nocheck(proc_query)[0],
                         'subprocess failed to terminate')


class ArgumentEscapingTest(DeviceTest):
    def test_shell_escaping(self):