From: Marek VavruĊĦa Date: Tue, 21 Aug 2018 06:59:24 +0000 (-0700) Subject: cache/api: prevent deadlock on kr_cache_remove with multiple processes X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=159b5e48705869ee3044404f3f9bec2073ce5470;p=thirdparty%2Fknot-resolver.git cache/api: prevent deadlock on kr_cache_remove with multiple processes Only the `kr_cache_remove_subtree` called `kr_cache_sync` to commit the write transaction after cache removal operation. This wasn't done in the `kr_cache_remove` so the write transaction could be long-lived. With two or more processes, if one help the write transaction open, no other process could open it. If the process holding the transaction would call IPC to other processes and wait, it would never release it and the other processes could never acquire it, and deadlock would occur. --- diff --git a/lib/cache/api.c b/lib/cache/api.c index 9f9452027..52e786869 100644 --- a/lib/cache/api.c +++ b/lib/cache/api.c @@ -862,7 +862,12 @@ int kr_cache_remove(struct kr_cache *cache, const knot_dname_t *name, uint16_t t if (ret) return kr_error(ret); knot_db_val_t key = key_exact_type(k, type, NULL); - return cache_op(cache, remove, &key, 1); + ret = cache_op(cache, remove, &key, 1); + + /* Commit write transactions, as only one can be open at a time */ + kr_cache_sync(cache); + + return ret; } int kr_cache_match(struct kr_cache *cache, const knot_dname_t *name, @@ -950,7 +955,8 @@ int kr_cache_remove_subtree(struct kr_cache *cache, const knot_dname_t *name, } ret = cache->api->remove(cache->db, keys, count); cleanup: - kr_cache_sync(cache); /* Sync even after just kr_cache_match(). */ + /* Commit write transactions, as only one can be open at a time */ + kr_cache_sync(cache); /* Free keys */ while (--i >= 0) { free(keys[i].data);