summaryrefslogtreecommitdiff
path: root/Applications
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-08-03 08:26:04 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-08-03 08:26:45 +0200
commit8a703c007647ece356f7e6b02757fbb19791d4d8 (patch)
tree5fb441b74d37533fdd14b8b1688d8cd09d1961cc /Applications
parent45c5a91afcff90fa156977bc3238ba3252a6f169 (diff)
downloadserenity-8a703c007647ece356f7e6b02757fbb19791d4d8.zip
ProcessManager: Add a new per-proces "open files" view showing open FDs
This uses the data from /proc/PID/fds with ease now that it's JSON. :^)
Diffstat (limited to 'Applications')
-rw-r--r--Applications/ProcessManager/Makefile2
-rw-r--r--Applications/ProcessManager/ProcessFileDescriptorMapModel.cpp74
-rw-r--r--Applications/ProcessManager/ProcessFileDescriptorMapModel.h29
-rw-r--r--Applications/ProcessManager/ProcessFileDescriptorMapWidget.cpp25
-rw-r--r--Applications/ProcessManager/ProcessFileDescriptorMapWidget.h18
-rw-r--r--Applications/ProcessManager/main.cpp5
6 files changed, 153 insertions, 0 deletions
diff --git a/Applications/ProcessManager/Makefile b/Applications/ProcessManager/Makefile
index a67af7d942..56a75d48eb 100644
--- a/Applications/ProcessManager/Makefile
+++ b/Applications/ProcessManager/Makefile
@@ -8,6 +8,8 @@ OBJS = \
ProcessStacksWidget.o \
ProcessMemoryMapWidget.o \
ProcessMemoryMapModel.o \
+ ProcessFileDescriptorMapWidget.o \
+ ProcessFileDescriptorMapModel.o \
main.o
APP = ProcessManager
diff --git a/Applications/ProcessManager/ProcessFileDescriptorMapModel.cpp b/Applications/ProcessManager/ProcessFileDescriptorMapModel.cpp
new file mode 100644
index 0000000000..512d1474dd
--- /dev/null
+++ b/Applications/ProcessManager/ProcessFileDescriptorMapModel.cpp
@@ -0,0 +1,74 @@
+#include "ProcessFileDescriptorMapModel.h"
+#include <AK/JsonObject.h>
+#include <AK/StringBuilder.h>
+#include <LibCore/CFile.h>
+
+void ProcessFileDescriptorMapModel::update()
+{
+ CFile file(String::format("/proc/%d/fds", m_pid));
+ if (!file.open(CIODevice::ReadOnly)) {
+ dbg() << "Unable to open " << file.filename();
+ return;
+ }
+
+ auto json = JsonValue::from_string(file.read_all());
+
+ ASSERT(json.is_array());
+ m_process_fds = json.as_array();
+
+ did_update();
+}
+
+int ProcessFileDescriptorMapModel::row_count(const GModelIndex&) const
+{
+ return m_process_fds.size();
+}
+
+String ProcessFileDescriptorMapModel::column_name(int column) const
+{
+ switch (column) {
+ case Column::FileDescriptor:
+ return "FD";
+ case Column::Path:
+ return "Path";
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
+GModel::ColumnMetadata ProcessFileDescriptorMapModel::column_metadata(int column) const
+{
+ switch (column) {
+ case Column::FileDescriptor:
+ return { 32, TextAlignment::CenterRight };
+ case Column::Path:
+ return { 300, TextAlignment::CenterLeft };
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ return {};
+}
+
+GVariant ProcessFileDescriptorMapModel::data(const GModelIndex& index, Role role) const
+{
+ auto& fd_object = m_process_fds.at(index.row()).as_object();
+ if (role == GModel::Role::Display) {
+ switch (index.column()) {
+ case Column::FileDescriptor:
+ return fd_object.get("fd").to_int();
+ case Column::Path:
+ return fd_object.get("absolute_path").to_string();
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+ return {};
+}
+
+void ProcessFileDescriptorMapModel::set_pid(pid_t pid)
+{
+ if (m_pid == pid)
+ return;
+ m_pid = pid;
+ update();
+}
diff --git a/Applications/ProcessManager/ProcessFileDescriptorMapModel.h b/Applications/ProcessManager/ProcessFileDescriptorMapModel.h
new file mode 100644
index 0000000000..b9386df903
--- /dev/null
+++ b/Applications/ProcessManager/ProcessFileDescriptorMapModel.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <AK/JsonArray.h>
+#include <LibGUI/GModel.h>
+
+class ProcessFileDescriptorMapModel final : public GModel {
+public:
+ enum Column {
+ FileDescriptor,
+ Path,
+ __Count
+ };
+
+ ProcessFileDescriptorMapModel() {}
+ virtual ~ProcessFileDescriptorMapModel() override {}
+
+ virtual int row_count(const GModelIndex& = GModelIndex()) const override;
+ virtual int column_count(const GModelIndex& = GModelIndex()) const override { return Column::__Count; }
+ virtual String column_name(int) const override;
+ virtual ColumnMetadata column_metadata(int) const override;
+ virtual GVariant data(const GModelIndex&, Role = Role::Display) const override;
+ virtual void update() override;
+
+ void set_pid(pid_t);
+
+private:
+ JsonArray m_process_fds;
+ int m_pid { -1 };
+};
diff --git a/Applications/ProcessManager/ProcessFileDescriptorMapWidget.cpp b/Applications/ProcessManager/ProcessFileDescriptorMapWidget.cpp
new file mode 100644
index 0000000000..cf3691661e
--- /dev/null
+++ b/Applications/ProcessManager/ProcessFileDescriptorMapWidget.cpp
@@ -0,0 +1,25 @@
+#include "ProcessFileDescriptorMapWidget.h"
+#include "ProcessFileDescriptorMapModel.h"
+#include <LibGUI/GBoxLayout.h>
+#include <LibGUI/GTableView.h>
+
+ProcessFileDescriptorMapWidget::ProcessFileDescriptorMapWidget(GWidget* parent)
+ : GWidget(parent)
+{
+ set_layout(make<GBoxLayout>(Orientation::Vertical));
+ layout()->set_margins({ 4, 4, 4, 4 });
+ m_table_view = new GTableView(this);
+ m_table_view->set_model(adopt(*new ProcessFileDescriptorMapModel));
+}
+
+ProcessFileDescriptorMapWidget::~ProcessFileDescriptorMapWidget()
+{
+}
+
+void ProcessFileDescriptorMapWidget::set_pid(pid_t pid)
+{
+ if (m_pid == pid)
+ return;
+ m_pid = pid;
+ static_cast<ProcessFileDescriptorMapModel*>(m_table_view->model())->set_pid(pid);
+}
diff --git a/Applications/ProcessManager/ProcessFileDescriptorMapWidget.h b/Applications/ProcessManager/ProcessFileDescriptorMapWidget.h
new file mode 100644
index 0000000000..a858281b6d
--- /dev/null
+++ b/Applications/ProcessManager/ProcessFileDescriptorMapWidget.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <LibGUI/GWidget.h>
+
+class GTableView;
+
+class ProcessFileDescriptorMapWidget final : public GWidget {
+ C_OBJECT(ProcessFileDescriptorMapWidget);
+public:
+ explicit ProcessFileDescriptorMapWidget(GWidget* parent);
+ virtual ~ProcessFileDescriptorMapWidget() override;
+
+ void set_pid(pid_t);
+
+private:
+ GTableView* m_table_view { nullptr };
+ pid_t m_pid { -1 };
+};
diff --git a/Applications/ProcessManager/main.cpp b/Applications/ProcessManager/main.cpp
index 36c15bb753..080683d493 100644
--- a/Applications/ProcessManager/main.cpp
+++ b/Applications/ProcessManager/main.cpp
@@ -1,5 +1,6 @@
#include "GraphWidget.h"
#include "MemoryStatsWidget.h"
+#include "ProcessFileDescriptorMapWidget.h"
#include "ProcessMemoryMapWidget.h"
#include "ProcessStacksWidget.h"
#include "ProcessTableView.h"
@@ -157,6 +158,9 @@ int main(int argc, char** argv)
auto* process_tab_widget = new GTabWidget(process_container_splitter);
+ auto* open_files_widget = new ProcessFileDescriptorMapWidget(nullptr);
+ process_tab_widget->add_widget("Open files", open_files_widget);
+
auto* memory_map_widget = new ProcessMemoryMapWidget(nullptr);
process_tab_widget->add_widget("Memory map", memory_map_widget);
@@ -164,6 +168,7 @@ int main(int argc, char** argv)
process_tab_widget->add_widget("Stacks", stacks_widget);
process_table_view->on_process_selected = [&](pid_t pid) {
+ open_files_widget->set_pid(pid);
stacks_widget->set_pid(pid);
memory_map_widget->set_pid(pid);
};