mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 22:02:44 +00:00 
			
		
		
		
	CrashReporter: Port to LibMain and use TRY() while building the UI :^)
This commit is contained in:
		
							parent
							
								
									2511da1f57
								
							
						
					
					
						commit
						01228bf4ef
					
				
					 2 changed files with 75 additions and 101 deletions
				
			
		|  | @ -13,4 +13,4 @@ set(SOURCES | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| serenity_app(CrashReporter ICON app-crash-reporter) | serenity_app(CrashReporter ICON app-crash-reporter) | ||||||
| target_link_libraries(CrashReporter LibCore LibCoredump LibDesktop LibGUI) | target_link_libraries(CrashReporter LibCore LibCoredump LibDesktop LibGUI LibMain) | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ | ||||||
| #include <LibC/spawn.h> | #include <LibC/spawn.h> | ||||||
| #include <LibCore/ArgsParser.h> | #include <LibCore/ArgsParser.h> | ||||||
| #include <LibCore/File.h> | #include <LibCore/File.h> | ||||||
|  | #include <LibCore/System.h> | ||||||
| #include <LibCoredump/Backtrace.h> | #include <LibCoredump/Backtrace.h> | ||||||
| #include <LibCoredump/Reader.h> | #include <LibCoredump/Reader.h> | ||||||
| #include <LibDesktop/AppFile.h> | #include <LibDesktop/AppFile.h> | ||||||
|  | @ -32,6 +33,7 @@ | ||||||
| #include <LibGUI/TextEditor.h> | #include <LibGUI/TextEditor.h> | ||||||
| #include <LibGUI/Widget.h> | #include <LibGUI/Widget.h> | ||||||
| #include <LibGUI/Window.h> | #include <LibGUI/Window.h> | ||||||
|  | #include <LibMain/Main.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| 
 | 
 | ||||||
|  | @ -164,14 +166,11 @@ static void unlink_coredump(StringView const& coredump_path) | ||||||
|         dbgln("Failed deleting coredump file"); |         dbgln("Failed deleting coredump file"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int main(int argc, char** argv) | ErrorOr<int> serenity_main(Main::Arguments arguments) | ||||||
| { | { | ||||||
|     if (pledge("stdio recvfd sendfd cpath rpath unix proc exec", nullptr) < 0) { |     TRY(Core::System::pledge("stdio recvfd sendfd cpath rpath unix proc exec")); | ||||||
|         perror("pledge"); |  | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     auto app = GUI::Application::construct(argc, argv); |     auto app = TRY(GUI::Application::try_create(arguments)); | ||||||
| 
 | 
 | ||||||
|     const char* coredump_path = nullptr; |     const char* coredump_path = nullptr; | ||||||
|     bool unlink_on_exit = false; |     bool unlink_on_exit = false; | ||||||
|  | @ -180,13 +179,13 @@ int main(int argc, char** argv) | ||||||
|     args_parser.set_general_help("Show information from an application crash coredump."); |     args_parser.set_general_help("Show information from an application crash coredump."); | ||||||
|     args_parser.add_positional_argument(coredump_path, "Coredump path", "coredump-path"); |     args_parser.add_positional_argument(coredump_path, "Coredump path", "coredump-path"); | ||||||
|     args_parser.add_option(unlink_on_exit, "Delete the coredump after its parsed", "unlink", 0); |     args_parser.add_option(unlink_on_exit, "Delete the coredump after its parsed", "unlink", 0); | ||||||
|     args_parser.parse(argc, argv); |     args_parser.parse(arguments); | ||||||
| 
 | 
 | ||||||
|     Vector<TitleAndText> thread_backtraces; |     Vector<TitleAndText> thread_backtraces; | ||||||
|     Vector<TitleAndText> thread_cpu_registers; |     Vector<TitleAndText> thread_cpu_registers; | ||||||
| 
 | 
 | ||||||
|     String executable_path; |     String executable_path; | ||||||
|     Vector<String> arguments; |     Vector<String> crashed_process_arguments; | ||||||
|     Vector<String> environment; |     Vector<String> environment; | ||||||
|     Vector<String> memory_regions; |     Vector<String> memory_regions; | ||||||
|     int pid { 0 }; |     int pid { 0 }; | ||||||
|  | @ -213,52 +212,27 @@ int main(int argc, char** argv) | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         executable_path = coredump->process_executable_path(); |         executable_path = coredump->process_executable_path(); | ||||||
|         arguments = coredump->process_arguments(); |         crashed_process_arguments = coredump->process_arguments(); | ||||||
|         environment = coredump->process_environment(); |         environment = coredump->process_environment(); | ||||||
|         pid = coredump->process_pid(); |         pid = coredump->process_pid(); | ||||||
|         termination_signal = coredump->process_termination_signal(); |         termination_signal = coredump->process_termination_signal(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (pledge("stdio recvfd sendfd rpath unix cpath proc exec", nullptr) < 0) { |     TRY(Core::System::pledge("stdio recvfd sendfd rpath unix cpath proc exec")); | ||||||
|         perror("pledge"); |  | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (unveil(executable_path.characters(), "r") < 0) { |     TRY(Core::System::unveil(executable_path.characters(), "r")); | ||||||
|         perror("unveil"); |     TRY(Core::System::unveil("/res", "r")); | ||||||
|         return 1; |     TRY(Core::System::unveil("/tmp/portal/launch", "rw")); | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (unveil("/res", "r") < 0) { |     if (unlink_on_exit) | ||||||
|         perror("unveil"); |         TRY(Core::System::unveil(coredump_path, "c")); | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (unveil("/tmp/portal/launch", "rw") < 0) { |     TRY(Core::System::unveil("/bin/HackStudio", "rx")); | ||||||
|         perror("unveil"); |     TRY(Core::System::unveil(nullptr, nullptr)); | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (unlink_on_exit) { |  | ||||||
|         if (unveil(coredump_path, "c") < 0) { |  | ||||||
|             perror("unveil"); |  | ||||||
|             return 1; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (unveil("/bin/HackStudio", "rx") < 0) { |  | ||||||
|         perror("unveil"); |  | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (unveil(nullptr, nullptr) < 0) { |  | ||||||
|         perror("unveil"); |  | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     auto app_icon = GUI::Icon::default_icon("app-crash-reporter"); |     auto app_icon = GUI::Icon::default_icon("app-crash-reporter"); | ||||||
| 
 | 
 | ||||||
|     auto window = GUI::Window::construct(); |     auto window = TRY(GUI::Window::try_create()); | ||||||
|     window->set_title("Crash Reporter"); |     window->set_title("Crash Reporter"); | ||||||
|     window->set_icon(app_icon.bitmap_for_size(16)); |     window->set_icon(app_icon.bitmap_for_size(16)); | ||||||
|     window->resize(460, 340); |     window->resize(460, 340); | ||||||
|  | @ -268,10 +242,10 @@ int main(int argc, char** argv) | ||||||
|             unlink_coredump(coredump_path); |             unlink_coredump(coredump_path); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     auto& widget = window->set_main_widget<GUI::Widget>(); |     auto widget = TRY(window->try_set_main_widget<GUI::Widget>()); | ||||||
|     widget.load_from_gml(crash_reporter_window_gml); |     widget->load_from_gml(crash_reporter_window_gml); | ||||||
| 
 | 
 | ||||||
|     auto& icon_image_widget = *widget.find_descendant_of_type_named<GUI::ImageWidget>("icon"); |     auto& icon_image_widget = *widget->find_descendant_of_type_named<GUI::ImageWidget>("icon"); | ||||||
|     icon_image_widget.set_bitmap(GUI::FileIconProvider::icon_for_executable(executable_path).bitmap_for_size(32)); |     icon_image_widget.set_bitmap(GUI::FileIconProvider::icon_for_executable(executable_path).bitmap_for_size(32)); | ||||||
| 
 | 
 | ||||||
|     auto app_name = LexicalPath::basename(executable_path); |     auto app_name = LexicalPath::basename(executable_path); | ||||||
|  | @ -279,96 +253,96 @@ int main(int argc, char** argv) | ||||||
|     if (af->is_valid()) |     if (af->is_valid()) | ||||||
|         app_name = af->name(); |         app_name = af->name(); | ||||||
| 
 | 
 | ||||||
|     auto& description_label = *widget.find_descendant_of_type_named<GUI::Label>("description"); |     auto& description_label = *widget->find_descendant_of_type_named<GUI::Label>("description"); | ||||||
|     description_label.set_text(String::formatted("\"{}\" (PID {}) has crashed - {} (signal {})", app_name, pid, strsignal(termination_signal), termination_signal)); |     description_label.set_text(String::formatted("\"{}\" (PID {}) has crashed - {} (signal {})", app_name, pid, strsignal(termination_signal), termination_signal)); | ||||||
| 
 | 
 | ||||||
|     auto& executable_link_label = *widget.find_descendant_of_type_named<GUI::LinkLabel>("executable_link"); |     auto& executable_link_label = *widget->find_descendant_of_type_named<GUI::LinkLabel>("executable_link"); | ||||||
|     executable_link_label.set_text(LexicalPath::canonicalized_path(executable_path)); |     executable_link_label.set_text(LexicalPath::canonicalized_path(executable_path)); | ||||||
|     executable_link_label.on_click = [&] { |     executable_link_label.on_click = [&] { | ||||||
|         LexicalPath path { executable_path }; |         LexicalPath path { executable_path }; | ||||||
|         Desktop::Launcher::open(URL::create_with_file_protocol(path.dirname(), path.basename())); |         Desktop::Launcher::open(URL::create_with_file_protocol(path.dirname(), path.basename())); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     auto& coredump_link_label = *widget.find_descendant_of_type_named<GUI::LinkLabel>("coredump_link"); |     auto& coredump_link_label = *widget->find_descendant_of_type_named<GUI::LinkLabel>("coredump_link"); | ||||||
|     coredump_link_label.set_text(LexicalPath::canonicalized_path(coredump_path)); |     coredump_link_label.set_text(LexicalPath::canonicalized_path(coredump_path)); | ||||||
|     coredump_link_label.on_click = [&] { |     coredump_link_label.on_click = [&] { | ||||||
|         LexicalPath path { coredump_path }; |         LexicalPath path { coredump_path }; | ||||||
|         Desktop::Launcher::open(URL::create_with_file_protocol(path.dirname(), path.basename())); |         Desktop::Launcher::open(URL::create_with_file_protocol(path.dirname(), path.basename())); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     auto& arguments_label = *widget.find_descendant_of_type_named<GUI::Label>("arguments_label"); |     auto& arguments_label = *widget->find_descendant_of_type_named<GUI::Label>("arguments_label"); | ||||||
|     arguments_label.set_text(String::join(" ", arguments)); |     arguments_label.set_text(String::join(" ", crashed_process_arguments)); | ||||||
| 
 | 
 | ||||||
|     auto& tab_widget = *widget.find_descendant_of_type_named<GUI::TabWidget>("tab_widget"); |     auto& tab_widget = *widget->find_descendant_of_type_named<GUI::TabWidget>("tab_widget"); | ||||||
| 
 | 
 | ||||||
|     auto& backtrace_tab = tab_widget.add_tab<GUI::Widget>("Backtrace"); |     auto backtrace_tab = TRY(tab_widget.try_add_tab<GUI::Widget>("Backtrace")); | ||||||
|     backtrace_tab.set_layout<GUI::VerticalBoxLayout>(); |     TRY(backtrace_tab->try_set_layout<GUI::VerticalBoxLayout>()); | ||||||
|     backtrace_tab.layout()->set_margins(4); |     backtrace_tab->layout()->set_margins(4); | ||||||
| 
 | 
 | ||||||
|     auto& backtrace_label = backtrace_tab.add<GUI::Label>("A backtrace for each thread alive during the crash is listed below:"); |     auto backtrace_label = TRY(backtrace_tab->try_add<GUI::Label>("A backtrace for each thread alive during the crash is listed below:")); | ||||||
|     backtrace_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); |     backtrace_label->set_text_alignment(Gfx::TextAlignment::CenterLeft); | ||||||
|     backtrace_label.set_fixed_height(16); |     backtrace_label->set_fixed_height(16); | ||||||
| 
 | 
 | ||||||
|     auto& backtrace_tab_widget = backtrace_tab.add<GUI::TabWidget>(); |     auto backtrace_tab_widget = TRY(backtrace_tab->try_add<GUI::TabWidget>()); | ||||||
|     backtrace_tab_widget.set_tab_position(GUI::TabWidget::TabPosition::Bottom); |     backtrace_tab_widget->set_tab_position(GUI::TabWidget::TabPosition::Bottom); | ||||||
|     for (auto& backtrace : thread_backtraces) { |     for (auto& backtrace : thread_backtraces) { | ||||||
|         auto& container = backtrace_tab_widget.add_tab<GUI::Widget>(backtrace.title); |         auto container = TRY(backtrace_tab_widget->try_add_tab<GUI::Widget>(backtrace.title)); | ||||||
|         container.set_layout<GUI::VerticalBoxLayout>(); |         TRY(container->try_set_layout<GUI::VerticalBoxLayout>()); | ||||||
|         container.layout()->set_margins(4); |         container->layout()->set_margins(4); | ||||||
|         auto& backtrace_text_editor = container.add<GUI::TextEditor>(); |         auto backtrace_text_editor = TRY(container->try_add<GUI::TextEditor>()); | ||||||
|         backtrace_text_editor.set_text(backtrace.text); |         backtrace_text_editor->set_text(backtrace.text); | ||||||
|         backtrace_text_editor.set_mode(GUI::TextEditor::Mode::ReadOnly); |         backtrace_text_editor->set_mode(GUI::TextEditor::Mode::ReadOnly); | ||||||
|         backtrace_text_editor.set_should_hide_unnecessary_scrollbars(true); |         backtrace_text_editor->set_should_hide_unnecessary_scrollbars(true); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto& cpu_registers_tab = tab_widget.add_tab<GUI::Widget>("CPU Registers"); |     auto cpu_registers_tab = TRY(tab_widget.try_add_tab<GUI::Widget>("CPU Registers")); | ||||||
|     cpu_registers_tab.set_layout<GUI::VerticalBoxLayout>(); |     cpu_registers_tab->set_layout<GUI::VerticalBoxLayout>(); | ||||||
|     cpu_registers_tab.layout()->set_margins(4); |     cpu_registers_tab->layout()->set_margins(4); | ||||||
| 
 | 
 | ||||||
|     auto& cpu_registers_label = cpu_registers_tab.add<GUI::Label>("The CPU register state for each thread alive during the crash is listed below:"); |     auto cpu_registers_label = TRY(cpu_registers_tab->try_add<GUI::Label>("The CPU register state for each thread alive during the crash is listed below:")); | ||||||
|     cpu_registers_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); |     cpu_registers_label->set_text_alignment(Gfx::TextAlignment::CenterLeft); | ||||||
|     cpu_registers_label.set_fixed_height(16); |     cpu_registers_label->set_fixed_height(16); | ||||||
| 
 | 
 | ||||||
|     auto& cpu_registers_tab_widget = cpu_registers_tab.add<GUI::TabWidget>(); |     auto cpu_registers_tab_widget = TRY(cpu_registers_tab->try_add<GUI::TabWidget>()); | ||||||
|     cpu_registers_tab_widget.set_tab_position(GUI::TabWidget::TabPosition::Bottom); |     cpu_registers_tab_widget->set_tab_position(GUI::TabWidget::TabPosition::Bottom); | ||||||
|     for (auto& cpu_registers : thread_cpu_registers) { |     for (auto& cpu_registers : thread_cpu_registers) { | ||||||
|         auto& container = cpu_registers_tab_widget.add_tab<GUI::Widget>(cpu_registers.title); |         auto container = TRY(cpu_registers_tab_widget->try_add_tab<GUI::Widget>(cpu_registers.title)); | ||||||
|         container.set_layout<GUI::VerticalBoxLayout>(); |         TRY(container->try_set_layout<GUI::VerticalBoxLayout>()); | ||||||
|         container.layout()->set_margins(4); |         container->layout()->set_margins(4); | ||||||
|         auto& cpu_registers_text_editor = container.add<GUI::TextEditor>(); |         auto cpu_registers_text_editor = TRY(container->try_add<GUI::TextEditor>()); | ||||||
|         cpu_registers_text_editor.set_text(cpu_registers.text); |         cpu_registers_text_editor->set_text(cpu_registers.text); | ||||||
|         cpu_registers_text_editor.set_mode(GUI::TextEditor::Mode::ReadOnly); |         cpu_registers_text_editor->set_mode(GUI::TextEditor::Mode::ReadOnly); | ||||||
|         cpu_registers_text_editor.set_should_hide_unnecessary_scrollbars(true); |         cpu_registers_text_editor->set_should_hide_unnecessary_scrollbars(true); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto& environment_tab = tab_widget.add_tab<GUI::Widget>("Environment"); |     auto environment_tab = TRY(tab_widget.try_add_tab<GUI::Widget>("Environment")); | ||||||
|     environment_tab.set_layout<GUI::VerticalBoxLayout>(); |     TRY(environment_tab->try_set_layout<GUI::VerticalBoxLayout>()); | ||||||
|     environment_tab.layout()->set_margins(4); |     environment_tab->layout()->set_margins(4); | ||||||
| 
 | 
 | ||||||
|     auto& environment_text_editor = environment_tab.add<GUI::TextEditor>(); |     auto environment_text_editor = TRY(environment_tab->try_add<GUI::TextEditor>()); | ||||||
|     environment_text_editor.set_text(String::join("\n", environment)); |     environment_text_editor->set_text(String::join("\n", environment)); | ||||||
|     environment_text_editor.set_mode(GUI::TextEditor::Mode::ReadOnly); |     environment_text_editor->set_mode(GUI::TextEditor::Mode::ReadOnly); | ||||||
|     environment_text_editor.set_should_hide_unnecessary_scrollbars(true); |     environment_text_editor->set_should_hide_unnecessary_scrollbars(true); | ||||||
| 
 | 
 | ||||||
|     auto& memory_regions_tab = tab_widget.add_tab<GUI::Widget>("Memory Regions"); |     auto memory_regions_tab = TRY(tab_widget.try_add_tab<GUI::Widget>("Memory Regions")); | ||||||
|     memory_regions_tab.set_layout<GUI::VerticalBoxLayout>(); |     TRY(memory_regions_tab->try_set_layout<GUI::VerticalBoxLayout>()); | ||||||
|     memory_regions_tab.layout()->set_margins(4); |     memory_regions_tab->layout()->set_margins(4); | ||||||
| 
 | 
 | ||||||
|     auto& memory_regions_text_editor = memory_regions_tab.add<GUI::TextEditor>(); |     auto memory_regions_text_editor = TRY(memory_regions_tab->try_add<GUI::TextEditor>()); | ||||||
|     memory_regions_text_editor.set_text(String::join("\n", memory_regions)); |     memory_regions_text_editor->set_text(String::join("\n", memory_regions)); | ||||||
|     memory_regions_text_editor.set_mode(GUI::TextEditor::Mode::ReadOnly); |     memory_regions_text_editor->set_mode(GUI::TextEditor::Mode::ReadOnly); | ||||||
|     memory_regions_text_editor.set_should_hide_unnecessary_scrollbars(true); |     memory_regions_text_editor->set_should_hide_unnecessary_scrollbars(true); | ||||||
|     memory_regions_text_editor.set_visualize_trailing_whitespace(false); |     memory_regions_text_editor->set_visualize_trailing_whitespace(false); | ||||||
| 
 | 
 | ||||||
|     auto& close_button = *widget.find_descendant_of_type_named<GUI::Button>("close_button"); |     auto& close_button = *widget->find_descendant_of_type_named<GUI::Button>("close_button"); | ||||||
|     close_button.on_click = [&](auto) { |     close_button.on_click = [&](auto) { | ||||||
|         if (unlink_on_exit) |         if (unlink_on_exit) | ||||||
|             unlink_coredump(coredump_path); |             unlink_coredump(coredump_path); | ||||||
|         app->quit(); |         app->quit(); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     auto& debug_button = *widget.find_descendant_of_type_named<GUI::Button>("debug_button"); |     auto& debug_button = *widget->find_descendant_of_type_named<GUI::Button>("debug_button"); | ||||||
|     debug_button.set_icon(MUST(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/app-hack-studio.png"))); |     debug_button.set_icon(TRY(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/app-hack-studio.png"))); | ||||||
|     debug_button.on_click = [&](int) { |     debug_button.on_click = [&](int) { | ||||||
|         pid_t child; |         pid_t child; | ||||||
|         const char* argv[4] = { "HackStudio", "-c", coredump_path, nullptr }; |         const char* argv[4] = { "HackStudio", "-c", coredump_path, nullptr }; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling