Add thread task to check ps command regularly

This commit is contained in:
Poly Takahiro Horikawa
2013-08-21 16:27:10 -07:00
parent 18674c501c
commit 675bfcf889
+42 -56
View File
@@ -20,12 +20,16 @@ limitations under the License.
# Written by Jeff Sharkey, http://jsharkey.org/ # Written by Jeff Sharkey, http://jsharkey.org/
# Piping detection and popen() added by other Android team members # Piping detection and popen() added by other Android team members
# Package name restriction by Jake Wharton, http://jakewharton.com # Package name restriction by Jake Wharton, http://jakewharton.com
# PID detection with ps command by Takahiro "Poly" Horikawa <horikawa.takahiro@gmail.com>
import argparse import argparse
import os import os
import sys import sys
import re import re
import subprocess import subprocess
import time
import thread
import threading
from subprocess import PIPE from subprocess import PIPE
@@ -130,13 +134,11 @@ TAGTYPES = {
'F': colorize(' F ', fg=BLACK, bg=RED), 'F': colorize(' F ', fg=BLACK, bg=RED),
} }
PID_START = re.compile(r'^Start proc ([a-zA-Z0-9._:]+) for ([a-z]+ [^:]+): pid=(\d+) uid=(\d+) gids=(.*)$')
PID_KILL = re.compile(r'^Killing (\d+):([a-zA-Z0-9._]+)/[^:]+: (.*)$')
PID_LEAVE = re.compile(r'^No longer want ([a-zA-Z0-9._]+) \(pid (\d+)\): .*$')
PID_DEATH = re.compile(r'^Process ([a-zA-Z0-9._]+) \(pid (\d+)\) has died.?$')
LOG_LINE = re.compile(r'^([A-Z])/(.+?)\( *(\d+)\): (.*?)$') LOG_LINE = re.compile(r'^([A-Z])/(.+?)\( *(\d+)\): (.*?)$')
BUG_LINE = re.compile(r'.*nativeGetEnabledTags.*') BUG_LINE = re.compile(r'.*nativeGetEnabledTags.*')
PS_POLLING_INTERVAL = 1
adb_options = [] adb_options = []
if args.device_serial: if args.device_serial:
adb_options.extend(['-s', args.device_serial]) adb_options.extend(['-s', args.device_serial])
@@ -160,27 +162,8 @@ def match_packages(token):
index = token.find(':') index = token.find(':')
return (token in args.package) if index == -1 else (token[:index] in args.package) return (token in args.package) if index == -1 else (token[:index] in args.package)
def parse_death(tag, message): def parse_ps(ps_out):
if tag != 'ActivityManager': new_pids = set()
return None
kill = PID_KILL.match(message)
if kill:
pid = kill.group(1)
if match_packages(kill.group(2)) and pid in pids:
return pid
leave = PID_LEAVE.match(message)
if leave:
pid = leave.group(2)
if match_packages(leave.group(1)) and pid in pids:
return pid
death = PID_DEATH.match(message)
if death:
pid = death.group(2)
if match_packages(death.group(1)) and pid in pids:
return pid
return None
def parse_ps(ps_out, set):
processes = ps_out.split('\n') processes = ps_out.split('\n')
fields = processes[0].split(); fields = processes[0].split();
nfields = len(fields) nfields = len(fields)
@@ -192,19 +175,48 @@ def parse_ps(ps_out, set):
name = fields[8] name = fields[8]
pid = fields[1] pid = fields[1]
if match_packages(name): if match_packages(name):
new_pids.add(pid)
return new_pids
def print_diff(pids, new_pids):
for new_pid in new_pids:
if new_pid not in pids:
linebuf = '\n' linebuf = '\n'
linebuf += colorize(' ' * (header_size - 1), bg=WHITE) linebuf += colorize(' ' * (header_size - 1), bg=WHITE)
linebuf += ' Process %s is found' % (pid) linebuf += ' Process %s is found' % (new_pid)
linebuf += '\n' linebuf += '\n'
print(linebuf) print(linebuf)
pids.add(pid)
def update_with_ps(): deleted_pids = pids.difference(new_pids)
for deleted_pid in deleted_pids:
linebuf = '\n'
linebuf += colorize(' ' * (header_size - 1), bg=WHITE)
linebuf += ' Process %s is deleted' % (deleted_pid)
linebuf += '\n'
print(linebuf)
pass
def get_pids():
ps = subprocess.Popen(ps_command, stdout=PIPE) ps = subprocess.Popen(ps_command, stdout=PIPE)
ps_out, ps_err = ps.communicate() ps_out, ps_err = ps.communicate()
parse_ps(ps_out, set) return parse_ps(ps_out)
def update_pids():
with lock:
new_pids = get_pids()
global pids
print_diff(pids, new_pids)
pids = new_pids
last_ps_check = time.time()
def update_pids_background():
while True:
update_pids()
time.sleep(PS_POLLING_INTERVAL)
lock = threading.RLock()
thread.start_new_thread(update_pids_background, ())
update_with_ps()
while adb.poll() is None: while adb.poll() is None:
try: try:
line = adb.stdout.readline().decode('utf-8', 'replace').strip() line = adb.stdout.readline().decode('utf-8', 'replace').strip()
@@ -223,32 +235,6 @@ while adb.poll() is None:
level, tag, owner, message = log_line.groups() level, tag, owner, message = log_line.groups()
start = PID_START.match(message)
if start is not None:
line_package, target, line_pid, line_uid, line_gids = start.groups()
if match_packages(line_package):
pids.add(line_pid)
linebuf = '\n'
linebuf += colorize(' ' * (header_size - 1), bg=WHITE)
linebuf += indent_wrap(' Process created for %s\n' % target)
linebuf += colorize(' ' * (header_size - 1), bg=WHITE)
linebuf += ' PID: %s UID: %s GIDs: %s' % (line_pid, line_uid, line_gids)
linebuf += '\n'
print(linebuf)
last_tag = None # Ensure next log gets a tag printed
dead_pid = parse_death(tag, message)
if dead_pid:
pids.remove(dead_pid)
linebuf = '\n'
linebuf += colorize(' ' * (header_size - 1), bg=RED)
linebuf += ' Process %s ended' % dead_pid
linebuf += '\n'
print(linebuf)
last_tag = None # Ensure next log gets a tag printed
if owner not in pids: if owner not in pids:
continue continue
if LOG_LEVELS_MAP[level] < min_level: if LOG_LEVELS_MAP[level] < min_level: