You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.7 KiB
122 lines
3.7 KiB
import os
|
|
import re
|
|
import time
|
|
import datetime
|
|
|
|
from raven import Client
|
|
from raven.transport.http import HTTPTransport
|
|
|
|
from selfdrive.version import version, dirty
|
|
from selfdrive.swaglog import cloudlog
|
|
|
|
def get_tombstones():
|
|
DIR_DATA = "/data/tombstones/"
|
|
return [(DIR_DATA + fn, int(os.stat(DIR_DATA + fn).st_ctime) )
|
|
for fn in os.listdir(DIR_DATA) if fn.startswith("tombstone")]
|
|
|
|
def report_tombstone(fn, client):
|
|
mtime = os.path.getmtime(fn)
|
|
with open(fn, "r") as f:
|
|
dat = f.read()
|
|
|
|
# see system/core/debuggerd/tombstone.cpp
|
|
parsed = re.match(r"[* ]*\n"
|
|
r"(?P<header>CM Version:[\s\S]*?ABI:.*\n)"
|
|
r"(?P<thread>pid:.*\n)"
|
|
r"(?P<signal>signal.*\n)?"
|
|
r"(?P<abort>Abort.*\n)?"
|
|
r"(?P<registers>\s+x0[\s\S]*?\n)\n"
|
|
r"(?:backtrace:\n"
|
|
r"(?P<backtrace>[\s\S]*?\n)\n"
|
|
r"stack:\n"
|
|
r"(?P<stack>[\s\S]*?\n)\n"
|
|
r")?", dat)
|
|
|
|
logtail = re.search(r"--------- tail end of.*\n([\s\S]*?\n)---", dat)
|
|
logtail = logtail and logtail.group(1)
|
|
|
|
if parsed:
|
|
parsedict = parsed.groupdict()
|
|
else:
|
|
parsedict = {}
|
|
|
|
thread_line = parsedict.get('thread', '')
|
|
thread_parsed = re.match(r'pid: (?P<pid>\d+), tid: (?P<tid>\d+), name: (?P<name>.*) >>> (?P<cmd>.*) <<<', thread_line)
|
|
if thread_parsed:
|
|
thread_parseddict = thread_parsed.groupdict()
|
|
else:
|
|
thread_parseddict = {}
|
|
pid = thread_parseddict.get('pid', '')
|
|
tid = thread_parseddict.get('tid', '')
|
|
name = thread_parseddict.get('name', 'unknown')
|
|
cmd = thread_parseddict.get('cmd', 'unknown')
|
|
|
|
signal_line = parsedict.get('signal', '')
|
|
signal_parsed = re.match(r'signal (?P<signal>.*?), code (?P<code>.*?), fault addr (?P<fault_addr>.*)\n', signal_line)
|
|
if signal_parsed:
|
|
signal_parseddict = signal_parsed.groupdict()
|
|
else:
|
|
signal_parseddict = {}
|
|
signal = signal_parseddict.get('signal', 'unknown')
|
|
code = signal_parseddict.get('code', 'unknown')
|
|
fault_addr = signal_parseddict.get('fault_addr', '')
|
|
|
|
abort_line = parsedict.get('abort', '')
|
|
|
|
if parsed:
|
|
message = 'Process {} ({}) got signal {} code {}'.format(name, cmd, signal, code)
|
|
if abort_line:
|
|
message += '\n'+abort_line
|
|
else:
|
|
message = fn+'\n'+dat[:1024]
|
|
|
|
|
|
client.captureMessage(
|
|
message=message,
|
|
date=datetime.datetime.utcfromtimestamp(mtime),
|
|
data={
|
|
'logger':'tombstoned',
|
|
'platform':'other',
|
|
},
|
|
sdk={'name': 'tombstoned', 'version': '0'},
|
|
extra={
|
|
'fault_addr': fault_addr,
|
|
'abort_msg': abort_line,
|
|
'pid': pid,
|
|
'tid': tid,
|
|
'name':'{} ({})'.format(name, cmd),
|
|
'tombstone_fn': fn,
|
|
'header': parsedict.get('header'),
|
|
'registers': parsedict.get('registers'),
|
|
'backtrace': parsedict.get('backtrace'),
|
|
'logtail': logtail,
|
|
},
|
|
tags={
|
|
'name':'{} ({})'.format(name, cmd),
|
|
'signal':signal,
|
|
'code':code,
|
|
'fault_addr':fault_addr,
|
|
},
|
|
)
|
|
cloudlog.error({'tombstone': message})
|
|
|
|
|
|
def main(gctx):
|
|
initial_tombstones = set(get_tombstones())
|
|
|
|
client = Client('https://d3b175702f62402c91ade04d1c547e68:b20d68c813c74f63a7cdf9c4039d8f56@sentry.io/157615',
|
|
install_sys_hook=False, transport=HTTPTransport, release=version, tags={'dirty': dirty}, string_max_length=10000)
|
|
|
|
client.user_context({'id': os.environ.get('DONGLE_ID')})
|
|
while True:
|
|
now_tombstones = set(get_tombstones())
|
|
|
|
for fn, ctime in (now_tombstones - initial_tombstones):
|
|
cloudlog.info("reporting new tombstone %s", fn)
|
|
report_tombstone(fn, client)
|
|
|
|
initial_tombstones = now_tombstones
|
|
time.sleep(5)
|
|
|
|
if __name__ == "__main__":
|
|
main(None)
|
|
|