1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 22:17:42 +00:00

Kernel/ProcFS: Clean dead processes properly

Now we use WeakPtrs to break Ref-counting cycle. Also, we call the
prepare_for_deletion method to ensure deleted objects are ready for
deletion. This is necessary to ensure we don't keep dead processes,
which would become zombies.

In addition to that, add some debug prints to aid debug in the future.
This commit is contained in:
Liav A 2021-07-01 19:18:38 +03:00 committed by Andreas Kling
parent 5073bf8e75
commit 3344f91fc4
6 changed files with 103 additions and 43 deletions

View file

@ -83,24 +83,29 @@ private:
, m_process_folder(parent_folder)
{
}
RefPtr<ProcFSProcessFolder> m_process_folder;
WeakPtr<ProcFSProcessFolder> m_process_folder;
mutable Lock m_lock;
};
KResultOr<size_t> ProcFSProcessStacks::entries_count() const
{
Locker locker(m_lock);
auto process = m_process_folder->m_associated_process;
return process->thread_count();
auto parent_folder = m_process_folder.strong_ref();
if (parent_folder.is_null())
return KResult(EINVAL);
return parent_folder->m_associated_process->thread_count();
}
KResult ProcFSProcessStacks::traverse_as_directory(unsigned fsid, Function<bool(const FS::DirectoryEntryView&)> callback) const
{
Locker locker(m_lock);
auto parent_folder = m_process_folder.strong_ref();
if (parent_folder.is_null())
return KResult(EINVAL);
callback({ ".", { fsid, component_index() }, 0 });
callback({ "..", { fsid, m_parent_folder->component_index() }, 0 });
callback({ "..", { fsid, parent_folder->component_index() }, 0 });
auto process = m_process_folder->m_associated_process;
auto process = parent_folder->m_associated_process;
process->for_each_thread([&](const Thread& thread) {
int tid = thread.tid().value();
InodeIdentifier identifier = { fsid, thread.global_procfs_inode_index() };
@ -112,13 +117,16 @@ KResult ProcFSProcessStacks::traverse_as_directory(unsigned fsid, Function<bool(
RefPtr<ProcFSExposedComponent> ProcFSProcessStacks::lookup(StringView name)
{
Locker locker(m_lock);
auto process = m_process_folder->m_associated_process;
auto parent_folder = m_process_folder.strong_ref();
if (parent_folder.is_null())
return nullptr;
auto process = parent_folder->m_associated_process;
RefPtr<ProcFSThreadStack> procfd_stack;
// FIXME: Try to exit the loop earlier
process->for_each_thread([&](const Thread& thread) {
int tid = thread.tid().value();
if (name == String::number(tid)) {
procfd_stack = ProcFSThreadStack::create(*m_process_folder, *this, thread);
procfd_stack = ProcFSThreadStack::create(*parent_folder, *this, thread);
}
});
return procfd_stack;
@ -177,24 +185,30 @@ private:
, m_process_folder(parent_folder)
{
}
RefPtr<ProcFSProcessFolder> m_process_folder;
WeakPtr<ProcFSProcessFolder> m_process_folder;
mutable Lock m_lock;
};
KResultOr<size_t> ProcFSProcessFileDescriptions::entries_count() const
{
Locker locker(m_lock);
return m_process_folder->m_associated_process->fds().open_count();
auto parent_folder = m_process_folder.strong_ref();
if (parent_folder.is_null())
return KResult(EINVAL);
return parent_folder->m_associated_process->fds().open_count();
}
KResult ProcFSProcessFileDescriptions::traverse_as_directory(unsigned fsid, Function<bool(const FS::DirectoryEntryView&)> callback) const
{
Locker locker(m_lock);
auto parent_folder = m_process_folder.strong_ref();
if (parent_folder.is_null())
return KResult(EINVAL);
callback({ ".", { fsid, component_index() }, 0 });
callback({ "..", { fsid, m_parent_folder->component_index() }, 0 });
callback({ "..", { fsid, parent_folder->component_index() }, 0 });
auto process = m_process_folder->m_associated_process;
auto process = parent_folder->m_associated_process;
size_t count = 0;
m_process_folder->m_associated_process->fds().enumerate([&](auto& file_description_metadata) {
process->fds().enumerate([&](auto& file_description_metadata) {
if (!file_description_metadata.is_valid()) {
count++;
return;
@ -208,11 +222,14 @@ KResult ProcFSProcessFileDescriptions::traverse_as_directory(unsigned fsid, Func
RefPtr<ProcFSExposedComponent> ProcFSProcessFileDescriptions::lookup(StringView name)
{
Locker locker(m_lock);
auto process = m_process_folder->m_associated_process;
auto parent_folder = m_process_folder.strong_ref();
if (parent_folder.is_null())
return nullptr;
auto process = parent_folder->m_associated_process;
RefPtr<ProcFSProcessFileDescription> procfd_fd;
// FIXME: Try to exit the loop earlier
size_t count = 0;
m_process_folder->m_associated_process->fds().enumerate([&](auto& file_description_metadata) {
process->fds().enumerate([&](auto& file_description_metadata) {
if (!file_description_metadata.is_valid()) {
count++;
return;
@ -239,8 +256,11 @@ private:
}
virtual bool output(KBufferBuilder& builder) override
{
auto parent_folder = m_parent_folder.strong_ref();
if (parent_folder.is_null())
return false;
JsonArraySerializer array { builder };
for (auto& unveiled_path : m_parent_folder->m_associated_process->unveiled_paths()) {
for (auto& unveiled_path : parent_folder->m_associated_process->unveiled_paths()) {
if (!unveiled_path.was_explicitly_unveiled())
continue;
auto obj = array.add_object();
@ -278,11 +298,15 @@ private:
virtual bool output(KBufferBuilder& builder) override
{
InterruptDisabler disabler;
if (!m_parent_folder->m_associated_process->perf_events()) {
dbgln("ProcFS: No perf events for {}", m_parent_folder->m_associated_process->pid());
auto parent_folder = m_parent_folder.strong_ref();
if (parent_folder.is_null())
return false;
auto process = parent_folder->m_associated_process;
if (!process->perf_events()) {
dbgln("ProcFS: No perf events for {}", process->pid());
return false;
}
return m_parent_folder->m_associated_process->perf_events()->to_json(builder);
return process->perf_events()->to_json(builder);
}
};
@ -300,8 +324,11 @@ private:
}
virtual bool output(KBufferBuilder& builder) override
{
auto parent_folder = m_parent_folder.strong_ref();
if (parent_folder.is_null())
return false;
JsonArraySerializer array { builder };
auto process = m_parent_folder->m_associated_process;
auto process = parent_folder->m_associated_process;
if (process->fds().open_count() == 0) {
array.finish();
return true;
@ -348,10 +375,13 @@ private:
}
virtual bool acquire_link(KBufferBuilder& builder) override
{
builder.append_bytes(m_parent_process_directory->m_associated_process->root_directory_relative_to_global_root().absolute_path().to_byte_buffer());
auto parent_folder = m_parent_process_directory.strong_ref();
if (parent_folder.is_null())
return false;
builder.append_bytes(parent_folder->m_associated_process->root_directory_relative_to_global_root().absolute_path().to_byte_buffer());
return true;
}
NonnullRefPtr<ProcFSProcessFolder> m_parent_process_directory;
WeakPtr<ProcFSProcessFolder> m_parent_process_directory;
};
class ProcFSProcessVirtualMemory final : public ProcFSProcessInformation {
@ -368,7 +398,10 @@ private:
}
virtual bool output(KBufferBuilder& builder) override
{
auto process = m_parent_folder->m_associated_process;
auto parent_folder = m_parent_folder.strong_ref();
if (parent_folder.is_null())
return false;
auto process = parent_folder->m_associated_process;
JsonArraySerializer array { builder };
{
ScopedSpinLock lock(process->space().get_lock());
@ -428,11 +461,14 @@ private:
}
virtual bool acquire_link(KBufferBuilder& builder) override
{
builder.append_bytes(m_parent_process_directory->m_associated_process->current_directory().absolute_path().bytes());
auto parent_folder = m_parent_process_directory.strong_ref();
if (parent_folder.is_null())
return false;
builder.append_bytes(parent_folder->m_associated_process->current_directory().absolute_path().bytes());
return true;
}
NonnullRefPtr<ProcFSProcessFolder> m_parent_process_directory;
WeakPtr<ProcFSProcessFolder> m_parent_process_directory;
};
class ProcFSProcessBinary final : public ProcFSExposedLink {
@ -444,7 +480,10 @@ public:
virtual mode_t required_mode() const override
{
if (!m_parent_process_directory->m_associated_process->executable())
auto parent_folder = m_parent_process_directory.strong_ref();
if (parent_folder.is_null())
return false;
if (!parent_folder->m_associated_process->executable())
return 0;
return ProcFSExposedComponent::required_mode();
}
@ -457,14 +496,17 @@ private:
}
virtual bool acquire_link(KBufferBuilder& builder) override
{
auto* custody = m_parent_process_directory->m_associated_process->executable();
auto parent_folder = m_parent_process_directory.strong_ref();
if (parent_folder.is_null())
return false;
auto* custody = parent_folder->m_associated_process->executable();
if (!custody)
return false;
builder.append(custody->absolute_path().bytes());
return true;
}
NonnullRefPtr<ProcFSProcessFolder> m_parent_process_directory;
WeakPtr<ProcFSProcessFolder> m_parent_process_directory;
};
NonnullRefPtr<ProcFSProcessFolder> ProcFSProcessFolder::create(const Process& process)