Depend on libhandy
This commit is contained in:
parent
bf17d460f4
commit
7faca4090e
|
@ -18,6 +18,7 @@ To build the app, make sure you have these dependencies:
|
||||||
* libsoup2.4-dev
|
* libsoup2.4-dev
|
||||||
* libgranite-dev
|
* libgranite-dev
|
||||||
* libjson-glib-dev
|
* libjson-glib-dev
|
||||||
|
* libhandy-0.0-dev
|
||||||
|
|
||||||
Then run `install.sh` in the project directory to install the app.
|
Then run `install.sh` in the project directory to install the app.
|
||||||
|
|
||||||
|
|
11
meson.build
11
meson.build
|
@ -4,10 +4,11 @@ gnome = import('gnome')
|
||||||
i18n = import('i18n')
|
i18n = import('i18n')
|
||||||
|
|
||||||
#add_project_arguments(['--disable-warnings', '-g', '-X', '-rdynamic'], language: 'vala')
|
#add_project_arguments(['--disable-warnings', '-g', '-X', '-rdynamic'], language: 'vala')
|
||||||
add_project_arguments(['-g', '-rdynamic', '-export-dynamic'], language: 'c')
|
#add_project_arguments(['-g', '-rdynamic', '-export-dynamic'], language: 'c')
|
||||||
|
|
||||||
add_global_arguments([
|
add_global_arguments([
|
||||||
'-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name())
|
'-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()),
|
||||||
|
'-DHANDY_USE_UNSTABLE_API',
|
||||||
],
|
],
|
||||||
language: 'c',
|
language: 'c',
|
||||||
)
|
)
|
||||||
|
@ -21,9 +22,6 @@ asresources = gnome.compile_resources(
|
||||||
executable(
|
executable(
|
||||||
meson.project_name(),
|
meson.project_name(),
|
||||||
asresources,
|
asresources,
|
||||||
|
|
||||||
'src/Stacktrace.vala', #TODO: move into a separate lib
|
|
||||||
|
|
||||||
'src/Build.vala',
|
'src/Build.vala',
|
||||||
'src/Application.vala',
|
'src/Application.vala',
|
||||||
'src/Desktop.vala',
|
'src/Desktop.vala',
|
||||||
|
@ -81,8 +79,7 @@ executable(
|
||||||
dependency('granite', version: '>=5.2.0'),
|
dependency('granite', version: '>=5.2.0'),
|
||||||
dependency('json-glib-1.0'),
|
dependency('json-glib-1.0'),
|
||||||
dependency('libsoup-2.4'),
|
dependency('libsoup-2.4'),
|
||||||
|
dependency('libhandy-0.0', version: '>=0.0.13'),
|
||||||
meson.get_compiler('vala').find_library('linux', required: true), #Required by Stacktrace.vala
|
|
||||||
],
|
],
|
||||||
install: true,
|
install: true,
|
||||||
link_args: '-export-dynamic'
|
link_args: '-export-dynamic'
|
||||||
|
|
|
@ -63,10 +63,7 @@ namespace Tootle {
|
||||||
|
|
||||||
public static int main (string[] args) {
|
public static int main (string[] args) {
|
||||||
Gtk.init (ref args);
|
Gtk.init (ref args);
|
||||||
|
Hdy.init (ref args);
|
||||||
Stacktrace.register_handlers ();
|
|
||||||
//assert (true == false); // I'm not crazy. It's for stacktrace testing.
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var opt_context = new OptionContext ("- Options");
|
var opt_context = new OptionContext ("- Options");
|
||||||
opt_context.add_main_entries (app_options, null);
|
opt_context.add_main_entries (app_options, null);
|
||||||
|
|
|
@ -1,651 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 PerfectCarl - https://github.com/PerfectCarl/vala-stacktrace
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Stacktrace {
|
|
||||||
|
|
||||||
public class Frame {
|
|
||||||
// Address used by addr2line
|
|
||||||
public string address { get;private set;default = "";}
|
|
||||||
|
|
||||||
public string line { get;private set;default = "";}
|
|
||||||
|
|
||||||
public string line_number { get;private set;default = "";}
|
|
||||||
|
|
||||||
public string file_path { get;private set;default = "";}
|
|
||||||
|
|
||||||
public string file_short_path { get;private set;default = "";}
|
|
||||||
|
|
||||||
public string function { get;private set;default = "";}
|
|
||||||
|
|
||||||
public Frame (string address, string line, string function, string file_path, string file_short_path) {
|
|
||||||
this._address = address;
|
|
||||||
this._line = line;
|
|
||||||
|
|
||||||
this._file_path = file_path;
|
|
||||||
this._file_short_path = file_short_path;
|
|
||||||
this._function = function;
|
|
||||||
this.line_number = extract_line (line);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string to_string () {
|
|
||||||
var result = line;
|
|
||||||
if (result == "")
|
|
||||||
result = " C library at address [" + address + "]";
|
|
||||||
return result + " [" + address + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Style {
|
|
||||||
RESET = 0,
|
|
||||||
BRIGHT = 1,
|
|
||||||
DIM = 2,
|
|
||||||
UNDERLINE = 3,
|
|
||||||
BLINK = 4,
|
|
||||||
REVERSE = 7,
|
|
||||||
HIDDEN = 8
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum CriticalHandler {
|
|
||||||
IGNORE,
|
|
||||||
PRINT_STACKTRACE,
|
|
||||||
CRASH
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Color {
|
|
||||||
BLACK = 0,
|
|
||||||
RED = 1,
|
|
||||||
GREEN = 2,
|
|
||||||
YELLOW = 3,
|
|
||||||
BLUE = 4,
|
|
||||||
MAGENTA = 5,
|
|
||||||
CYAN = 6,
|
|
||||||
WHITE = 7
|
|
||||||
}
|
|
||||||
|
|
||||||
public Gee.ArrayList<Frame> _frames = new Gee.ArrayList<Frame>();
|
|
||||||
|
|
||||||
private Frame first_vala = null;
|
|
||||||
|
|
||||||
private int max_file_name_length = 0;
|
|
||||||
|
|
||||||
private int max_line_number_length = 0;
|
|
||||||
|
|
||||||
private bool is_all_function_name_blank = true;
|
|
||||||
|
|
||||||
private bool is_all_file_name_blank = true;
|
|
||||||
|
|
||||||
private ProcessSignal sig;
|
|
||||||
|
|
||||||
public static bool enabled { get;set;default = true;}
|
|
||||||
|
|
||||||
public static bool hide_installed_libraries { get;set;default = false;}
|
|
||||||
|
|
||||||
public static Color default_highlight_color { get;set;default = Color.WHITE;}
|
|
||||||
|
|
||||||
public static Color default_error_background { get;set;default = Color.RED;}
|
|
||||||
|
|
||||||
public Color highlight_color { get;set;default = Color.WHITE;}
|
|
||||||
|
|
||||||
public Color error_background { get;set;default = Color.RED;}
|
|
||||||
|
|
||||||
public Gee.ArrayList<Frame> frames {
|
|
||||||
get {
|
|
||||||
return _frames;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Stacktrace (GLib.ProcessSignal sig = GLib.ProcessSignal.TTOU) {
|
|
||||||
this.sig = sig;
|
|
||||||
error_background = default_error_background;
|
|
||||||
highlight_color = default_highlight_color;
|
|
||||||
//hide_installed_libraries = true;
|
|
||||||
create_stacktrace ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string get_module_name () {
|
|
||||||
var path = new char[1024];
|
|
||||||
Posix.readlink ("/proc/self/exe", path);
|
|
||||||
string result = (string) path;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO CARL convert this piece of code to vala conventions
|
|
||||||
public static string get_relative_path (string p_fullDestinationPath, string p_startPath) {
|
|
||||||
|
|
||||||
string[] l_startPathParts = p_startPath.split ("/");
|
|
||||||
string[] l_destinationPathParts = p_fullDestinationPath.split ("/");
|
|
||||||
|
|
||||||
int l_sameCounter = 0;
|
|
||||||
while ((l_sameCounter < l_startPathParts.length) &&
|
|
||||||
(l_sameCounter < l_destinationPathParts.length) &&
|
|
||||||
l_startPathParts[l_sameCounter] == l_destinationPathParts[l_sameCounter]) {
|
|
||||||
l_sameCounter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l_sameCounter == 0) {
|
|
||||||
return p_fullDestinationPath; // There is no relative link.
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder l_builder = new StringBuilder ();
|
|
||||||
for (int i = l_sameCounter ; i < l_startPathParts.length ; i++) {
|
|
||||||
l_builder.append ("../");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = l_sameCounter ; i < l_destinationPathParts.length ; i++) {
|
|
||||||
l_builder.append (l_destinationPathParts[i] + "/");
|
|
||||||
}
|
|
||||||
|
|
||||||
// CARL l_builder.Length--;
|
|
||||||
// Remove the last /
|
|
||||||
var result = l_builder.str;
|
|
||||||
result = result.substring (0, result.length - 1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string extract_short_file_path (string file_path) {
|
|
||||||
var path = Environment.get_current_dir ();
|
|
||||||
/*var i = file_path.index_of ( path );
|
|
||||||
if( i>=0 )
|
|
||||||
return file_path.substring ( path.length, file_path.length - path.length );
|
|
||||||
return file_path; */
|
|
||||||
var result = get_relative_path (file_path, path);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool is_custom {
|
|
||||||
get {
|
|
||||||
return sig == ProcessSignal.TTOU;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// input : '/home/cran/Documents/Projects/elementary/noise/instant-beta/build/core/libnoise-core.so.0(noise_job_repository_create_job+0x309) [0x7ff60a021e69]'
|
|
||||||
// ouput: 0x309
|
|
||||||
private int extract_base_address (string line) {
|
|
||||||
int result = 0 ;
|
|
||||||
var start = line.last_index_of ("+");
|
|
||||||
if (start >= 0) {
|
|
||||||
var end = line.last_index_of (")");
|
|
||||||
if( end > start ) {
|
|
||||||
var text = line.substring (start+3,end-start-3) ;
|
|
||||||
text.scanf("%x", &result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result ;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void process_info_for_file (string full_line, string str ) {
|
|
||||||
func = "" ;
|
|
||||||
file_path = "";
|
|
||||||
short_file_path = "";
|
|
||||||
l = "";
|
|
||||||
file_line = "";
|
|
||||||
func_line = "";
|
|
||||||
|
|
||||||
var lines = full_line.split ("\n");
|
|
||||||
|
|
||||||
if (lines.length > 0)
|
|
||||||
func_line = lines[0];
|
|
||||||
|
|
||||||
if (lines.length > 1)
|
|
||||||
file_line = lines[1];
|
|
||||||
if (file_line == "??:0" || file_line == "??:?")
|
|
||||||
file_line = "";
|
|
||||||
func = extract_function_name (str);
|
|
||||||
|
|
||||||
file_path = "";
|
|
||||||
short_file_path = "";
|
|
||||||
l = "";
|
|
||||||
if (file_line != "") {
|
|
||||||
if (func == "")
|
|
||||||
func = extract_function_name_from_line (func_line);
|
|
||||||
file_path = extract_file_path (file_line);
|
|
||||||
short_file_path = extract_short_file_path (file_path);
|
|
||||||
l = extract_line (file_line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string func = "" ;
|
|
||||||
string file_path = "";
|
|
||||||
string short_file_path = "";
|
|
||||||
string l = "";
|
|
||||||
string file_line = "";
|
|
||||||
string func_line = "";
|
|
||||||
|
|
||||||
private void process_info_from_lib (string file_path, string str) {
|
|
||||||
var cmd2 = "nm %s".printf(file_path) ;
|
|
||||||
var addr1_s = execute_command_sync_get_output (cmd2) ;
|
|
||||||
MatchInfo info ;
|
|
||||||
try {
|
|
||||||
Regex regex = new Regex ("\\n[^ ]* T "+func);
|
|
||||||
|
|
||||||
if( regex.match (addr1_s, 0, out info) )
|
|
||||||
{
|
|
||||||
while( info.matches() ){
|
|
||||||
var lll = info.fetch(0) ;
|
|
||||||
//stdout.printf ( "lll '%s'\n", lll ) ;
|
|
||||||
addr1_s = lll.substring(0, lll.index_of(" ")) ;
|
|
||||||
info.next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (RegexError e)
|
|
||||||
{
|
|
||||||
critical( "Error while processing regex %s", e.message ) ;
|
|
||||||
}
|
|
||||||
//stdout.printf ("addr1_s %s\n", addr1_s) ;
|
|
||||||
int addr1 = 0 ;
|
|
||||||
addr1_s.scanf("%x", &addr1);
|
|
||||||
if( addr1 != 0 ) {
|
|
||||||
int addr2 = extract_base_address (str) ;
|
|
||||||
string addr3 = "%#08x".printf (addr1+addr2);
|
|
||||||
var new_full_line = process_line (file_path, addr3);
|
|
||||||
process_info_for_file (new_full_line, str ) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void create_stacktrace () {
|
|
||||||
int frame_count = 100;
|
|
||||||
int skipped_frames_count = 5;
|
|
||||||
// Stacktrace not due to a crash
|
|
||||||
if (is_custom)
|
|
||||||
skipped_frames_count = 3;
|
|
||||||
|
|
||||||
void *[] array = new void *[frame_count];
|
|
||||||
|
|
||||||
_frames.clear ();
|
|
||||||
first_vala = null;
|
|
||||||
max_file_name_length = 0;
|
|
||||||
is_all_function_name_blank = true;
|
|
||||||
is_all_file_name_blank = true;
|
|
||||||
|
|
||||||
#if VALA_0_26
|
|
||||||
var size = Linux.Backtrace.@get (array);
|
|
||||||
var strings = Linux.Backtrace.symbols (array);
|
|
||||||
#else
|
|
||||||
int size = Linux.backtrace (array, frame_count);
|
|
||||||
unowned string[] strings = Linux.backtrace_symbols (array, size);
|
|
||||||
// Needed because of some weird bug
|
|
||||||
strings.length = size;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int[] addresses = (int[])array;
|
|
||||||
string module = get_module_name ();
|
|
||||||
// First ones are the handler
|
|
||||||
for (int i = skipped_frames_count ; i < size ; i++) {
|
|
||||||
int address = addresses[i];
|
|
||||||
string str = strings[i];
|
|
||||||
var addr = extract_address (str);
|
|
||||||
|
|
||||||
var full_line = process_line (module, addr);
|
|
||||||
process_info_for_file( full_line, str) ;
|
|
||||||
if (file_line == "") {
|
|
||||||
file_path = extract_file_path_from (str);
|
|
||||||
|
|
||||||
}
|
|
||||||
if( file_path.has_suffix(".so.0")) {
|
|
||||||
process_info_from_lib (file_path, str) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
//stdout.printf ("Building %d \n . addr: [%s]\n . full_line: '%s'\n . file_line: '%s'\n . func_line: '%s'\n . str : '%s'\n . func: '%s'\n . file: '%s'\n . line: '%s'\n",
|
|
||||||
//i, addr, full_line, file_line, func_line, str, func, file_path, l);
|
|
||||||
|
|
||||||
if (func != "" && file_path.has_suffix (".vala") && is_all_function_name_blank)
|
|
||||||
is_all_function_name_blank = false;
|
|
||||||
|
|
||||||
if (short_file_path != "" && is_all_file_name_blank)
|
|
||||||
is_all_file_name_blank = false;
|
|
||||||
|
|
||||||
var frame = new Frame (addr, file_line, func, file_path, short_file_path);
|
|
||||||
|
|
||||||
if (first_vala == null && file_path.has_suffix (".vala"))
|
|
||||||
first_vala = frame;
|
|
||||||
|
|
||||||
if (short_file_path.length > max_file_name_length)
|
|
||||||
max_file_name_length = short_file_path.length;
|
|
||||||
if (l.length > max_line_number_length)
|
|
||||||
max_line_number_length = l.length;
|
|
||||||
_frames.add (frame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string extract_function_name (string line) {
|
|
||||||
if (line == "")
|
|
||||||
return "";
|
|
||||||
var start = line.index_of ("(");
|
|
||||||
if (start >= 0) {
|
|
||||||
var end = line.index_of ("+", start);
|
|
||||||
if (end >= 0) {
|
|
||||||
var result = line.substring (start + 1, end - start - 1);
|
|
||||||
return result.strip ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string extract_function_name_from_line (string line) {
|
|
||||||
return line.strip ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string extract_file_path_from (string str) {
|
|
||||||
if (str == "")
|
|
||||||
return "";
|
|
||||||
/*if( str.index_of("??") >= 0)
|
|
||||||
//result = result.substring (4, line.length - 4 );
|
|
||||||
stdout.printf ("ERR2?? : %s\n", str ) ; */
|
|
||||||
var start = str.index_of ("(");
|
|
||||||
if (start >= 0) {
|
|
||||||
return str.substring (0, start).strip ();
|
|
||||||
}
|
|
||||||
return str.strip ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string extract_file_path (string line) {
|
|
||||||
var result = line;
|
|
||||||
if (result == "")
|
|
||||||
return "";
|
|
||||||
if (result == "??:0??:0")
|
|
||||||
return "";
|
|
||||||
// For some reason, the file name can starts with ??:0
|
|
||||||
if (result.has_prefix ("??:0"))
|
|
||||||
result = result.substring (4, line.length - 4);
|
|
||||||
// stdout.printf ("ERR1?? : %s\n", line ) ;
|
|
||||||
var start = result.index_of (":");
|
|
||||||
if (start >= 0) {
|
|
||||||
result = result.substring (0, start);
|
|
||||||
return result.strip ();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string extract_line (string line) {
|
|
||||||
var result = line;
|
|
||||||
if (result == "")
|
|
||||||
return "";
|
|
||||||
if (result.has_prefix ("??:0"))
|
|
||||||
result = result.substring (4, line.length - 4);
|
|
||||||
var start = result.index_of (":");
|
|
||||||
if (start >= 0) {
|
|
||||||
result = result.substring (start + 1, line.length - start - 1);
|
|
||||||
var end = result.index_of ("(");
|
|
||||||
if (end >= 0) {
|
|
||||||
result = result.substring (0, end);
|
|
||||||
}
|
|
||||||
return result.strip ();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string extract_address (string line) {
|
|
||||||
if (line == "")
|
|
||||||
return "";
|
|
||||||
var start = line.index_of ("[");
|
|
||||||
if (start >= 0) {
|
|
||||||
var end = line.index_of ("]", start);
|
|
||||||
if (end >= 0) {
|
|
||||||
var result = line.substring (start + 1, end - start - 1);
|
|
||||||
return result.strip ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string execute_command_sync_get_output (string cmd) {
|
|
||||||
try {
|
|
||||||
int exitCode;
|
|
||||||
string std_out;
|
|
||||||
string std_err;
|
|
||||||
Process.spawn_command_line_sync (cmd, out std_out, out std_err, out exitCode);
|
|
||||||
return std_out;
|
|
||||||
}
|
|
||||||
catch (Error e) {
|
|
||||||
warning (@"Error while executing '$cmd': $(e.message)");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Poor's man demangler. libunwind is another dep
|
|
||||||
// TODO : Optimize this
|
|
||||||
// module : app
|
|
||||||
// address : 0x007f80
|
|
||||||
// output : /home/cran/Projects/noise/noise-perf-instant-search/tests/errors.vala:87
|
|
||||||
string process_line (string module, string address) {
|
|
||||||
var cmd = "addr2line -f -e %s %s".printf (module, address);
|
|
||||||
var result = execute_command_sync_get_output (cmd);
|
|
||||||
//stdout.printf( "CMD %s\n", cmd) ;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string get_reset_code () {
|
|
||||||
// return get_color_code (Style.RESET, Colors.WHITE, Colors.BLACK);
|
|
||||||
return "\x1b[0m";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string get_reset_style () {
|
|
||||||
return get_color_code (Style.DIM, highlight_color, background_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string get_color_code (Style attr, Color fg, Color bg = background_color) {
|
|
||||||
/* Command is the control command to the terminal */
|
|
||||||
if (bg == Color.BLACK)
|
|
||||||
return "%c[%d;%dm".printf (0x1B, (int) attr, (int) fg + 30);
|
|
||||||
else
|
|
||||||
return "%c[%d;%d;%dm".printf (0x1B, (int) attr, (int) fg + 30, (int) bg + 40);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string get_signal_name () {
|
|
||||||
return sig.to_string ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string get_highlight_code () {
|
|
||||||
return get_color_code (Style.BRIGHT, highlight_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string get_printable_function (Frame frame, int padding = 0) {
|
|
||||||
var result = "";
|
|
||||||
var is_unknown = false;
|
|
||||||
if (frame.function == "") {
|
|
||||||
result = "<unknown> " + frame.address;
|
|
||||||
is_unknown = true;
|
|
||||||
} else {
|
|
||||||
var s = "";
|
|
||||||
int count = padding - get_signal_name ().length;
|
|
||||||
if (padding != 0 && count > 0)
|
|
||||||
s = string.nfill (count, ' ');
|
|
||||||
result = "'" + frame.function + "'" + s;
|
|
||||||
}
|
|
||||||
if (is_unknown)
|
|
||||||
return result + get_reset_code ();
|
|
||||||
else
|
|
||||||
return get_highlight_code () + result + get_reset_code ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string get_printable_line_number (Frame frame, bool pad = true) {
|
|
||||||
var path = frame.line_number;
|
|
||||||
var result = "";
|
|
||||||
var color = get_highlight_code ();
|
|
||||||
if (path.length >= max_line_number_length || !pad)
|
|
||||||
result = color + path + get_reset_style ();
|
|
||||||
else {
|
|
||||||
result = color + path + get_reset_style ();
|
|
||||||
result = string.nfill (max_line_number_length - path.length, ' ') + result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string get_printable_file_short_path (Frame frame, bool pad = true) {
|
|
||||||
var path = frame.file_short_path;
|
|
||||||
var result = "";
|
|
||||||
var color = get_highlight_code ();
|
|
||||||
if (path.length >= max_file_name_length || !pad)
|
|
||||||
result = color + path + get_reset_style ();
|
|
||||||
else {
|
|
||||||
result = color + path + get_reset_style ();
|
|
||||||
result = result + string.nfill (max_file_name_length - path.length, ' ');
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Color background_color = Color.BLACK;
|
|
||||||
int title_length = 0;
|
|
||||||
|
|
||||||
private string get_printable_title () {
|
|
||||||
var c = get_color_code (Style.DIM, highlight_color, background_color);
|
|
||||||
var color = get_highlight_code ();
|
|
||||||
|
|
||||||
var result = "" ;
|
|
||||||
|
|
||||||
if( is_custom)
|
|
||||||
result = "%sA function was called in %s".printf (
|
|
||||||
c,
|
|
||||||
get_reset_style ());
|
|
||||||
else
|
|
||||||
result = "%sAn error occured %s(%s)%s".printf (
|
|
||||||
c,
|
|
||||||
color,
|
|
||||||
get_signal_name (),
|
|
||||||
get_reset_style ());
|
|
||||||
|
|
||||||
title_length = get_signal_name ().length;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string get_reason () {
|
|
||||||
// var c = get_reset_code();
|
|
||||||
var color = get_highlight_code ();
|
|
||||||
if (sig == ProcessSignal.TRAP) {
|
|
||||||
return "The reason is likely %san uncaught error%s".printf (
|
|
||||||
color, get_reset_code ());
|
|
||||||
}
|
|
||||||
if (sig == ProcessSignal.ABRT) {
|
|
||||||
return "The reason is likely %sa failed assertion (assert...)%s".printf (
|
|
||||||
color, get_reset_code ());
|
|
||||||
}
|
|
||||||
if (sig == ProcessSignal.SEGV) {
|
|
||||||
return "The reason is likely %sa null reference being used%s".printf (
|
|
||||||
color, get_reset_code ());
|
|
||||||
}
|
|
||||||
return "Unknown reason";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void print () {
|
|
||||||
stdout.printf ("\n");
|
|
||||||
background_color = error_background;
|
|
||||||
var header = "%s%s\n".printf (get_printable_title (),
|
|
||||||
get_reset_code ());
|
|
||||||
|
|
||||||
if (first_vala != null) {
|
|
||||||
header = "%s in %s, line %s in %s\n".printf (
|
|
||||||
get_printable_title (),
|
|
||||||
get_printable_file_short_path (first_vala, false),
|
|
||||||
get_printable_line_number (first_vala, false),
|
|
||||||
get_printable_function (first_vala) + get_reset_code ());
|
|
||||||
title_length += first_vala.line_number.length +
|
|
||||||
first_vala.function.length +
|
|
||||||
first_vala.file_short_path.length;
|
|
||||||
}
|
|
||||||
stdout.printf (header);
|
|
||||||
background_color = Color.BLACK;
|
|
||||||
if( !is_custom) {
|
|
||||||
var reason = get_reason ();
|
|
||||||
stdout.printf ("%s\n", reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has the user forgot to compile with -g -X -rdynamic flag ?
|
|
||||||
if (is_all_file_name_blank) {
|
|
||||||
//var advice = " %sNote%s: no file path and line numbers can be retrieved. Are you sure %syou added -g -X -rdynamic%s to valac command line?\n";
|
|
||||||
var advice = "%sNote%s: no vala function name can be retrieved.";
|
|
||||||
var color = get_highlight_code ();
|
|
||||||
stdout.printf (advice, color, get_reset_code (), color, get_reset_code ());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has the user forgot to compile with rdynamic flag ?
|
|
||||||
if (is_all_function_name_blank && !is_all_file_name_blank) {
|
|
||||||
var advice = "%sNote%s: no vala function name can be retrieved.";
|
|
||||||
//var advice = " %sNote%s: no vala function name can be retrieved. Are you sure %syou added -X -rdynamic%s to valac command line?\n";
|
|
||||||
var color = get_highlight_code ();
|
|
||||||
stdout.printf (advice, color, get_reset_code (), color, get_reset_code ());
|
|
||||||
}
|
|
||||||
|
|
||||||
stdout.printf ("\n");
|
|
||||||
int i = 1;
|
|
||||||
bool has_displayed_first_vala = false;
|
|
||||||
foreach (var frame in _frames) {
|
|
||||||
var show_frame = frame.function != "" || frame.file_path.has_suffix (".vala") || frame.file_path.has_suffix (".c");
|
|
||||||
if (hide_installed_libraries && has_displayed_first_vala)
|
|
||||||
show_frame = show_frame && frame.file_short_path != "";
|
|
||||||
|
|
||||||
// Ignore glib tracing code if displayed before the first vala frame
|
|
||||||
if ((frame.function == "g_logv" || frame.function == "g_log") && !has_displayed_first_vala)
|
|
||||||
show_frame = false;
|
|
||||||
if (show_frame) {
|
|
||||||
// #2 ./OtherModule.c line 80 in 'other_module_do_it'
|
|
||||||
// at /home/cran/Projects/noise/noise-perf-instant-search/tests/errors/module/OtherModule.vala:10
|
|
||||||
var str = " %s #%d %s line %s in %s\n";
|
|
||||||
background_color = Color.BLACK;
|
|
||||||
var lead = " ";
|
|
||||||
var function_padding = 0;
|
|
||||||
if (frame == first_vala) {
|
|
||||||
has_displayed_first_vala = true;
|
|
||||||
lead = "*";
|
|
||||||
background_color = error_background;
|
|
||||||
function_padding = 22;
|
|
||||||
}
|
|
||||||
var l_number = "";
|
|
||||||
if (frame.line_number == "") {
|
|
||||||
str = " %s #%d <unknown> %s in %s\n";
|
|
||||||
var func_name = get_printable_function (frame);
|
|
||||||
var fill_len = int.max (max_file_name_length + max_line_number_length - 1, 0);
|
|
||||||
str = str.printf (
|
|
||||||
lead,
|
|
||||||
i,
|
|
||||||
string.nfill (fill_len, ' '),
|
|
||||||
func_name);
|
|
||||||
} else {
|
|
||||||
str = str.printf (
|
|
||||||
lead,
|
|
||||||
i,
|
|
||||||
get_printable_file_short_path (frame),
|
|
||||||
get_printable_line_number (frame),
|
|
||||||
get_printable_function (frame, function_padding));
|
|
||||||
l_number = ":" + frame.line_number;
|
|
||||||
}
|
|
||||||
stdout.printf (str);
|
|
||||||
str = " at %s%s\n".printf (
|
|
||||||
frame.file_path, l_number);
|
|
||||||
stdout.printf (str);
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void register_handlers () {
|
|
||||||
Process.@signal (ProcessSignal.SEGV, handler);
|
|
||||||
Process.@signal (ProcessSignal.ABRT, handler);
|
|
||||||
Process.@signal (ProcessSignal.TRAP, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CriticalHandler critical_handling { get;set;default = CriticalHandler.PRINT_STACKTRACE;}
|
|
||||||
|
|
||||||
public static void handler (int sig) {
|
|
||||||
Stacktrace stack = new Stacktrace ((ProcessSignal) sig);
|
|
||||||
stack.print ();
|
|
||||||
if (sig != ProcessSignal.TRAP ||
|
|
||||||
(sig == ProcessSignal.TRAP && critical_handling == CriticalHandler.CRASH))
|
|
||||||
Process.exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -107,7 +107,6 @@ public class Tootle.Views.Notifications : Views.Base, IAccountListener, IStreamL
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool accepts (ref string event) {
|
public override bool accepts (ref string event) {
|
||||||
warning (event);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue