1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 09:15:07 +00:00

Profiler: Show a GUI message box with the error when profiling fails

This came up in @jonathandturner's video walking through the system
and playing with things: https://www.youtube.com/watch?v=TtV86uL5oD4

At one point, he tried profiling his Terminal app, and since the
Terminal was completely idle while profiling, no samples were captured
and there was no profile to show.

Make sure we propagate any error when loading the profile, and show it
in a GUI message box instead of stderr. :^)
This commit is contained in:
Andreas Kling 2020-12-26 10:27:57 +01:00
parent b2316701a8
commit bd47957c3a
3 changed files with 19 additions and 23 deletions

View file

@ -263,29 +263,23 @@ void Profile::rebuild_tree()
m_model->update(); m_model->update();
} }
OwnPtr<Profile> Profile::load_from_perfcore_file(const StringView& path) Result<NonnullOwnPtr<Profile>, String> Profile::load_from_perfcore_file(const StringView& path)
{ {
auto file = Core::File::construct(path); auto file = Core::File::construct(path);
if (!file->open(Core::IODevice::ReadOnly)) { if (!file->open(Core::IODevice::ReadOnly))
warnln("Unable to open {}, error: {}", path, file->error_string()); return String::formatted("Unable to open {}, error: {}", path, file->error_string());
return nullptr;
}
auto json = JsonValue::from_string(file->read_all()); auto json = JsonValue::from_string(file->read_all());
ASSERT(json.has_value()); ASSERT(json.has_value());
if (!json.value().is_object()) { if (!json.value().is_object())
warnln("Invalid perfcore format (not a JSON object)"); return String { "Invalid perfcore format (not a JSON object)" };
return nullptr;
}
auto& object = json.value().as_object(); auto& object = json.value().as_object();
auto executable_path = object.get("executable").to_string(); auto executable_path = object.get("executable").to_string();
auto coredump = CoreDumpReader::create(String::format("/tmp/profiler_coredumps/%d", object.get("pid").as_u32())); auto coredump = CoreDumpReader::create(String::formatted("/tmp/profiler_coredumps/{}", object.get("pid").as_u32()));
if (!coredump) { if (!coredump)
warnln("Could not open coredump"); return String { "Could not open coredump" };
return nullptr;
}
MappedFile kernel_elf_file("/boot/Kernel"); MappedFile kernel_elf_file("/boot/Kernel");
OwnPtr<ELF::Image> kernel_elf; OwnPtr<ELF::Image> kernel_elf;
@ -294,11 +288,11 @@ OwnPtr<Profile> Profile::load_from_perfcore_file(const StringView& path)
auto events_value = object.get("events"); auto events_value = object.get("events");
if (!events_value.is_array()) if (!events_value.is_array())
return nullptr; return String { "Malformed profile (events is not an array)" };
auto& perf_events = events_value.as_array(); auto& perf_events = events_value.as_array();
if (perf_events.is_empty()) if (perf_events.is_empty())
return nullptr; return String { "No events captured (targeted process was never on CPU)" };
Vector<Event> events; Vector<Event> events;
@ -346,7 +340,7 @@ OwnPtr<Profile> Profile::load_from_perfcore_file(const StringView& path)
events.append(move(event)); events.append(move(event));
} }
return NonnullOwnPtr<Profile>(NonnullOwnPtr<Profile>::Adopt, *new Profile(executable_path, move(events))); return adopt_own(*new Profile(executable_path, move(events)));
} }
void ProfileNode::sort_children() void ProfileNode::sort_children()

View file

@ -32,6 +32,7 @@
#include <AK/JsonValue.h> #include <AK/JsonValue.h>
#include <AK/NonnullRefPtrVector.h> #include <AK/NonnullRefPtrVector.h>
#include <AK/OwnPtr.h> #include <AK/OwnPtr.h>
#include <AK/Result.h>
#include <LibGUI/Forward.h> #include <LibGUI/Forward.h>
#include <LibGUI/ModelIndex.h> #include <LibGUI/ModelIndex.h>
@ -128,7 +129,7 @@ private:
class Profile { class Profile {
public: public:
static OwnPtr<Profile> load_from_perfcore_file(const StringView& path); static Result<NonnullOwnPtr<Profile>, String> load_from_perfcore_file(const StringView& path);
~Profile(); ~Profile();
GUI::Model& model(); GUI::Model& model();

View file

@ -71,13 +71,14 @@ int main(int argc, char** argv)
path = argv[1]; path = argv[1];
} }
auto profile = Profile::load_from_perfcore_file(path); auto profile_or_error = Profile::load_from_perfcore_file(path);
if (profile_or_error.is_error()) {
if (!profile) { GUI::MessageBox::show(nullptr, profile_or_error.error(), "Profiler", GUI::MessageBox::Type::Error);
warnln("Unable to load profile '{}'", path); return 0;
return 1;
} }
auto& profile = profile_or_error.value();
auto window = GUI::Window::construct(); auto window = GUI::Window::construct();
window->set_title("Profiler"); window->set_title("Profiler");
window->set_icon(app_icon.bitmap_for_size(16)); window->set_icon(app_icon.bitmap_for_size(16));