[geary/wip/713006-better-error-reporting] Include a back trace in problem report technical details.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/713006-better-error-reporting] Include a back trace in problem report technical details.
- Date: Sat, 18 Nov 2017 04:26:08 +0000 (UTC)
commit bcca75f5a827f30767f2d7e531724a2aa7238c25
Author: Michael James Gratton <mike vee net>
Date: Sat Nov 18 15:25:28 2017 +1100
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.
INSTALL | 6 ++-
bindings/vapi/libunwind.vapi | 63 +++++++++++++++++++++++
debian/control | 2 +
src/CMakeLists.txt | 2 +
src/client/components/main-window-info-bar.vala | 18 ++++--
src/engine/api/geary-problem-report.vala | 47 +++++++++++++++++
ui/main-window-info-bar.ui | 29 +++++++---
7 files changed, 150 insertions(+), 17 deletions(-)
---
diff --git a/INSTALL b/INSTALL
index 44962ec..da17adc 100644
--- a/INSTALL
+++ b/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:
diff --git a/bindings/vapi/libunwind.vapi b/bindings/vapi/libunwind.vapi
new file mode 100644
index 0000000..7a4b39d
--- /dev/null
+++ b/bindings/vapi/libunwind.vapi
@@ -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
+ }
+
+}
diff --git a/debian/control b/debian/control
index 61ffd31..61db4e6 100644
--- a/debian/control
+++ b/debian/control
@@ -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
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0f2a2e5..942c6b1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -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
diff --git a/src/client/components/main-window-info-bar.vala b/src/client/components/main-window-info-bar.vala
index 13048f9..96ba5fb 100644
--- a/src/client/components/main-window-info-bar.vala
+++ b/src/client/components/main-window-info-bar.vala
@@ -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;
}
diff --git a/src/engine/api/geary-problem-report.vala b/src/engine/api/geary-problem-report.vala
index dd9ad2e..938fd4e 100644
--- a/src/engine/api/geary-problem-report.vala
+++ b/src/engine/api/geary-problem-report.vala
@@ -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. */
diff --git a/ui/main-window-info-bar.ui b/ui/main-window-info-bar.ui
index 312ffaa..6817927 100644
--- a/ui/main-window-info-bar.ui
+++ b/ui/main-window-info-bar.ui
@@ -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>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]