Races and ThreadSafe issues (#4239)

* used atomics for thread safety

* equeue: Save filter/ident before std:move since we access them out of the locked loop

* fixed kqueues memory leak

* clean storage objects effectively

* fixed memory leak

* fix some races

* fixed race condition
This commit is contained in:
georgemoralis 2026-04-09 17:46:36 +03:00 committed by GitHub
parent 36e11fcce5
commit 2c6d41cdd4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 28 additions and 19 deletions

View File

@ -77,7 +77,9 @@ private:
}
void Release() {
std::destroy_n(storage.get(), used_objects);
for (size_t i = 0; i < used_objects; i++) {
storage[i].object.~T();
}
used_objects = 0;
}

View File

@ -1,9 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <atomic>
#include <memory>
#include "common/assert.h"
#include "common/spin_lock.h"
@ -152,6 +153,7 @@ public:
}
void Free(T* obj) {
std::destroy_at(obj);
BaseHeap::Free(obj);
}

View File

@ -303,6 +303,7 @@ File* HandleTable::GetResolver(int d) {
}
File* HandleTable::GetFile(const std::filesystem::path& host_name) {
std::scoped_lock lock{m_mutex};
for (auto* file : m_files) {
if (file != nullptr && file->m_host_name == host_name) {
return file;

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <thread>
@ -49,6 +49,10 @@ static void TimerCallback(OrbisKernelEqueue eq, const OrbisKernelEvent& kevent)
// Events are uniquely identified by id and filter.
bool EqueueInternal::AddEvent(EqueueEvent& event) {
// Save id and filter before event is moved into m_events.
const u64 id = event.event.ident;
const auto filter = event.event.filter;
{
std::scoped_lock lock{m_mutex};
@ -71,8 +75,6 @@ bool EqueueInternal::AddEvent(EqueueEvent& event) {
}
// First, check if there's already an event with the same id and filter.
u64 id = event.event.ident;
OrbisKernelEvent::Filter filter = event.event.filter;
const auto& find_it = std::ranges::find_if(m_events, [id, filter](auto& ev) {
return ev.event.ident == id && ev.event.filter == filter;
});
@ -106,12 +108,10 @@ bool EqueueInternal::AddEvent(EqueueEvent& event) {
}
// Schedule callbacks for timer events
if (event.event.filter == OrbisKernelEvent::Timer) {
return this->ScheduleEvent(event.event.ident, OrbisKernelEvent::Filter::Timer,
TimerCallback);
} else if (event.event.filter == OrbisKernelEvent::HrTimer) {
return this->ScheduleEvent(event.event.ident, OrbisKernelEvent::Filter::HrTimer,
HrTimerCallback);
if (filter == OrbisKernelEvent::Filter::Timer) {
return this->ScheduleEvent(id, OrbisKernelEvent::Filter::Timer, TimerCallback);
} else if (filter == OrbisKernelEvent::Filter::HrTimer) {
return this->ScheduleEvent(id, OrbisKernelEvent::Filter::HrTimer, HrTimerCallback);
}
return true;
@ -454,6 +454,7 @@ int PS4_SYSV_ABI sceKernelDeleteEqueue(OrbisKernelEqueue eq) {
auto* handles = Common::Singleton<Core::FileSys::HandleTable>::Instance();
handles->DeleteHandle(eq);
delete kqueues[eq];
kqueues.erase(eq);
return ORBIS_OK;
}

View File

@ -30,8 +30,8 @@ static int CondInit(PthreadCondT* cond, const PthreadCondAttrT* cond_attr, const
if (name) {
cvp->name = name;
} else {
static int CondId = 0;
cvp->name = fmt::format("Cond{}", CondId++);
static std::atomic<int> CondId{0};
cvp->name = fmt::format("Cond{}", CondId.fetch_add(1));
}
if (cond_attr == nullptr || *cond_attr == nullptr) {

View File

@ -60,8 +60,8 @@ static s32 MutexInit(PthreadMutexT* mutex, const PthreadMutexAttr* mutex_attr, c
if (name) {
pmutex->name = name;
} else {
static s32 MutexId = 0;
pmutex->name = fmt::format("Mutex{}", MutexId++);
static std::atomic<s32> MutexId{0};
pmutex->name = fmt::format("Mutex{}", MutexId.fetch_add(1));
}
pmutex->m_flags = PthreadMutexFlags(attr->m_type);

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <boost/container/small_vector.hpp>
@ -78,8 +78,10 @@ Pthread* ThreadState::Alloc(Pthread* curthread) {
}
if (!free_threads.empty()) {
std::scoped_lock lk{free_thread_lock};
thread = free_threads.back();
free_threads.pop_back();
if (!free_threads.empty()) {
thread = free_threads.back();
free_threads.pop_back();
}
}
}
if (thread == nullptr) {
@ -123,9 +125,10 @@ void ThreadState::Free(Pthread* curthread, Pthread* thread) {
TcbDtor(thread->tcb);
}
thread->tcb = nullptr;
auto* sleepqueue = thread->sleepqueue;
std::destroy_at(thread);
if (free_threads.size() >= MaxCachedThreads) {
delete thread->sleepqueue;
delete sleepqueue;
thread_heap.Free(thread);
total_threads.fetch_sub(1);
} else {