~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/crash.py

  • Committer: Vincent Ladeuil
  • Date: 2010-01-25 15:55:48 UTC
  • mto: (4985.1.4 add-attr-cleanup)
  • mto: This revision was merged to the branch mainline in revision 4988.
  • Revision ID: v.ladeuil+lp@free.fr-20100125155548-0l352pujvt5bzl5e
Deploy addAttrCleanup on the whole test suite.

Several use case worth mentioning:

- setting a module or any other object attribute is the majority
by far. In some cases the setting itself is deferred but most of
the time we want to set at the same time we add the cleanup.

- there multiple occurrences of protecting hooks or ui factory
which are now useless (the test framework takes care of that now),

- there was some lambda uses that can now be avoided.

That first cleanup already simplifies things a lot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
21
# for interactive testing, try the 'bzr assert-fail' command 
 
22
# or see http://code.launchpad.net/~mbp/bzr/bzr-fail
 
23
 
 
24
import os
 
25
import platform
 
26
import pprint
 
27
import sys
 
28
import time
 
29
from StringIO import StringIO
 
30
 
 
31
import bzrlib
 
32
from bzrlib import (
 
33
    config,
 
34
    debug,
 
35
    osutils,
 
36
    plugin,
 
37
    trace,
 
38
    )
 
39
 
 
40
 
 
41
def report_bug(exc_info, stderr):
 
42
    if 'no_apport' not in debug.debug_flags:
 
43
        try:
 
44
            report_bug_to_apport(exc_info, stderr)
 
45
            return
 
46
        except ImportError, e:
 
47
            trace.mutter("couldn't find apport bug-reporting library: %s" % e)
 
48
            pass
 
49
        except Exception, e:
 
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
 
52
            sys.stderr.write("bzr: failed to report crash using apport:\n "
 
53
                "    %r\n" % e)
 
54
            pass
 
55
    report_bug_legacy(exc_info, stderr)
 
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),
 
65
                        platform.platform(aliased=1)))
 
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")
 
72
    err_file.write(_format_plugin_list())
 
73
    err_file.write(
 
74
        "\n\n"
 
75
        "*** Bazaar has encountered an internal error.  This probably indicates a\n"
 
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"
 
79
        )
 
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
 
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
 
91
 
 
92
    crash_file = _open_crash_file()
 
93
    try:
 
94
        _write_apport_report_to_file(exc_info, crash_file)
 
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"
 
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"
 
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):
 
114
    import traceback
 
115
    from apport.report import Report
 
116
 
 
117
    exc_type, exc_object, exc_tb = exc_info
 
118
 
 
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()
 
125
    pr['CommandLine'] = pprint.pformat(sys.argv)
 
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')
 
132
    pr['BzrPlugins'] = _format_plugin_list()
 
133
    pr['PythonLoadedModules'] = _format_module_list()
 
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
 
 
140
    pr.write(crash_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')
 
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)