From 8395a4db7c4df2495830a9ffa19039d46601fe4e Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Thu, 3 Sep 2026 13:25:43 +0200 Subject: [PATCH] server : fix deadlock when removing a finished download The download monitor thread acquires the mutex on its way out, so joining it while holding the lock in server_models::remove deadlocks once the status has flipped to DOWNLOADED. Join outside the lock, same pattern as load_models(). Assisted-by: pi:zai-org/GLM-5.3 --- tools/server/server-models.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/server/server-models.cpp b/tools/server/server-models.cpp index db0fac9952..775090e654 100644 --- a/tools/server/server-models.cpp +++ b/tools/server/server-models.cpp @@ -1332,14 +1332,20 @@ bool server_models::remove(const std::string & name) { return true; } - // join before erasing - thread no longer acquires this mutex - if (it->second.th.joinable()) { - it->second.th.join(); - } + // on the cancelled-download path the status flips to DOWNLOADED while the + // monitoring thread still has a mutex-guarded step left, so joining under + // the lock would deadlock - join outside, as load_models() does + std::thread th = std::move(it->second.th); // remove from disk (best-effort: cancelled downloads may have no cached files) bool ok = common_download_remove(name); mapping.erase(name); + lk.unlock(); + + if (th.joinable()) { + th.join(); + } + if (!ok) { SRV_WRN("removing model name=%s from disk returned false (no cached files?)\n", name.c_str()); }