@@ -1046,12 +1046,8 @@ void server_models::download(common_params_model && model, common_download_opts
10461046 SRV_INF (" download finished for model name=%s with status=%s\n " ,
10471047 dl->model .name .c_str (), ok ? " success" : " failure" );
10481048 update_download_progress (dl->model .name , {}, true , ok);
1049- // mark list as dirty
1050- {
1051- std::lock_guard<std::mutex> lk (this ->mutex );
1052- need_reload = true ;
1053- // the next time load_models() is called, it will clean up this instance
1054- }
1049+ // need_reload is set inside update_download_progress under the mutex;
1050+ // the next load_models() call will clean up this instance
10551051 });
10561052
10571053 mapping[name] = std::move (inst);
@@ -1167,6 +1163,7 @@ void server_models::update_download_progress(const std::string & name, const com
11671163 if (done) {
11681164 // mark the instance to be erased on next load_models() call
11691165 it->second .meta .status = SERVER_MODEL_STATUS_DOWNLOADED ;
1166+ need_reload = true ;
11701167 } else {
11711168 json & info = it->second .meta .loaded_info ;
11721169 if (!info.contains (" progress" )) {
@@ -1198,12 +1195,19 @@ bool server_models::remove(const std::string & name) {
11981195 throw std::runtime_error (" model name=" + name + " is not removable (not from cache)" );
11991196 }
12001197
1201- unload (name); // ensure it's not running
1198+ unload (name); // cancel download or stop running instance
12021199 {
12031200 std::unique_lock<std::mutex> lk (mutex);
1201+ // a cancelled download lands on DOWNLOADED; a stopped instance lands on UNLOADED
12041202 wait (lk, name, [](const server_model_meta & new_meta) {
1205- return new_meta.status == SERVER_MODEL_STATUS_UNLOADED ;
1203+ return new_meta.status == SERVER_MODEL_STATUS_UNLOADED
1204+ || new_meta.status == SERVER_MODEL_STATUS_DOWNLOADED ;
12061205 });
1206+ // join before erasing - after status reaches UNLOADED/DOWNLOADED the thread no
1207+ // longer acquires this mutex, so joining while holding it is safe
1208+ if (mapping[name].th .joinable ()) {
1209+ mapping[name].th .join ();
1210+ }
12071211 // remove the model from disk (hold lock to prevent concurrent load)
12081212 bool ok = common_download_remove (name);
12091213 if (ok) {
0 commit comments