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:
|
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 };
|
enum class ChunkLoadStyle { RANDOM, CENTER };
|
||||||
using ChunkHashMap =
|
using ChunkHashMap =
|
||||||
tbb::concurrent_hash_map<ChunkPos, std::shared_ptr<ClientChunk>,
|
tbb::concurrent_hash_map<ChunkPos, std::shared_ptr<ClientChunk>,
|
||||||
@@ -130,15 +136,11 @@ private:
|
|||||||
std::vector<glm::vec4> m_planes;
|
std::vector<glm::vec4> m_planes;
|
||||||
std::jthread m_client_thread;
|
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;
|
mutable std::shared_mutex m_player_info_mutex;
|
||||||
|
|
||||||
tbb::concurrent_queue<std::unique_ptr<ClientChunk>> m_pending_upload_queue;
|
tbb::concurrent_queue<std::unique_ptr<ClientChunk>> m_pending_upload_queue;
|
||||||
tbb::concurrent_queue<ChunkPos> m_dirty_chunk_queue;
|
tbb::concurrent_queue<ChunkPos> m_dirty_chunk_queue;
|
||||||
tbb::concurrent_queue<PendingSound> m_pending_sound;
|
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::deque<ChunkPos> m_dirty_queue;
|
||||||
std::vector<const ChunkRenderSnapshot*> m_render_snapshots;
|
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) {}
|
: m_player(*this), m_audio(auido), m_config(config) {}
|
||||||
|
|
||||||
ClientWorld::~ClientWorld() {
|
ClientWorld::~ClientWorld() {
|
||||||
|
m_client->close();
|
||||||
|
|
||||||
stop_client_thread();
|
stop_client_thread();
|
||||||
stop_thread_pool();
|
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();
|
m_chunks.clear();
|
||||||
|
|
||||||
|
if (m_is_pending_delete_queue_free.exchange(true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard lk(m_delete_vbo_mutex);
|
std::lock_guard lk(m_delete_vbo_mutex);
|
||||||
m_pending_delete_vbo.clear();
|
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) {
|
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);
|
std::lock_guard lk(m_delete_vbo_mutex);
|
||||||
m_pending_delete_vbo.push_back(std::move(vbo));
|
m_pending_delete_vbo.push_back(std::move(vbo));
|
||||||
}
|
}
|
||||||
void ClientWorld::push_delete_vao(std::unique_ptr<VertexArray>& vao) {
|
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);
|
std::lock_guard lk(m_delete_vao_mutex);
|
||||||
m_pending_delete_vao.push_back(std::move(vao));
|
m_pending_delete_vao.push_back(std::move(vao));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user