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

This commit is contained in:
David Pursell 2015-09-15 18:27:33 +00:00 committed by Gerrit Code Review
commit d9076f2132
2 changed files with 37 additions and 0 deletions

View file

@ -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();
}
}

View file

@ -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):