summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2021-11-02 04:11:30 +0100
committerGitHub <noreply@github.com>2021-11-02 04:11:30 +0100
commitb118fa8698dbe0e2b6e663c1c37a7eac03422905 (patch)
tree14864116c00d385abba61ad2330c1c0f50e4b961 /src
parentMerge pull request #7264 from zhaobot/tx-update-20211101021628 (diff)
parentFix dangling kernel objects when exiting (diff)
downloadyuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.tar
yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.tar.gz
yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.tar.bz2
yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.tar.lz
yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.tar.xz
yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.tar.zst
yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.zip
Diffstat (limited to 'src')
-rw-r--r--src/core/core.cpp16
-rw-r--r--src/core/hle/kernel/k_handle_table.cpp1
-rw-r--r--src/core/hle/kernel/k_process.cpp11
-rw-r--r--src/core/hle/kernel/kernel.cpp36
-rw-r--r--src/core/hle/kernel/kernel.h8
-rw-r--r--src/core/hle/kernel/svc.cpp6
6 files changed, 54 insertions, 24 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 3c75f42ae..c3a0f9dae 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -83,12 +83,6 @@ FileSys::StorageId GetStorageIdForFrontendSlot(
}
}
-void KProcessDeleter(Kernel::KProcess* process) {
- process->Destroy();
-}
-
-using KProcessPtr = std::unique_ptr<Kernel::KProcess, decltype(&KProcessDeleter)>;
-
} // Anonymous namespace
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
@@ -261,11 +255,10 @@ struct System::Impl {
}
telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
- main_process = KProcessPtr{Kernel::KProcess::Create(system.Kernel()), KProcessDeleter};
- ASSERT(Kernel::KProcess::Initialize(main_process.get(), system, "main",
+ auto main_process = Kernel::KProcess::Create(system.Kernel());
+ ASSERT(Kernel::KProcess::Initialize(main_process, system, "main",
Kernel::KProcess::ProcessType::Userland)
.IsSuccess());
- main_process->Open();
const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
if (load_result != Loader::ResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result);
@@ -275,7 +268,7 @@ struct System::Impl {
static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
}
AddGlueRegistrationForProcess(*app_loader, *main_process);
- kernel.MakeCurrentProcess(main_process.get());
+ kernel.MakeCurrentProcess(main_process);
kernel.InitializeCores();
// Initialize cheat engine
@@ -340,8 +333,6 @@ struct System::Impl {
kernel.Shutdown();
memory.Reset();
applet_manager.ClearAll();
- // TODO: The main process should be freed based on KAutoObject ref counting.
- main_process.reset();
LOG_DEBUG(Core, "Shutdown OK");
}
@@ -403,7 +394,6 @@ struct System::Impl {
std::unique_ptr<Tegra::GPU> gpu_core;
std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
std::unique_ptr<Core::DeviceMemory> device_memory;
- KProcessPtr main_process{nullptr, KProcessDeleter};
Core::Memory::Memory memory;
CpuManager cpu_manager;
std::atomic_bool is_powered_on{};
diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp
index 44d13169f..e90fc0628 100644
--- a/src/core/hle/kernel/k_handle_table.cpp
+++ b/src/core/hle/kernel/k_handle_table.cpp
@@ -56,6 +56,7 @@ bool KHandleTable::Remove(Handle handle) {
}
// Close the object.
+ kernel.UnregisterInUseObject(obj);
obj->Close();
return true;
}
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 211157ccc..76fd8c285 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -434,11 +434,6 @@ void KProcess::PrepareForTermination() {
}
void KProcess::Finalize() {
- // Release memory to the resource limit.
- if (resource_limit != nullptr) {
- resource_limit->Close();
- }
-
// Finalize the handle table and close any open handles.
handle_table.Finalize();
@@ -460,6 +455,12 @@ void KProcess::Finalize() {
}
}
+ // Release memory to the resource limit.
+ if (resource_limit != nullptr) {
+ resource_limit->Close();
+ resource_limit = nullptr;
+ }
+
// Perform inherited finalization.
KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize();
}
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index bea945301..4a139c5e7 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -91,12 +91,6 @@ struct KernelCore::Impl {
}
void Shutdown() {
- // Shutdown all processes.
- if (current_process) {
- current_process->Finalize();
- current_process->Close();
- current_process = nullptr;
- }
process_list.clear();
// Close all open server ports.
@@ -170,6 +164,24 @@ struct KernelCore::Impl {
// Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
+ // Close kernel objects that were not freed on shutdown
+ {
+ std::lock_guard lk(registered_in_use_objects_lock);
+ if (registered_in_use_objects.size()) {
+ for (auto& object : registered_in_use_objects) {
+ object->Close();
+ }
+ registered_in_use_objects.clear();
+ }
+ }
+
+ // Shutdown all processes.
+ if (current_process) {
+ current_process->Finalize();
+ current_process->Close();
+ current_process = nullptr;
+ }
+
// Track kernel objects that were not freed on shutdown
{
std::lock_guard lk(registered_objects_lock);
@@ -714,9 +726,11 @@ struct KernelCore::Impl {
std::unordered_set<KServerPort*> server_ports;
std::unordered_set<KServerSession*> server_sessions;
std::unordered_set<KAutoObject*> registered_objects;
+ std::unordered_set<KAutoObject*> registered_in_use_objects;
std::mutex server_ports_lock;
std::mutex server_sessions_lock;
std::mutex registered_objects_lock;
+ std::mutex registered_in_use_objects_lock;
std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
std::vector<Kernel::PhysicalCore> cores;
@@ -928,6 +942,16 @@ void KernelCore::UnregisterKernelObject(KAutoObject* object) {
impl->registered_objects.erase(object);
}
+void KernelCore::RegisterInUseObject(KAutoObject* object) {
+ std::lock_guard lk(impl->registered_in_use_objects_lock);
+ impl->registered_in_use_objects.insert(object);
+}
+
+void KernelCore::UnregisterInUseObject(KAutoObject* object) {
+ std::lock_guard lk(impl->registered_in_use_objects_lock);
+ impl->registered_in_use_objects.erase(object);
+}
+
bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const {
return port != impl->named_ports.cend();
}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index b6658b437..d2ceae950 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -204,6 +204,14 @@ public:
/// destroyed during the current emulation session.
void UnregisterKernelObject(KAutoObject* object);
+ /// Registers kernel objects with guest in use state, this is purely for close
+ /// after emulation has been shutdown.
+ void RegisterInUseObject(KAutoObject* object);
+
+ /// Unregisters a kernel object previously registered with RegisterInUseObject when it was
+ /// destroyed during the current emulation session.
+ void UnregisterInUseObject(KAutoObject* object);
+
/// Determines whether or not the given port is a valid named port.
bool IsValidNamedPort(NamedPortTable::const_iterator port) const;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 7f38ade1c..c43135856 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -427,11 +427,15 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles,
num_handles),
ResultInvalidHandle);
+ for (const auto& obj : objs) {
+ kernel.RegisterInUseObject(obj);
+ }
}
// Ensure handles are closed when we're done.
SCOPE_EXIT({
for (u64 i = 0; i < num_handles; ++i) {
+ kernel.UnregisterInUseObject(objs[i]);
objs[i]->Close();
}
});
@@ -1561,6 +1565,7 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) {
// If we succeeded, persist a reference to the thread.
thread->Open();
+ system.Kernel().RegisterInUseObject(thread.GetPointerUnsafe());
return ResultSuccess;
}
@@ -1576,6 +1581,7 @@ static void ExitThread(Core::System& system) {
auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
system.GlobalSchedulerContext().RemoveThread(current_thread);
current_thread->Exit();
+ system.Kernel().UnregisterInUseObject(current_thread);
}
static void ExitThread32(Core::System& system) {