idm: Fix minor race in cellVdecClose, sys_raw_spu_destroy...

Because of racing removal of IDs vs the shared pointer owned object
This commit is contained in:
Eladash 2020-03-14 13:27:18 +02:00
parent efe6e1eb0a
commit c16124f0d9
6 changed files with 33 additions and 20 deletions

View file

@ -833,7 +833,12 @@ error_code cellAdecClose(u32 handle)
thread_ctrl::wait_for(1000); // hack
}
idm::remove<ppu_thread>(handle);
if (!idm::remove_verify<ppu_thread>(handle, std::move(adec)))
{
// Removed by other thread beforehead
return CELL_ADEC_ERROR_ARG;
}
return CELL_OK;
}

View file

@ -693,7 +693,13 @@ error_code cellVdecClose(ppu_thread& ppu, u32 handle)
}
ppu_execute<&sys_interrupt_thread_disestablish>(ppu, vdec->ppu_tid);
idm::remove<vdec_context>(handle);
if (!idm::remove_verify<vdec_context>(handle, std::move(vdec)))
{
// Other thread removed it beforehead
return CELL_VDEC_ERROR_ARG;
}
return CELL_OK;
}

View file

@ -117,15 +117,11 @@ error_code sceNpSnsFbDestroyHandle(u32 handle)
return SCE_NP_SNS_ERROR_INVALID_ARGUMENT;
}
const auto sfh = idm::get<sns_fb_handle_t>(handle);
if (!sfh)
if (!idm::remove<sns_fb_handle_t>(handle))
{
return SCE_NP_SNS_FB_ERROR_UNKNOWN_HANDLE;
}
idm::remove<sns_fb_handle_t>(handle);
return CELL_OK;
}

View file

@ -120,7 +120,7 @@ void sys_mempool_destroy(ppu_thread& ppu, sys_mempool_t mempool)
u32 mutexid = memory_pool->mutexid;
sys_mutex_lock(ppu, memory_pool->mutexid, 0);
idm::remove<memory_pool_t>(mempool);
idm::remove_verify<memory_pool_t>(mempool, std::move(memory_pool));
sys_mutex_unlock(ppu, mutexid);
sys_mutex_destroy(ppu, mutexid);
sys_cond_destroy(ppu, condid);

View file

@ -39,7 +39,7 @@ void lv2_int_serv::join()
thread_ctrl::notify(*thread);
(*thread)();
idm::remove<named_thread<ppu_thread>>(thread->id);
idm::remove_verify<named_thread<ppu_thread>>(thread->id, thread);
}
error_code sys_interrupt_tag_destroy(ppu_thread& ppu, u32 intrtag)

View file

@ -1703,32 +1703,33 @@ error_code sys_raw_spu_destroy(ppu_thread& ppu, u32 id)
thread->state += cpu_flag::stop;
// Kernel objects which must be removed
std::unordered_map<lv2_obj*, u32, pointer_hash<lv2_obj, alignof(void*)>> to_remove;
std::vector<std::pair<std::shared_ptr<lv2_obj>, u32>> to_remove;
// Clear interrupt handlers
for (auto& intr : thread->int_ctrl)
{
if (const auto tag = intr.tag.lock())
if (auto tag = intr.tag.lock())
{
if (auto handler = tag->handler.lock())
{
// SLEEP
handler->join();
to_remove.emplace(handler.get(), 0);
to_remove.emplace_back(std::move(handler), 0);
}
to_remove.emplace(tag.get(), 0);
to_remove.emplace_back(std::move(tag), 0);
}
}
// Scan all kernel objects to determine IDs
idm::select<lv2_obj>([&](u32 id, lv2_obj& obj)
{
const auto found = to_remove.find(&obj);
if (found != to_remove.end())
for (auto& pair : to_remove)
{
found->second = id;
if (pair.first.get() == std::addressof(obj))
{
pair.second = id;
}
}
});
@ -1736,12 +1737,17 @@ error_code sys_raw_spu_destroy(ppu_thread& ppu, u32 id)
for (auto&& pair : to_remove)
{
if (pair.second >> 24 == 0xa)
idm::remove<lv2_obj, lv2_int_tag>(pair.second);
idm::remove_verify<lv2_obj, lv2_int_tag>(pair.second, std::move(pair.first));
if (pair.second >> 24 == 0xb)
idm::remove<lv2_obj, lv2_int_serv>(pair.second);
idm::remove_verify<lv2_obj, lv2_int_serv>(pair.second, std::move(pair.first));
}
if (!idm::remove_verify<named_thread<spu_thread>>(thread->id, std::move(thread)))
{
// Other thread destroyed beforehead
return CELL_ESRCH;
}
idm::remove<named_thread<spu_thread>>(thread->id);
return CELL_OK;
}