Merge "Stack: Add subprocess caching"

am: a1b14a7357

Change-Id: Ia61629b625c5cbb45b040d6f41755417751b6d7a
This commit is contained in:
Andreas Gampe
2017-05-18 20:51:50 +00:00
committed by android-build-merger

View File

@@ -19,10 +19,12 @@
The information can include symbol names, offsets, and source locations.
"""
import atexit
import glob
import os
import platform
import re
import signal
import subprocess
import unittest
@@ -56,6 +58,78 @@ _SYMBOL_INFORMATION_ADDR2LINE_CACHE = {}
_SYMBOL_INFORMATION_OBJDUMP_CACHE = {}
_SYMBOL_DEMANGLING_CACHE = {}
# Caches for pipes to subprocesses.
class ProcessCache:
_cmd2pipe = {}
_lru = []
# Max number of open pipes.
_PIPE_MAX_OPEN = 10
def GetProcess(self, cmd):
cmd_tuple = tuple(cmd) # Need to use a tuple as lists can't be dict keys.
# Pipe already available?
if cmd_tuple in self._cmd2pipe:
pipe = self._cmd2pipe[cmd_tuple]
# Update LRU.
self._lru = [(cmd_tuple, pipe)] + [i for i in self._lru if i[0] != cmd_tuple]
return pipe
# Not cached, yet. Open a new one.
# Check if too many are open, close the old ones.
while len(self._lru) >= self._PIPE_MAX_OPEN:
open_cmd, open_pipe = self._lru.pop()
del self._cmd2pipe[open_cmd]
self.TerminateProcess(open_pipe)
# Create and put into cache.
pipe = self.SpawnProcess(cmd)
self._cmd2pipe[cmd_tuple] = pipe
self._lru = [(cmd_tuple, pipe)] + self._lru
return pipe
def SpawnProcess(self, cmd):
return subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
def TerminateProcess(self, pipe):
pipe.stdin.close()
pipe.stdout.close()
pipe.terminate()
pipe.wait()
def KillAllProcesses(self):
for _, open_pipe in self._lru:
self.TerminateProcess(open_pipe)
_cmd2pipe = {}
_lru = []
_PIPE_ADDR2LINE_CACHE = ProcessCache()
_PIPE_CPPFILT_CACHE = ProcessCache()
# Process cache cleanup on shutdown.
def CloseAllPipes():
_PIPE_ADDR2LINE_CACHE.KillAllProcesses()
_PIPE_CPPFILT_CACHE.KillAllProcesses()
atexit.register(CloseAllPipes)
def PipeTermHandler(signum, frame):
CloseAllPipes()
os._exit(0)
for sig in (signal.SIGABRT, signal.SIGINT, signal.SIGTERM):
signal.signal(sig, PipeTermHandler)
def ToolPath(tool, toolchain=None):
"""Return a fully-qualified path to the specified tool"""
@@ -222,7 +296,7 @@ def CallAddr2LineForSet(lib, unique_addrs):
cmd = [ToolPath("addr2line"), "--functions", "--inlines",
"--demangle", "--exe=" + symbols]
child = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
child = _PIPE_ADDR2LINE_CACHE.GetProcess(cmd)
for addr in addrs:
child.stdin.write("0x%s\n" % addr)
@@ -247,8 +321,6 @@ def CallAddr2LineForSet(lib, unique_addrs):
first = False
result[addr] = records
addr_cache[addr] = records
child.stdin.close()
child.stdout.close()
return result
@@ -376,12 +448,12 @@ def CallCppFilt(mangled_symbol):
return _SYMBOL_DEMANGLING_CACHE[mangled_symbol]
cmd = [ToolPath("c++filt")]
process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
process = _PIPE_CPPFILT_CACHE.GetProcess(cmd)
process.stdin.write(mangled_symbol)
process.stdin.write("\n")
process.stdin.close()
process.stdin.flush()
demangled_symbol = process.stdout.readline().strip()
process.stdout.close()
_SYMBOL_DEMANGLING_CACHE[mangled_symbol] = demangled_symbol