1 // 2 // Copyright (c) 2010-2022 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using System.IO; 10 using Antmicro.Renode.Utilities; 11 using Xwt; 12 using System.Text; 13 using System.Linq; 14 using System.Threading; 15 16 namespace Antmicro.Renode.UI 17 { 18 public class CrashHandler 19 { HandleCrash(Exception e)20 public static void HandleCrash(Exception e) 21 { 22 var message = GetFullStackTrace(e); 23 SaveErrorToFile(TemporaryFilesManager.Instance.EmulatorTemporaryPath + TemporaryFilesManager.CrashSuffix, message); 24 ShowErrorInConsole(message); 25 try 26 { 27 ApplicationExtensions.InvokeInUIThreadAndWait(() => ShowErrorWindow(message)); 28 } 29 catch(Exception) 30 { 31 // there is nothing to do here 32 } 33 } 34 ShowErrorWindow(string message)35 private static void ShowErrorWindow(string message) 36 { 37 var dialog = new Dialog(); 38 dialog.Title = "Fatal error"; 39 var markdown = new MarkdownView(); 40 markdown.Markdown = message.Split(new [] { '\n' }).Select(x => "\t" + x).Aggregate((x, y) => x + "\n" + y); 41 42 var copyButton = new Button("Copy to clipboard"); 43 copyButton.Clicked += (sender, ev) => Clipboard.SetText(message); 44 45 var box = new VBox(); 46 47 box.PackStart(new Label("Got unhandled exception") { Font = global::Xwt.Drawing.Font.SystemFont.WithSize(15).WithWeight(Xwt.Drawing.FontWeight.Bold) }); 48 box.PackStart(new ScrollView(markdown), true, true); 49 box.PackStart(copyButton); 50 51 dialog.Content = box; 52 53 dialog.Buttons.Add(new DialogButton(Command.Ok)); 54 dialog.Width = 350; 55 dialog.Height = 300; 56 57 dialog.Run(); 58 dialog.Dispose(); 59 } 60 SaveErrorToFile(string location, string message)61 private static void SaveErrorToFile(string location, string message) 62 { 63 Directory.CreateDirectory(location); 64 var filename = CustomDateTime.Now.ToString("yyyyMMddHHmmssfff"); 65 File.AppendAllText(Path.Combine(location, filename), message); 66 } 67 ShowErrorInConsole(string message)68 private static void ShowErrorInConsole(string message) 69 { 70 Console.ForegroundColor = ConsoleColor.Red; 71 Console.Error.WriteLine("Fatal error:"); 72 Console.Error.WriteLine(message); 73 Console.ResetColor(); 74 } 75 GetFullStackTrace(Exception e)76 private static string GetFullStackTrace(Exception e) 77 { 78 var result = new StringBuilder(); 79 var current = e; 80 while(current != null) 81 { 82 result.AppendLine(current.Message); 83 result.AppendLine(current.StackTrace); 84 current = current.InnerException; 85 if(current != null) 86 { 87 result.AppendLine("Inner exception:"); 88 } 89 } 90 return result.ToString(); 91 } 92 } 93 } 94 95