am d9076f21: Merge "adb: Kill subprocess when the client exits."
* commit 'd9076f2132006505227e5fec91926acb512c3d68': adb: Kill subprocess when the client exits.
This commit is contained in:
commit
2017030b49
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue