From 5a60f9965d2b02a27c480ecf2dbd48efdce0dd1e Mon Sep 17 00:00:00 2001 From: Juston Li Date: Tue, 19 Nov 2024 16:09:31 -0800 Subject: [PATCH] util/cache_test: Fix racey Cache.List test Instead of using unreliable polling to wait for foz db updater to parse and load from the dynamic list, also use inotify to wait for foz db updater close the list file after its done updating. Fixes: 4dfd306454a4 ("disk_cache: Disable the "List" test for RO disk cache.") Signed-off-by: Juston Li Reviewed-by: David Heidelberg Part-of: (cherry picked from commit cbb3bb5c7bc9b58a95ea3612f6fb9263362751b9) --- .pick_status.json | 2 +- src/util/tests/cache_test.cpp | 71 +++++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 1c67ae04764..0b03aab26aa 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -494,7 +494,7 @@ "description": "util/cache_test: Fix racey Cache.List test", "nominated": true, "nomination_type": 2, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "4dfd306454a4653a8c0b0a37a3e6bb1632abfc9e", "notes": null diff --git a/src/util/tests/cache_test.cpp b/src/util/tests/cache_test.cpp index 315228ef637..f181178c809 100644 --- a/src/util/tests/cache_test.cpp +++ b/src/util/tests/cache_test.cpp @@ -44,6 +44,10 @@ #include "util/disk_cache_os.h" #include "util/ralloc.h" +#ifdef FOZ_DB_UTIL_DYNAMIC_LIST +#include +#endif + #ifdef ENABLE_SHADER_CACHE /* Callback for nftw used in rmrf_local below. @@ -129,23 +133,46 @@ cache_exists(struct disk_cache *cache) return result != NULL; } -static void * -poll_disk_cache_get(struct disk_cache *cache, - const cache_key key, - size_t *size) +#ifdef FOZ_DB_UTIL_DYNAMIC_LIST +/* + * Wait for foz_db updater to close the foz db list file after its + * done updating. + */ +static void +close_and_wait_for_list(FILE* list_file, const char* list_filename) { - void *result; - - for (int iter = 0; iter < 1000; ++iter) { - result = disk_cache_get(cache, key, size); - if (result) - return result; - - usleep(1000); + char buf[10 * (sizeof(struct inotify_event) + NAME_MAX + 1)]; + int fd = inotify_init1(IN_CLOEXEC); + int wd = inotify_add_watch(fd, list_filename, IN_CLOSE_NOWRITE); + if (wd < 0) { + close(fd); + return; } - return NULL; + /* Prevent racing by closing the list file we wrote to after inotify + * has started. Since this was a write, it gets ignored by inotify + */ + fclose(list_file); + + int len = read(fd, buf, sizeof(buf)); + if (len == -1) { + close(fd); + inotify_rm_watch(fd, wd); + return; + } + + int i = 0; + while (i < len) { + struct inotify_event *event = (struct inotify_event *)&buf[i]; + i += sizeof(struct inotify_event) + event->len; + if (event->mask & IN_CLOSE_NOWRITE) + break; + } + + inotify_rm_watch(fd, wd); + close(fd); } +#endif #define CACHE_TEST_TMP "./cache-test-tmp" @@ -1048,7 +1075,7 @@ TEST_F(Cache, Combined) #endif } -TEST_F(Cache, DISABLED_List) +TEST_F(Cache, List) { const char *driver_id = "make_check"; char blob[] = "This is a RO blob"; @@ -1148,10 +1175,12 @@ TEST_F(Cache, DISABLED_List) /* Add ro_cache to list file for loading */ list_file = fopen(list_filename, "a"); fputs("ro_cache\n", list_file); - fclose(list_file); - /* Poll result to give time for updater to load ro cache */ - result = (char *)poll_disk_cache_get(cache_sf, blob_key, &size); + /* Close the list file for writing and wait for the updater to finish + * updating from the list. + */ + close_and_wait_for_list(list_file, list_filename); + result = (char *)disk_cache_get(cache_sf, blob_key, &size); /* Blob entry must present because it shall be retrieved from the * ro_cache.foz loaded from list at runtime */ @@ -1183,10 +1212,12 @@ TEST_F(Cache, DISABLED_List) fputs("no_cache/no_cache3\n", list_file); /* Add ro_cache to list file for loading */ fputs("ro_cache\n", list_file); - fclose(list_file); - /* Poll result to give time for updater to load ro cache */ - result = (char *)poll_disk_cache_get(cache_sf, blob_key, &size); + /* Close the list file for writing and wait for the updater to finish + * updating from the list. + */ + close_and_wait_for_list(list_file, list_filename); + result = (char *)disk_cache_get(cache_sf, blob_key, &size); /* Blob entry must present because it shall be retrieved from the * ro_cache.foz loaded from list at runtime despite invalid files