Races and leak fixes part 2 (#4241)

* fixed Unsynchronized free_threads.size()` Read in ThreadState::Free

* fixed data race in posix_pthread_key_create , allocated and seqno are atomic now

* fixed playtime thread

* argv array size fix

* destroy mutex on object deletion with pthread_mutex_destroy

* fixed object_pool
This commit is contained in:
georgemoralis
2026-04-09 20:47:47 +03:00
committed by GitHub
parent 5ca2b07f94
commit 15279c42ac
8 changed files with 33 additions and 19 deletions
+8 -1
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
#pragma once
@@ -12,6 +12,13 @@ namespace Common {
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
class AdaptiveMutex {
public:
AdaptiveMutex() = default;
~AdaptiveMutex() {
pthread_mutex_destroy(&mutex);
}
AdaptiveMutex(const AdaptiveMutex&) = delete;
AdaptiveMutex& operator=(const AdaptiveMutex&) = delete;
void lock() {
pthread_mutex_lock(&mutex);
}
+1 -3
View File
@@ -77,9 +77,7 @@ private:
}
void Release() {
for (size_t i = 0; i < used_objects; i++) {
storage[i].object.~T();
}
std::destroy_n(storage.get(), used_objects);
used_objects = 0;
}
+3 -3
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
#pragma once
@@ -212,8 +212,8 @@ struct PthreadSpecificElem {
using PthreadKeyDestructor = void PS4_SYSV_ABI (*)(const void*);
struct PthreadKey {
int allocated;
int seqno;
std::atomic<int> allocated;
std::atomic<int> seqno;
PthreadKeyDestructor destructor;
};
using PthreadKeyT = s32;
@@ -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 "core/libraries/kernel/kernel.h"
@@ -16,7 +16,8 @@ static std::mutex KeytableLock;
int PS4_SYSV_ABI posix_pthread_key_create(PthreadKeyT* key, PthreadKeyDestructor destructor) {
std::scoped_lock lk{KeytableLock};
const auto it = std::ranges::find(ThreadKeytable, 0, &PthreadKey::allocated);
const auto it = std::ranges::find_if(
ThreadKeytable, [](const PthreadKey& k) { return k.allocated.load() == 0; });
if (it != ThreadKeytable.end()) {
it->allocated = 1;
it->destructor = destructor;
@@ -127,13 +127,20 @@ void ThreadState::Free(Pthread* curthread, Pthread* thread) {
thread->tcb = nullptr;
auto* sleepqueue = thread->sleepqueue;
std::destroy_at(thread);
if (free_threads.size() >= MaxCachedThreads) {
bool should_free;
{
std::scoped_lock lk{free_thread_lock};
if (free_threads.size() >= MaxCachedThreads) {
should_free = true;
} else {
should_free = false;
free_threads.push_back(thread);
}
}
if (should_free) {
delete sleepqueue;
thread_heap.Free(thread);
total_threads.fetch_sub(1);
} else {
std::scoped_lock lk{free_thread_lock};
free_threads.push_back(thread);
}
}
+3 -2
View File
@@ -140,8 +140,9 @@ void Linker::Execute(const std::vector<std::string>& args) {
params.argc = 1;
params.argv[0] = "eboot.bin";
if (!args.empty()) {
params.argc = args.size();
for (int i = 0; i < args.size() && i < 33; i++) {
constexpr int MaxArgs = sizeof(params.argv) / sizeof(params.argv[0]);
params.argc = std::min<int>(args.size(), MaxArgs);
for (int i = 0; i < params.argc; i++) {
params.argv[i] = args[i].c_str();
}
}
+3 -4
View File
@@ -445,13 +445,12 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
if (!id.empty()) {
start_time = std::chrono::steady_clock::now();
std::thread([this, id]() {
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(60));
play_time_thread = std::jthread([this, id](std::stop_token stop) {
while (Common::StoppableTimedWait(stop, std::chrono::seconds(60))) {
UpdatePlayTime(id);
start_time = std::chrono::steady_clock::now();
}
}).detach();
});
}
args.insert(args.begin(), eboot_name.generic_string());
+1
View File
@@ -47,6 +47,7 @@ private:
Core::Linker* linker;
std::unique_ptr<Frontend::WindowSDL> window;
std::chrono::steady_clock::time_point start_time;
std::jthread play_time_thread;
};
} // namespace Core