summaryrefslogtreecommitdiff
path: root/MenuApplets
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2020-09-18 20:05:56 -0600
committerAndreas Kling <kling@serenityos.org>2021-01-03 22:12:19 +0100
commit754bf22da72bfdf160549713655acde26bee580c (patch)
treec468799b2685af4b74813bd0a0370d1ac0a2fe62 /MenuApplets
parentf98ca35b83d521377d4bce5927fdcb4a764ac02e (diff)
downloadserenity-754bf22da72bfdf160549713655acde26bee580c.zip
ResourceGraph: Handle low memory situations bit better
Rather than crashing with an ASSERT, when we can't read from /proc we draw the graph with red instead. This also alerts the user that memory is very low.
Diffstat (limited to 'MenuApplets')
-rw-r--r--MenuApplets/ResourceGraph/main.cpp71
1 files changed, 48 insertions, 23 deletions
diff --git a/MenuApplets/ResourceGraph/main.cpp b/MenuApplets/ResourceGraph/main.cpp
index 38d47a3bb1..f829dedeb6 100644
--- a/MenuApplets/ResourceGraph/main.cpp
+++ b/MenuApplets/ResourceGraph/main.cpp
@@ -51,11 +51,12 @@ class GraphWidget final : public GUI::Frame {
public:
static constexpr size_t history_size = 30;
- GraphWidget(GraphType graph_type, Optional<Gfx::Color> graph_color)
+ GraphWidget(GraphType graph_type, Optional<Gfx::Color> graph_color, Optional<Gfx::Color> graph_error_color)
: m_graph_type(graph_type)
{
set_frame_thickness(1);
m_graph_color = graph_color.value_or(palette().menu_selection());
+ m_graph_error_color = graph_error_color.value_or(Color::Red);
start_timer(1000);
}
@@ -66,24 +67,32 @@ private:
case GraphType::CPU: {
unsigned busy;
unsigned idle;
- get_cpu_usage(busy, idle);
- unsigned busy_diff = busy - m_last_cpu_busy;
- unsigned idle_diff = idle - m_last_cpu_idle;
- m_last_cpu_busy = busy;
- m_last_cpu_idle = idle;
- float cpu = (float)busy_diff / (float)(busy_diff + idle_diff);
- m_history.enqueue(cpu);
- m_tooltip = String::format("CPU usage: %.1f%%", 100 * cpu);
+ if (get_cpu_usage(busy, idle)) {
+ unsigned busy_diff = busy - m_last_cpu_busy;
+ unsigned idle_diff = idle - m_last_cpu_idle;
+ m_last_cpu_busy = busy;
+ m_last_cpu_idle = idle;
+ float cpu = (float)busy_diff / (float)(busy_diff + idle_diff);
+ m_history.enqueue(cpu);
+ m_tooltip = String::format("CPU usage: %.1f%%", 100 * cpu);
+ } else {
+ m_history.enqueue(-1);
+ m_tooltip = StringView("Unable to determine CPU usage");
+ }
break;
}
case GraphType::Memory: {
unsigned allocated;
unsigned available;
- get_memory_usage(allocated, available);
- float total_memory = allocated + available;
- float memory = (float)allocated / total_memory;
- m_history.enqueue(memory);
- m_tooltip = String::format("Memory: %.1f MiB of %.1f MiB in use", (float)allocated / MiB, total_memory / MiB);
+ if (get_memory_usage(allocated, available)) {
+ float total_memory = allocated + available;
+ float memory = (float)allocated / total_memory;
+ m_history.enqueue(memory);
+ m_tooltip = String::format("Memory: %.1f MiB of %.1f MiB in use", (float)allocated / MiB, total_memory / MiB);
+ } else {
+ m_history.enqueue(-1);
+ m_tooltip = StringView("Unable to determine memory usage");
+ }
break;
}
default:
@@ -103,10 +112,17 @@ private:
int i = m_history.capacity() - m_history.size();
auto rect = frame_inner_rect();
for (auto value : m_history) {
- painter.draw_line(
- { rect.x() + i, rect.bottom() },
- { rect.x() + i, rect.top() + (int)(round(rect.height() - (value * rect.height()))) },
- m_graph_color);
+ if (value >= 0) {
+ painter.draw_line(
+ { rect.x() + i, rect.bottom() },
+ { rect.x() + i, rect.top() + (int)(round(rect.height() - (value * rect.height()))) },
+ m_graph_color);
+ } else {
+ painter.draw_line(
+ { rect.x() + i, rect.top() },
+ { rect.x() + i, rect.bottom() },
+ m_graph_error_color);
+ }
++i;
}
}
@@ -125,12 +141,14 @@ private:
}
}
- static void get_cpu_usage(unsigned& busy, unsigned& idle)
+ static bool get_cpu_usage(unsigned& busy, unsigned& idle)
{
busy = 0;
idle = 0;
auto all_processes = Core::ProcessStatisticsReader::get_all();
+ if (all_processes.is_empty())
+ return false;
for (auto& it : all_processes) {
for (auto& jt : it.value.threads) {
@@ -140,13 +158,14 @@ private:
busy += jt.ticks_user + jt.ticks_kernel;
}
}
+ return true;
}
- static void get_memory_usage(unsigned& allocated, unsigned& available)
+ static bool get_memory_usage(unsigned& allocated, unsigned& available)
{
auto proc_memstat = Core::File::construct("/proc/memstat");
if (!proc_memstat->open(Core::IODevice::OpenMode::ReadOnly))
- ASSERT_NOT_REACHED();
+ return false;
auto file_contents = proc_memstat->read_all();
auto json = JsonValue::from_string(file_contents);
@@ -155,10 +174,12 @@ private:
unsigned user_physical_available = json.value().as_object().get("user_physical_available").to_u32();
allocated = (user_physical_allocated * PAGE_SIZE);
available = (user_physical_available * PAGE_SIZE);
+ return true;
}
GraphType m_graph_type;
Gfx::Color m_graph_color;
+ Gfx::Color m_graph_error_color;
CircularQueue<float, history_size> m_history;
unsigned m_last_cpu_busy { 0 };
unsigned m_last_cpu_idle { 0 };
@@ -183,11 +204,13 @@ int main(int argc, char** argv)
bool memory = false;
const char* name = nullptr;
const char* color = nullptr;
+ const char* error_color = nullptr;
Core::ArgsParser args_parser;
args_parser.add_option(cpu, "Show CPU usage", "cpu", 'C');
args_parser.add_option(memory, "Show memory usage", "memory", 'M');
args_parser.add_option(name, "Applet name used by WindowServer.ini to set the applet order", "name", 'n', "name");
args_parser.add_option(color, "Graph color", "color", 'c', "color");
+ args_parser.add_option(error_color, "Graph color (error)", "error-color", 'e', "error-color");
args_parser.parse(argc, argv);
if (!cpu && !memory) {
@@ -207,16 +230,18 @@ int main(int argc, char** argv)
if (name == nullptr)
name = "ResourceGraph";
- Optional<Gfx::Color> graph_color;
+ Optional<Gfx::Color> graph_color, graph_error_color;
if (color != nullptr)
graph_color = Gfx::Color::from_string(color);
+ if (error_color != nullptr)
+ graph_error_color = Gfx::Color::from_string(error_color);
auto window = GUI::Window::construct();
window->set_title(name);
window->set_window_type(GUI::WindowType::MenuApplet);
window->resize(GraphWidget::history_size + 2, 16);
- window->set_main_widget<GraphWidget>(graph_type, graph_color);
+ window->set_main_widget<GraphWidget>(graph_type, graph_color, graph_error_color);
window->show();
if (unveil("/res", "r") < 0) {