DeveloperHowTo

Differences between revisions 8 and 9
Revision 8 as of 2008-08-06 00:51:24
Size: 4262
Editor: c-67-168-235-241
Comment: guess all the questions are answered in the txt file
Revision 9 as of 2008-08-06 06:51:07
Size: 5740
Editor: p579DED5B
Comment: document custom invocation
Deletions are marked like this. Additions are marked like this.
Line 74: Line 74:
For still greater flexibility, apport can be invoked explicitly to trap and report on custom events, even if no signal-driven crash (such as a segfault) has occurred. For example, GCC can trap internal compiler errors, and the kernel can trap system crash dumps. Apport needs to be "triggered" by something to create a report. For real
crashes, that is the kernel itself (`/proc/sys/kernel/core_pattern`), for Python
scripts this is a fallback exception handler in `/etc/python2.5/sitecustomize.py`.
Line 76: Line 78:
'''XXX examples''' For still greater flexibility, apport can be invoked explicitly under other
conditions, to trap and report on custom events, even if no signal-driven crash
(such as a segfault) has occurred. For example, GCC can trap internal compiler
errors and calls `/usr/share/apport/gcc_ice_hook` if one happens; if apt sees
that a package fails to install, it calls `/usr/share/apport/package_hook`.

These scripts should create minimal `apport.Report()` object and set the
`Package` and `SourcPackage` fields correctly, so that any matching package
hook will be triggered as well. Finally it should write the report to a file.

Additional information collection can either happen

 * directly in the script, if it needs to be done synchronously when the script is called, or

 * in a separate package hook, in which case the additional information collection will be done asynchronously when the user gets notified about the problem and decides to report it.

In general you should collect as much information as possible in package hooks, especially when they require expensive operations. That way, the calling program does not have to block very long, and information is not collected if the user does not want to report a bug at all.

For an asynchronous script, see `/usr/share/apport/kernel_hook` and the accompanying package hook `/usr/share/apport/package-hooks/source_linux.py`. For a synchronous script, see `/usr/share/apport/gcc_ice_hook` (this also shows how to read bulk data directly from stdin).

How to Use Apport in your Programs

By default, apport provides the following functionality for all programs in Ubuntu:

  • When a program segfaults, apport stores a persistent crash report in /var/crash which can be later analyzed even if the bug cannot be reproduced by a developer

  • Relevant information about the state of the system and installed software is automatically included in the report
  • Apport can semi-automatically attach the crash report to a bug report in Launchpad
  • For C and C++ programs, the [:../Retracer:retracer] will automatically decode the stack trace in the crash report and attach the decoded stack trace to the bug report. See [https://bugs.launchpad.net/ubuntu/+source/gvfs/+bug/252046 bug #252046] as an example how this looks like.

Package Hooks

In addition to the generic information apport collects, arbitrary package-specific data can be included in the report by adding package hooks. For example:

  • Relevant log files
  • Configuration files
  • Current system state

Hooks can also cause a crash to be ignored, or the report suppressed with an explanation.

To create a hook, have your package install a file /usr/share/apport/<binarypackagename>.py or /usr/share/apport/source_<sourcepackagename>.py. The hook will be used whenever apport logs a report for the specified package. Here's a simple example of a hook:

import os.path

def add_info(report):
    if os.path.exists('/var/log/foo.log'):
        report['FooLog'] = open('/var/log/foo.log').read()

'report' is a Python dictionary which can be used to store arbitrary data using a string key.

For complete instructions, see /usr/share/doc/apport/package-hooks.txt

General Hooks

These are the same as package hooks, but apply to all packages. They can be used, for example, to implement a 'taint check' which reports on whether certain problematic software is installed, regardless of which program is misbehaving. They are installed in /usr/share/apport/general-hooks/*.py.

For complete instructions, see /usr/share/doc/apport/package-hooks.txt

Bug patterns

Apport can suppress reports for bugs which have already been reported. Sometimes a bug affects so many people that we get hundreds of duplicates in a matter of days, which both creates a lot of needless reporting, triaging, and retracing work. In those cases, and when the bug can be uniquely identified with regular expressions on the apport report keys, a "bug pattern" should be created which will prevent Apport from reporting the bug in the first place, and instead guide the user to the already existing bug page.

To avoid inventing a new file format and to be able to extend the functionality in the future (e. g. other operators than just regexp matching) the bug patterns are stored as XML files, named after the binary package.

The general syntax is:

  • {{{ root element := <patterns> patterns := <pattern url="http://bug.url"> * pattern := <re key="report_key">regular expression*</re>

}}}

For example:

}}}

The bug patterns are publicly accessible at http://people.ubuntu.com/~pitti/bugpatterns/, where Apport (when running on the client side) will check for them. They are maintained in a [https://code.launchpad.net/~ubuntu-bugcontrol/apport/ubuntu-bugpatterns bzr branch] accessible to the [https://launchpad.net/~ubuntu-bugcontrol/ Ubuntu bug control] team, and copied to people.ubuntu.com every 15 minutes.

Custom Invocation

Apport needs to be "triggered" by something to create a report. For real crashes, that is the kernel itself (/proc/sys/kernel/core_pattern), for Python scripts this is a fallback exception handler in /etc/python2.5/sitecustomize.py.

For still greater flexibility, apport can be invoked explicitly under other conditions, to trap and report on custom events, even if no signal-driven crash (such as a segfault) has occurred. For example, GCC can trap internal compiler errors and calls /usr/share/apport/gcc_ice_hook if one happens; if apt sees that a package fails to install, it calls /usr/share/apport/package_hook.

These scripts should create minimal apport.Report() object and set the Package and SourcPackage fields correctly, so that any matching package hook will be triggered as well. Finally it should write the report to a file.

Additional information collection can either happen

  • directly in the script, if it needs to be done synchronously when the script is called, or
  • in a separate package hook, in which case the additional information collection will be done asynchronously when the user gets notified about the problem and decides to report it.

In general you should collect as much information as possible in package hooks, especially when they require expensive operations. That way, the calling program does not have to block very long, and information is not collected if the user does not want to report a bug at all.

For an asynchronous script, see /usr/share/apport/kernel_hook and the accompanying package hook /usr/share/apport/package-hooks/source_linux.py. For a synchronous script, see /usr/share/apport/gcc_ice_hook (this also shows how to read bulk data directly from stdin).

TODO

Apport/DeveloperHowTo (last edited 2023-08-25 14:02:07 by cjwatson)