add a way to create a crash report

This commit is contained in:
Michael Hudson-Doyle 2019-10-31 14:34:10 +13:00
parent 38dfeebde7
commit 74ef2ad8f6
4 changed files with 61 additions and 20 deletions

View File

@ -49,6 +49,7 @@ parts:
- libsystemd0
- iso-codes
- lsb-release
- python3-apport
- python3-distutils-extra
- python3-urwid
- python3-requests

View File

@ -13,11 +13,11 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import datetime
import enum
import json
import logging
import os
import time
import apport
import apport.crashdb
@ -57,21 +57,10 @@ class ErrorReport:
@classmethod
def new(cls, controller, kind):
prefix = "installer.{}.{}".format(
datetime.datetime.utcnow().isoformat(timespec='seconds'),
kind.name.lower())
i = 0
while 1:
base = "{}.{}".format(prefix, i)
crash_path = os.path.join(
controller.crash_directory, base + ".crash")
try:
crash_file = open(crash_path, 'xb')
except FileExistsError:
i += 1
continue
else:
break
base = "installer.{:.9f}.{}".format(time.time(), kind.name.lower())
crash_file = open(
os.path.join(controller.crash_directory, base + ".crash"),
'wb')
pr = apport.Report('Bug')
pr['CrashDB'] = repr(controller.crashdb_spec)

View File

@ -16,9 +16,16 @@
import logging
import os
import platform
import sys
import traceback
import apport.hookutils
from subiquitycore.core import Application
from subiquity.controllers.error import (
ErrorController,
)
from subiquity.models.subiquity import SubiquityModel
from subiquity.snapd import (
FakeSnapdConnection,
@ -128,8 +135,49 @@ class Subiquity(Application):
self.run_command_in_foreground(
"bash", before_hook=_before, cwd='/')
def load_controllers(self):
super().load_controllers()
self.error_controller = ErrorController(self)
def start_controllers(self):
super().start_controllers()
self.error_controller.start()
def note_file_for_apport(self, key, path):
self._apport_files.append((key, path))
def note_data_for_apport(self, key, value):
self._apport_data.append((key, value))
def make_apport_report(self, kind, thing, *, wait=False):
log.debug("generating crash report")
try:
report = self.error_controller.create_report(kind)
except Exception:
log.exception("creating crash report failed")
return
etype = sys.exc_info()[0]
if etype is not None:
report.pr["Title"] = "{} crashed with {}".format(
thing, etype.__name__)
report.pr['Traceback'] = traceback.format_exc()
else:
report.pr["Title"] = thing
apport_files = self._apport_files[:]
apport_data = self._apport_data.copy()
def _bg_attach_hook():
# Attach any stuff other parts of the code think we should know
# about.
for key, path in apport_files:
apport.hookutils.attach_file_if_exists(report.pr, path, key)
for key, value in apport_data:
report.pr[key] = value
report.add_info(_bg_attach_hook, wait)
# In the fullness of time we should do the signature thing here.
return report

View File

@ -570,6 +570,12 @@ class Application:
orig, count)
log.debug("load_controllers done")
def start_controllers(self):
log.debug("starting controllers")
for k in self.controllers:
self.controller_instances[k].start()
log.debug("controllers started")
def load_serialized_state(self):
for k in self.controllers:
state_path = os.path.join(self.state_dir, 'states', k)
@ -631,10 +637,7 @@ class Application:
0.05, select_initial_screen, initial_controller_index)
self._connect_base_signals()
log.debug("starting controllers")
for k in self.controllers:
self.controller_instances[k].start()
log.debug("controllers started")
self.start_controllers()
self.loop.run()
except Exception: