4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
1 |
# Copyright (C) 2009 Canonical Ltd
|
2 |
#
|
|
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
#
|
|
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
#
|
|
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
15 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
16 |
||
17 |
||
18 |
"""Handling and reporting crashes.
|
|
19 |
"""
|
|
20 |
||
4584.3.17
by Martin Pool
Better message in apport crash |
21 |
# for interactive testing, try the 'bzr assert-fail' command
|
22 |
# or see http://code.launchpad.net/~mbp/bzr/bzr-fail
|
|
4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
23 |
|
24 |
import os |
|
4584.3.30
by Martin Pool
Fix call to platform() when apport not present |
25 |
import platform |
4584.3.13
by Martin Pool
Refactor _format_plugin_list and include list of loaded modules in apport |
26 |
import pprint |
4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
27 |
import sys |
28 |
import time |
|
4584.3.22
by Martin Pool
further tweaks to and tests of bzr apport reporting |
29 |
from StringIO import StringIO |
4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
30 |
|
31 |
import bzrlib |
|
32 |
from bzrlib import ( |
|
33 |
config, |
|
4584.3.16
by Martin Pool
Add -Dno_apport and fallback if apport fails |
34 |
debug, |
4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
35 |
osutils, |
36 |
plugin, |
|
37 |
trace, |
|
38 |
)
|
|
39 |
||
40 |
||
41 |
def report_bug(exc_info, stderr): |
|
4584.3.16
by Martin Pool
Add -Dno_apport and fallback if apport fails |
42 |
if 'no_apport' not in debug.debug_flags: |
43 |
try: |
|
44 |
report_bug_to_apport(exc_info, stderr) |
|
45 |
return
|
|
4584.3.25
by Martin Pool
Better handling of ImportError from apport |
46 |
except ImportError, e: |
47 |
trace.mutter("couldn't find apport bug-reporting library: %s" % e) |
|
48 |
pass
|
|
4584.3.16
by Martin Pool
Add -Dno_apport and fallback if apport fails |
49 |
except Exception, e: |
4584.3.21
by Martin Pool
Start adding tests for apport |
50 |
# this should only happen if apport is installed but it didn't
|
51 |
# work, eg because of an io error writing the crash file
|
|
4584.3.22
by Martin Pool
further tweaks to and tests of bzr apport reporting |
52 |
sys.stderr.write("bzr: failed to report crash using apport:\n " |
53 |
" %r\n" % e) |
|
4584.3.16
by Martin Pool
Add -Dno_apport and fallback if apport fails |
54 |
pass
|
55 |
report_bug_legacy(exc_info, stderr) |
|
4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
56 |
|
57 |
||
58 |
def report_bug_legacy(exc_info, err_file): |
|
59 |
"""Report a bug by just printing a message to the user."""
|
|
60 |
trace.print_exception(exc_info, err_file) |
|
61 |
err_file.write('\n') |
|
62 |
err_file.write('bzr %s on python %s (%s)\n' % \ |
|
63 |
(bzrlib.__version__, |
|
64 |
bzrlib._format_version_tuple(sys.version_info), |
|
4584.3.30
by Martin Pool
Fix call to platform() when apport not present |
65 |
platform.platform(aliased=1))) |
4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
66 |
err_file.write('arguments: %r\n' % sys.argv) |
67 |
err_file.write( |
|
68 |
'encoding: %r, fsenc: %r, lang: %r\n' % ( |
|
69 |
osutils.get_user_encoding(), sys.getfilesystemencoding(), |
|
70 |
os.environ.get('LANG'))) |
|
71 |
err_file.write("plugins:\n") |
|
4584.3.22
by Martin Pool
further tweaks to and tests of bzr apport reporting |
72 |
err_file.write(_format_plugin_list()) |
4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
73 |
err_file.write( |
4584.3.22
by Martin Pool
further tweaks to and tests of bzr apport reporting |
74 |
"\n\n" |
4584.3.19
by Martin Pool
Tweak crash message and use the same one with apport or without. |
75 |
"*** Bazaar has encountered an internal error. This probably indicates a\n" |
4584.3.22
by Martin Pool
further tweaks to and tests of bzr apport reporting |
76 |
" bug in Bazaar. You can help us fix it by filing a bug report at\n" |
77 |
" https://bugs.launchpad.net/bzr/+filebug\n" |
|
78 |
" including this traceback and a description of the problem.\n" |
|
4584.3.19
by Martin Pool
Tweak crash message and use the same one with apport or without. |
79 |
)
|
4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
80 |
|
81 |
||
82 |
def report_bug_to_apport(exc_info, stderr): |
|
83 |
"""Report a bug to apport for optional automatic filing.
|
|
84 |
"""
|
|
85 |
# this is based on apport_package_hook.py, but omitting some of the
|
|
86 |
# Ubuntu-specific policy about what to report and when
|
|
4584.3.25
by Martin Pool
Better handling of ImportError from apport |
87 |
|
88 |
# if this fails its caught at a higher level; we don't want to open the
|
|
89 |
# crash file unless apport can be loaded.
|
|
90 |
import apport |
|
4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
91 |
|
4584.3.21
by Martin Pool
Start adding tests for apport |
92 |
crash_file = _open_crash_file() |
93 |
try: |
|
4584.3.22
by Martin Pool
further tweaks to and tests of bzr apport reporting |
94 |
_write_apport_report_to_file(exc_info, crash_file) |
4584.3.21
by Martin Pool
Start adding tests for apport |
95 |
finally: |
96 |
crash_file.close() |
|
97 |
||
98 |
stderr.write("bzr: ERROR: %s.%s: %s\n" |
|
99 |
"\n" |
|
100 |
"*** Bazaar has encountered an internal error. This probably indicates a\n" |
|
4584.3.22
by Martin Pool
further tweaks to and tests of bzr apport reporting |
101 |
" bug in Bazaar. You can help us fix it by filing a bug report at\n" |
102 |
" https://bugs.launchpad.net/bzr/+filebug\n" |
|
103 |
" attaching the crash file\n" |
|
104 |
" %s\n" |
|
105 |
" and including a description of the problem.\n" |
|
106 |
"\n" |
|
107 |
" The crash file is plain text and you can inspect or edit it to remove\n" |
|
108 |
" private information.\n" |
|
4584.3.21
by Martin Pool
Start adding tests for apport |
109 |
% (exc_info[0].__module__, exc_info[0].__name__, exc_info[1], |
110 |
crash_file.name)) |
|
111 |
||
112 |
||
113 |
def _write_apport_report_to_file(exc_info, crash_file): |
|
4584.3.22
by Martin Pool
further tweaks to and tests of bzr apport reporting |
114 |
import traceback |
4584.3.21
by Martin Pool
Start adding tests for apport |
115 |
from apport.report import Report |
4584.3.22
by Martin Pool
further tweaks to and tests of bzr apport reporting |
116 |
|
117 |
exc_type, exc_object, exc_tb = exc_info |
|
118 |
||
4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
119 |
pr = Report() |
120 |
# add_proc_info gives you the memory map of the process: this seems rarely
|
|
121 |
# useful for Bazaar and it does make the report harder to scan, though it
|
|
122 |
# does tell you what binary modules are loaded.
|
|
123 |
# pr.add_proc_info()
|
|
124 |
pr.add_user_info() |
|
4584.3.22
by Martin Pool
further tweaks to and tests of bzr apport reporting |
125 |
pr['CommandLine'] = pprint.pformat(sys.argv) |
4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
126 |
pr['BzrVersion'] = bzrlib.__version__ |
127 |
pr['PythonVersion'] = bzrlib._format_version_tuple(sys.version_info) |
|
128 |
pr['Platform'] = platform.platform(aliased=1) |
|
129 |
pr['UserEncoding'] = osutils.get_user_encoding() |
|
130 |
pr['FileSystemEncoding'] = sys.getfilesystemencoding() |
|
131 |
pr['Locale'] = os.environ.get('LANG') |
|
4584.3.13
by Martin Pool
Refactor _format_plugin_list and include list of loaded modules in apport |
132 |
pr['BzrPlugins'] = _format_plugin_list() |
133 |
pr['PythonLoadedModules'] = _format_module_list() |
|
4584.3.22
by Martin Pool
further tweaks to and tests of bzr apport reporting |
134 |
pr['BzrDebugFlags'] = pprint.pformat(debug.debug_flags) |
135 |
||
136 |
tb_file = StringIO() |
|
137 |
traceback.print_exception(exc_type, exc_object, exc_tb, file=tb_file) |
|
138 |
pr['Traceback'] = tb_file.getvalue() |
|
139 |
||
4584.3.21
by Martin Pool
Start adding tests for apport |
140 |
pr.write(crash_file) |
4584.3.6
by Martin Pool
Move apport integration to bzrlib.crash and send output to a file. |
141 |
|
142 |
||
143 |
def _open_crash_file(): |
|
144 |
crash_dir = config.crash_dir() |
|
145 |
# user-readable only, just in case the contents are sensitive.
|
|
146 |
if not osutils.isdir(crash_dir): |
|
147 |
os.makedirs(crash_dir, mode=0700) |
|
148 |
filename = 'bzr-%s-%s.crash' % ( |
|
149 |
osutils.compact_date(time.time()), |
|
150 |
os.getpid(),) |
|
151 |
return open(osutils.pathjoin(crash_dir, filename), 'wt') |
|
4584.3.13
by Martin Pool
Refactor _format_plugin_list and include list of loaded modules in apport |
152 |
|
153 |
||
154 |
def _format_plugin_list(): |
|
155 |
plugin_lines = [] |
|
156 |
for name, a_plugin in sorted(plugin.plugins().items()): |
|
157 |
plugin_lines.append(" %-20s %s [%s]" % |
|
158 |
(name, a_plugin.path(), a_plugin.__version__)) |
|
159 |
return '\n'.join(plugin_lines) |
|
160 |
||
161 |
||
162 |
def _format_module_list(): |
|
163 |
return pprint.pformat(sys.modules) |