From 7faca4090e6933bd71a13582489f66d7e9bbb365 Mon Sep 17 00:00:00 2001 From: Bleak Grey Date: Sat, 30 May 2020 14:39:41 +0300 Subject: [PATCH] Depend on libhandy --- README.md | 1 + meson.build | 11 +- src/Application.vala | 5 +- src/Stacktrace.vala | 651 ----------------------------------- src/Views/Notifications.vala | 1 - 5 files changed, 6 insertions(+), 663 deletions(-) delete mode 100644 src/Stacktrace.vala diff --git a/README.md b/README.md index 2b732ec..e201f61 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ To build the app, make sure you have these dependencies: * libsoup2.4-dev * libgranite-dev * libjson-glib-dev +* libhandy-0.0-dev Then run `install.sh` in the project directory to install the app. diff --git a/meson.build b/meson.build index 4664b6a..180b0ef 100644 --- a/meson.build +++ b/meson.build @@ -4,10 +4,11 @@ gnome = import('gnome') i18n = import('i18n') #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([ - '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()) + '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), + '-DHANDY_USE_UNSTABLE_API', ], language: 'c', ) @@ -21,9 +22,6 @@ asresources = gnome.compile_resources( executable( meson.project_name(), asresources, - - 'src/Stacktrace.vala', #TODO: move into a separate lib - 'src/Build.vala', 'src/Application.vala', 'src/Desktop.vala', @@ -81,8 +79,7 @@ executable( dependency('granite', version: '>=5.2.0'), dependency('json-glib-1.0'), dependency('libsoup-2.4'), - - meson.get_compiler('vala').find_library('linux', required: true), #Required by Stacktrace.vala + dependency('libhandy-0.0', version: '>=0.0.13'), ], install: true, link_args: '-export-dynamic' diff --git a/src/Application.vala b/src/Application.vala index db83dc7..ad4b22d 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -63,10 +63,7 @@ namespace Tootle { public static int main (string[] args) { Gtk.init (ref args); - - Stacktrace.register_handlers (); - //assert (true == false); // I'm not crazy. It's for stacktrace testing. - + Hdy.init (ref args); try { var opt_context = new OptionContext ("- Options"); opt_context.add_main_entries (app_options, null); diff --git a/src/Stacktrace.vala b/src/Stacktrace.vala deleted file mode 100644 index adf65b1..0000000 --- a/src/Stacktrace.vala +++ /dev/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 _frames = new Gee.ArrayList(); - - 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 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 = " " + 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 %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); - } - -} - diff --git a/src/Views/Notifications.vala b/src/Views/Notifications.vala index f2b146a..2f8c115 100644 --- a/src/Views/Notifications.vala +++ b/src/Views/Notifications.vala @@ -107,7 +107,6 @@ public class Tootle.Views.Notifications : Views.Base, IAccountListener, IStreamL } public override bool accepts (ref string event) { - warning (event); return true; }