mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
fix(gameplay): prevent use-after-free in pending delete queues during destruction
This commit is contained in:
@@ -105,6 +105,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<bool> m_is_pending_delete_queue_free{false};
|
||||
std::mutex m_delete_vbo_mutex;
|
||||
std::mutex m_delete_vao_mutex;
|
||||
std::vector<std::unique_ptr<VertexBuffer>> m_pending_delete_vbo;
|
||||
std::vector<std::unique_ptr<VertexArray>> m_pending_delete_vao;
|
||||
|
||||
enum class ChunkLoadStyle { RANDOM, CENTER };
|
||||
using ChunkHashMap =
|
||||
tbb::concurrent_hash_map<ChunkPos, std::shared_ptr<ClientChunk>,
|
||||
@@ -130,15 +136,11 @@ private:
|
||||
std::vector<glm::vec4> m_planes;
|
||||
std::jthread m_client_thread;
|
||||
|
||||
std::mutex m_delete_vbo_mutex;
|
||||
std::mutex m_delete_vao_mutex;
|
||||
mutable std::shared_mutex m_player_info_mutex;
|
||||
|
||||
tbb::concurrent_queue<std::unique_ptr<ClientChunk>> m_pending_upload_queue;
|
||||
tbb::concurrent_queue<ChunkPos> m_dirty_chunk_queue;
|
||||
tbb::concurrent_queue<PendingSound> m_pending_sound;
|
||||
std::vector<std::unique_ptr<VertexBuffer>> m_pending_delete_vbo;
|
||||
std::vector<std::unique_ptr<VertexArray>> m_pending_delete_vao;
|
||||
|
||||
std::deque<ChunkPos> m_dirty_queue;
|
||||
std::vector<const ChunkRenderSnapshot*> m_render_snapshots;
|
||||
|
||||
@@ -25,11 +25,22 @@ ClientWorld::ClientWorld(AudioEngine& auido, Config& config)
|
||||
: m_player(*this), m_audio(auido), m_config(config) {}
|
||||
|
||||
ClientWorld::~ClientWorld() {
|
||||
m_client->close();
|
||||
|
||||
stop_client_thread();
|
||||
stop_thread_pool();
|
||||
// Must first clean up and push the generated chunk data into
|
||||
// m_pending_delete_vbo and m_pending_delete_vao; cannot delete them in the
|
||||
// destructor, otherwise it will cause leaks and use-after-free.
|
||||
m_dirty_chunk_queue.clear();
|
||||
m_pending_upload_queue.clear();
|
||||
|
||||
m_chunks.clear();
|
||||
|
||||
if (m_is_pending_delete_queue_free.exchange(true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard lk(m_delete_vbo_mutex);
|
||||
m_pending_delete_vbo.clear();
|
||||
@@ -262,10 +273,18 @@ void ClientWorld::set_block(const glm::ivec3& block_pos, unsigned id) {
|
||||
}
|
||||
}
|
||||
void ClientWorld::push_delete_vbo(std::unique_ptr<VertexBuffer>& vbo) {
|
||||
if (m_is_pending_delete_queue_free) {
|
||||
Logger::error("Push delete vbo Use After Free");
|
||||
return;
|
||||
}
|
||||
std::lock_guard lk(m_delete_vbo_mutex);
|
||||
m_pending_delete_vbo.push_back(std::move(vbo));
|
||||
}
|
||||
void ClientWorld::push_delete_vao(std::unique_ptr<VertexArray>& vao) {
|
||||
if (m_is_pending_delete_queue_free) {
|
||||
Logger::error("Push delete vao Use After Free");
|
||||
return;
|
||||
}
|
||||
std::lock_guard lk(m_delete_vao_mutex);
|
||||
m_pending_delete_vao.push_back(std::move(vao));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user