Include a back trace in problem report technical details.
This adds a dependcy on libunwind for generating the back trace. * src/CMakeLists.txt: Require libunwind-generic package and libunwind VAPI. Update docs and debian/control with new dependencies. * src/engine/api/geary-problem-report.vala (ProblemReport): Generate a stack trace in the default constructor if an error is specified. * src/client/components/main-window-info-bar.vala (MainWindowInfoBar::format_details): Include stack trafe from problem report in output if present. * ui/main-window-info-bar.ui: Add a ScrolledWindow around the TextView since the details could now be quite large. * bindings/vapi/libunwind.vapi: Add bindings for libunwind courtesy Guillaume Poirier-Morency, add Error enum.
This commit is contained in:
parent
0d1efc2fe0
commit
bcca75f5a8
7 changed files with 150 additions and 17 deletions
6
INSTALL
6
INSTALL
|
|
@ -46,6 +46,7 @@
|
|||
* webkit2gtk-4.0
|
||||
* gcr-3
|
||||
* enchant
|
||||
* libunwind
|
||||
* messaging-menu (optional; enables support for Ubuntu Unity
|
||||
messaging menu)
|
||||
* unity (optional; enables support for Ubuntu Unity launcher)
|
||||
|
|
@ -67,7 +68,7 @@
|
|||
desktop-file-utils gnome-doc-utils libcanberra-devel libgee-devel \
|
||||
glib2-devel gmime-devel gtk3-devel libnotify-devel sqlite-devel \
|
||||
webkitgtk4-devel libsecret-devel libxml2-devel vala-tools \
|
||||
gcr-devel enchant-devel
|
||||
gcr-devel enchant-devel libunwind-devel
|
||||
|
||||
|
||||
* Installing dependencies on Ubuntu/Debian
|
||||
|
|
@ -86,7 +87,8 @@
|
|||
cmake desktop-file-utils gnome-doc-utils libcanberra-dev \
|
||||
libgee-0.8-dev libglib2.0-dev libgmime-2.6-dev libgtk-3-dev \
|
||||
libsecret-1-dev libxml2-dev libnotify-dev libsqlite3-dev \
|
||||
libwebkit2gtk-4.0-dev libgcr-3-dev libenchant-dev
|
||||
libwebkit2gtk-4.0-dev libgcr-3-dev libenchant-dev \
|
||||
libunwind-dev
|
||||
|
||||
And for Ubuntu Unity integration:
|
||||
|
||||
|
|
|
|||
63
bindings/vapi/libunwind.vapi
Normal file
63
bindings/vapi/libunwind.vapi
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Based on version from Sentry-GLib: https://github.com/arteymix/sentry-glib
|
||||
* Courtesy of Guillaume Poirier-Morency <guillaumepoiriermorency@gmail.com>
|
||||
*/
|
||||
|
||||
[CCode (cprefix = "UNW_", lower_case_cprefix = "unw_", cheader_filename = "libunwind.h")]
|
||||
namespace Unwind
|
||||
{
|
||||
|
||||
[CCode (cname = "unw_context_t")]
|
||||
public struct Context
|
||||
{
|
||||
[CCode (cname = "unw_getcontext")]
|
||||
public Context ();
|
||||
}
|
||||
|
||||
[CCode (cname = "unw_proc_info_t")]
|
||||
public struct ProcInfo
|
||||
{
|
||||
void* start_ip;
|
||||
void* end_ip;
|
||||
void* lsda;
|
||||
void* handler;
|
||||
void* gp;
|
||||
long flags;
|
||||
int format;
|
||||
}
|
||||
|
||||
[CCode (cname = "unw_frame_regnum_t")]
|
||||
public enum Reg
|
||||
{
|
||||
IP,
|
||||
SP,
|
||||
EH
|
||||
}
|
||||
|
||||
[CCode (cname = "unw_cursor_t", cprefix = "unw_")]
|
||||
public struct Cursor
|
||||
{
|
||||
public Cursor.local (Context ctx);
|
||||
public int get_proc_info (out ProcInfo pip);
|
||||
public int get_proc_name (uint8[] bufp, out long offp = null);
|
||||
public int get_reg (Reg reg, out void* valp);
|
||||
public int step ();
|
||||
}
|
||||
|
||||
[CCode (cname = "unw_error_t", cprefix = "UNW_E", has_type_id = false)]
|
||||
public enum Error
|
||||
{
|
||||
SUCCESS,
|
||||
UNSPEC,
|
||||
NOMEM,
|
||||
BADREG,
|
||||
READONLYREG,
|
||||
STOPUNWIND,
|
||||
INVALIDIP,
|
||||
BADFRAME,
|
||||
INVAL,
|
||||
BADVERSION,
|
||||
NOINFO
|
||||
}
|
||||
|
||||
}
|
||||
2
debian/control
vendored
2
debian/control
vendored
|
|
@ -23,6 +23,7 @@ Build-Depends: debhelper (>= 8),
|
|||
gnome-doc-utils,
|
||||
libgcr-3-dev (>= 3.10.1),
|
||||
libenchant-dev (>= 1.6.0)
|
||||
libunwind8-dev (>= 1.1)
|
||||
Standards-Version: 3.8.3
|
||||
Homepage: https://wiki.gnome.org/Apps/Geary
|
||||
|
||||
|
|
@ -45,6 +46,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends},
|
|||
libgcr-base-3-1 (>= 3.10.1),
|
||||
libgcr-ui-3-1 (>= 3.10.1),
|
||||
libenchant1c2a (>= 1.6.0)
|
||||
libunwind8 (>= 1.1)
|
||||
Description: Email application
|
||||
Geary is an email application built around conversations, for the
|
||||
GNOME 3 desktop. It allows you to read, find and send email with a
|
||||
|
|
|
|||
|
|
@ -512,6 +512,7 @@ pkg_check_modules(DEPS REQUIRED
|
|||
webkit2gtk-web-extension-4.0>=${TARGET_WEBKIT}
|
||||
javascriptcoregtk-4.0>=${TARGET_WEBKIT}
|
||||
enchant>=1.6
|
||||
libunwind-generic>=1.1
|
||||
${EXTRA_CLIENT_PKG_CONFIG}
|
||||
)
|
||||
|
||||
|
|
@ -529,6 +530,7 @@ set(ENGINE_PACKAGES
|
|||
gio-2.0
|
||||
glib-2.0
|
||||
gmime-2.6
|
||||
libunwind
|
||||
javascriptcore-4.0
|
||||
libxml-2.0
|
||||
posix
|
||||
|
|
|
|||
|
|
@ -213,12 +213,18 @@ public class MainWindowInfoBar : Gtk.InfoBar {
|
|||
"Endpoint: %s\n", service_report.endpoint.to_string()
|
||||
);
|
||||
}
|
||||
details.append_printf(
|
||||
"Error type: %s\n", (this.report.error != null) ? this.report.format_error_type() : "None specified"
|
||||
);
|
||||
details.append_printf(
|
||||
"Message: %s\n", (this.report.error != null) ? this.report.error.message : "None specified"
|
||||
);
|
||||
if (this.report.error == null) {
|
||||
details.append("No error reported");
|
||||
} else {
|
||||
details.append_printf("Error type: %s\n", this.report.format_error_type());
|
||||
details.append_printf("Message: %s\n", this.report.error.message);
|
||||
}
|
||||
if (this.report.backtrace != null) {
|
||||
details.append("Back trace:\n");
|
||||
foreach (Geary.ProblemReport.StackFrame frame in this.report.backtrace) {
|
||||
details.append_printf(" - %s\n", frame.to_string());
|
||||
}
|
||||
}
|
||||
return details.str;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
/** Describes available problem types. */
|
||||
public enum Geary.ProblemType {
|
||||
|
||||
|
||||
/** Indicates an engine problem not covered by one of the other types. */
|
||||
GENERIC_ERROR,
|
||||
|
||||
|
|
@ -30,6 +31,7 @@ public enum Geary.ProblemType {
|
|||
/** Indicates an outgoing message was sent, but not saved. */
|
||||
SEND_EMAIL_SAVE_FAILED;
|
||||
|
||||
|
||||
/** Determines the appropriate problem type for an IOError. */
|
||||
public static ProblemType for_ioerror(IOError error) {
|
||||
if (error is IOError.CONNECTION_REFUSED ||
|
||||
|
|
@ -54,16 +56,61 @@ public enum Geary.ProblemType {
|
|||
*/
|
||||
public class Geary.ProblemReport : Object {
|
||||
|
||||
|
||||
/**
|
||||
* Represents an individual stack frame in a call back-trace.
|
||||
*/
|
||||
public class StackFrame {
|
||||
|
||||
|
||||
/** Name of the function being called. */
|
||||
public string name = "unknown";
|
||||
|
||||
|
||||
internal StackFrame(Unwind.Cursor frame) {
|
||||
uint8 proc_name[256];
|
||||
int ret = -frame.get_proc_name(proc_name);
|
||||
if (ret == Unwind.Error.SUCCESS ||
|
||||
ret == Unwind.Error.NOMEM) {
|
||||
this.name = (string) proc_name;
|
||||
}
|
||||
}
|
||||
|
||||
public string to_string() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** Describes the type of being reported. */
|
||||
public ProblemType problem_type { get; private set; }
|
||||
|
||||
/** The exception caused the problem, if any. */
|
||||
public Error? error { get; private set; default = null; }
|
||||
|
||||
/** A back trace from when the problem report was constructed. */
|
||||
public Gee.List<StackFrame>? backtrace = null;
|
||||
|
||||
|
||||
public ProblemReport(ProblemType type, Error? error) {
|
||||
this.problem_type = type;
|
||||
this.error = error;
|
||||
|
||||
if (error != null) {
|
||||
// Some kind of exception occurred, so build a trace. This
|
||||
// is far from perfect, but at least we will know where it
|
||||
// was getting caught.
|
||||
this.backtrace = new Gee.LinkedList<StackFrame>();
|
||||
Unwind.Context trace = Unwind.Context();
|
||||
Unwind.Cursor cursor = Unwind.Cursor.local(trace);
|
||||
|
||||
// This misses the first frame, but that's this
|
||||
// constructor call, so we don't really care.
|
||||
while (cursor.step() != 0) {
|
||||
this.backtrace.add(new StackFrame(cursor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a string representation of the report, for debugging only. */
|
||||
|
|
|
|||
|
|
@ -119,19 +119,30 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTextView" id="detail_text">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="width_request">600</property>
|
||||
<property name="height_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="editable">False</property>
|
||||
<property name="wrap_mode">word</property>
|
||||
<property name="left_margin">6</property>
|
||||
<property name="right_margin">6</property>
|
||||
<property name="top_margin">6</property>
|
||||
<property name="bottom_margin">6</property>
|
||||
<property name="cursor_visible">False</property>
|
||||
<property name="monospace">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTextView" id="detail_text">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="editable">False</property>
|
||||
<property name="wrap_mode">word</property>
|
||||
<property name="left_margin">6</property>
|
||||
<property name="right_margin">6</property>
|
||||
<property name="top_margin">6</property>
|
||||
<property name="bottom_margin">6</property>
|
||||
<property name="cursor_visible">False</property>
|
||||
<property name="monospace">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue