32
32
In principle apport can run on any platform though as of Feb 2010 there seem
33
33
to be some portability bugs.
35
To force this off in brz turn set APPORT_DISABLE in the environment or
35
To force this off in bzr turn set APPORT_DISABLE in the environment or
39
# for interactive testing, try the 'brz assert-fail' command
39
from __future__ import absolute_import
41
# for interactive testing, try the 'bzr assert-fail' command
40
42
# or see http://code.launchpad.net/~mbp/bzr/bzr-fail
42
44
# to test with apport it's useful to set
43
45
# export APPORT_IGNORE_OBSOLETE_PACKAGES=1
45
from io import StringIO
62
66
def report_bug(exc_info, stderr):
63
67
if ('no_apport' in debug.debug_flags) or \
64
os.environ.get('APPORT_DISABLE', None):
68
os.environ.get('APPORT_DISABLE', None):
65
69
return report_bug_legacy(exc_info, stderr)
67
71
if report_bug_to_apport(exc_info, stderr):
72
76
except Exception as e:
73
77
# this should only happen if apport is installed but it didn't
74
78
# work, eg because of an io error writing the crash file
75
trace.mutter("brz: failed to report crash using apport: %r" % e)
79
trace.mutter("bzr: failed to report crash using apport: %r" % e)
76
80
trace.log_exception_quietly()
77
81
return report_bug_legacy(exc_info, stderr)
82
86
trace.print_exception(exc_info, err_file)
83
87
err_file.write('\n')
86
89
def print_wrapped(l):
87
err_file.write(textwrap.fill(
88
l, width=78, subsequent_indent=' ') + '\n')
89
print_wrapped('brz %s on python %s (%s)\n' %
91
breezy._format_version_tuple(sys.version_info),
92
platform.platform(aliased=1)))
90
err_file.write(textwrap.fill(l,
91
width=78, subsequent_indent=' ') + '\n')
92
print_wrapped('bzr %s on python %s (%s)\n' % \
94
breezy._format_version_tuple(sys.version_info),
95
platform.platform(aliased=1)))
93
96
print_wrapped('arguments: %r\n' % sys.argv)
94
97
print_wrapped(textwrap.fill(
95
98
'plugins: ' + plugin.format_concise_plugin_list(),
106
109
"*** Bazaar has encountered an internal error. This probably indicates a\n"
107
110
" bug in Bazaar. You can help us fix it by filing a bug report at\n"
108
" https://bugs.launchpad.net/brz/+filebug\n"
111
" https://bugs.launchpad.net/bzr/+filebug\n"
109
112
" including this traceback and a description of the problem.\n"
121
124
# This import is apparently not used, but we're doing it so that if the
122
125
# import fails, the exception will be caught at a higher level and we'll
123
126
# report the error by other means.
124
import apport # noqa: F401
126
129
crash_filename = _write_apport_report_to_file(exc_info)
128
131
if crash_filename is None:
129
132
stderr.write("\n"
130
"apport is set to ignore crashes in this version of brz.\n"
133
"apport is set to ignore crashes in this version of bzr.\n"
133
136
trace.print_exception(exc_info, stderr)
134
137
stderr.write("\n"
135
"You can report this problem to Bazaar's developers by running\n"
137
"if a bug-reporting window does not automatically appear.\n"
138
"You can report this problem to Bazaar's developers by running\n"
140
"if a bug-reporting window does not automatically appear.\n"
139
142
# XXX: on Windows, Mac, and other platforms where we might have the
140
143
# apport libraries but not have an apport always running, we could
141
144
# synchronously file now
158
161
pr.add_user_info()
160
163
# Package and SourcePackage are needed so that apport will report about even
161
# non-packaged versions of brz; also this reports on their packaged
164
# non-packaged versions of bzr; also this reports on their packaged
162
165
# dependencies which is useful.
163
pr['SourcePackage'] = 'brz'
164
pr['Package'] = 'brz'
166
pr['SourcePackage'] = 'bzr'
167
pr['Package'] = 'bzr'
166
169
pr['CommandLine'] = pprint.pformat(sys.argv)
167
pr['BrzVersion'] = breezy.__version__
170
pr['BzrVersion'] = breezy.__version__
168
171
pr['PythonVersion'] = breezy._format_version_tuple(sys.version_info)
169
172
pr['Platform'] = platform.platform(aliased=1)
170
173
pr['UserEncoding'] = osutils.get_user_encoding()
171
174
pr['FileSystemEncoding'] = sys.getfilesystemencoding()
172
175
pr['Locale'] = os.environ.get('LANG', 'C')
173
pr['BrzPlugins'] = _format_plugin_list()
176
pr['BzrPlugins'] = _format_plugin_list()
174
177
pr['PythonLoadedModules'] = _format_module_list()
175
pr['BrzDebugFlags'] = pprint.pformat(debug.debug_flags)
178
pr['BzrDebugFlags'] = pprint.pformat(debug.debug_flags)
177
180
# actually we'd rather file directly against the upstream product, but
178
181
# apport does seem to count on there being one in there; we might need to
179
182
# redirect it elsewhere anyhow
180
pr['SourcePackage'] = 'brz'
181
pr['Package'] = 'brz'
183
pr['SourcePackage'] = 'bzr'
184
pr['Package'] = 'bzr'
183
# tell apport to file directly against the brz package using
186
# tell apport to file directly against the bzr package using
184
187
# <https://bugs.launchpad.net/bzr/+bug/391015>
186
189
# XXX: unfortunately apport may crash later if the crashdb definition
187
190
# file isn't present
188
pr['CrashDb'] = 'brz'
191
pr['CrashDb'] = 'bzr'
190
193
tb_file = StringIO()
191
194
traceback.print_exception(exc_type, exc_object, exc_tb, file=tb_file)
194
197
_attach_log_tail(pr)
196
# We want to use the 'brz' crashdb so that it gets sent directly upstream,
199
# We want to use the 'bzr' crashdb so that it gets sent directly upstream,
197
200
# which is a reasonable default for most internal errors. However, if we
198
201
# set it here then apport will crash later if it doesn't know about that
199
# crashdb. Instead, we rely on the brz package installing both a
202
# crashdb. Instead, we rely on the bzr package installing both a
200
203
# source hook telling crashes to go to this crashdb, and a crashdb
201
204
# configuration describing it.
203
206
# these may contain some sensitive info (smtp_passwords)
204
207
# TODO: strip that out and attach the rest
206
# attach_file_if_exists(report,
207
# os.path.join(dot_brz, 'breezy.conf', 'BrzConfig')
208
# attach_file_if_exists(report,
209
# os.path.join(dot_brz, 'locations.conf', 'BrzLocations')
209
#attach_file_if_exists(report,
210
# os.path.join(dot_bzr, 'bazaar.conf', 'BzrConfig')
211
#attach_file_if_exists(report,
212
# os.path.join(dot_bzr, 'locations.conf', 'BzrLocations')
211
214
# strip username, hostname, etc
224
227
def _attach_log_tail(pr):
226
brz_log = open(trace._get_brz_log_filename(), 'rt')
229
bzr_log = open(trace._get_brz_log_filename(), 'rt')
227
230
except (IOError, OSError) as e:
228
pr['BrzLogTail'] = repr(e)
231
pr['BzrLogTail'] = repr(e)
231
lines = brz_log.readlines()
232
pr['BrzLogTail'] = ''.join(lines[-40:])
234
lines = bzr_log.readlines()
235
pr['BzrLogTail'] = ''.join(lines[-40:])
237
240
def _open_crash_file():
238
crash_dir = bedding.crash_dir()
241
crash_dir = config.crash_dir()
239
242
if not osutils.isdir(crash_dir):
240
243
# on unix this should be /var/crash and should already exist; on
241
244
# Windows or if it's manually configured it might need to be created,
242
245
# and then it should be private
243
246
os.makedirs(crash_dir, mode=0o600)
244
date_string = time.strftime('%Y-%m-%dT%H:%M', time.gmtime())
247
date_string = time.strftime('%Y-%m-%dT%H:%M', osutils.gmtime())
245
248
# XXX: getuid doesn't work on win32, but the crash directory is per-user
246
249
if sys.platform == 'win32':
249
252
user_part = '.%d' % os.getuid()
250
253
filename = osutils.pathjoin(
255
258
# be careful here that people can't play tmp-type symlink mischief in the
256
259
# world-writable directory
257
260
return filename, os.fdopen(
259
os.O_WRONLY | os.O_CREAT | os.O_EXCL,
262
os.O_WRONLY|os.O_CREAT|os.O_EXCL,