Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++][lit] Atomically update the persistent cache #66538

Merged
merged 1 commit into from
Sep 18, 2023

Conversation

arichardson
Copy link
Member

When running multiple shards in parallel, one shard might write to the cache while another one is reading this cache. Instead of updating the file in place, write to a temporary file and swap the cache file using os.replace(). This is an atomic operation and means shards will either see the old state or the new one.

@arichardson arichardson requested a review from ldionne September 15, 2023 19:24
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Sep 15, 2023
@llvmbot
Copy link
Member

llvmbot commented Sep 15, 2023

@llvm/pr-subscribers-libcxx

Changes

When running multiple shards in parallel, one shard might write to the cache while another one is reading this cache. Instead of updating the file in place, write to a temporary file and swap the cache file using os.replace(). This is an atomic operation and means shards will either see the old state or the new one.

Full diff: https://github.com/llvm/llvm-project/pull/66538.diff

1 Files Affected:

  • (modified) libcxx/utils/libcxx/test/dsl.py (+5-1)
diff --git a/libcxx/utils/libcxx/test/dsl.py b/libcxx/utils/libcxx/test/dsl.py
index 847cebf5962f6aa..7d4df6b01eabdae 100644
--- a/libcxx/utils/libcxx/test/dsl.py
+++ b/libcxx/utils/libcxx/test/dsl.py
@@ -69,8 +69,12 @@ def f(config, *args, **kwargs):
             if cacheKey not in cache:
                 cache[cacheKey] = function(config, *args, **kwargs)
                 # Update the persistent cache so it knows about the new key
-                with open(persistentCache, "wb") as cacheFile:
+                # We write to a temporary file and rename the result to ensure
+                # that the cahe is not corrupted when running the test suite
+                # with multiple shards.
+                with open(persistentCache + ".tmp", "wb") as cacheFile:
                     pickle.dump(cache, cacheFile)
+                os.replace(persistentCache + ".tmp", persistentCache)
             return cache[cacheKey]
 
         return f

@arichardson arichardson force-pushed the libcxx-lit-cache-atomic branch from d288487 to f3fc44c Compare September 15, 2023 19:27
@ldionne ldionne self-assigned this Sep 15, 2023
@@ -69,8 +69,12 @@ def f(config, *args, **kwargs):
if cacheKey not in cache:
cache[cacheKey] = function(config, *args, **kwargs)
# Update the persistent cache so it knows about the new key
with open(persistentCache, "wb") as cacheFile:
# We write to a temporary file and rename the result to ensure
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we have the same problem with the creation of the .tmp file now? Don't we need to generate a unique file name instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm that's a good point, in my limited testing this was enough to avoid the race, but really it should be a per-shard suffix. Will update to use the PID.

libcxx/utils/libcxx/test/dsl.py Show resolved Hide resolved
When running multiple shards in parallel, one shard might write to the
cache while another one is reading this cache. Instead of updating the
file in place, write to a temporary file and swap the cache file using
os.replace(). This is an atomic operation and means shards will either
see the old state or the new one.
@arichardson arichardson force-pushed the libcxx-lit-cache-atomic branch from f3fc44c to 5b36d6c Compare September 15, 2023 20:35
@arichardson arichardson requested a review from a team as a code owner September 15, 2023 20:35
@ldionne ldionne merged commit 14882d6 into llvm:main Sep 18, 2023
@arichardson arichardson deleted the libcxx-lit-cache-atomic branch September 18, 2023 16:11
ZijunZhaoCCK pushed a commit to ZijunZhaoCCK/llvm-project that referenced this pull request Sep 19, 2023
When running multiple shards in parallel, one shard might write to the
cache while another one is reading this cache. Instead of updating the
file in place, write to a temporary file and swap the cache file using
os.replace(). This is an atomic operation and means shards will either
see the old state or the new one.
zahiraam pushed a commit to tahonermann/llvm-project that referenced this pull request Oct 24, 2023
When running multiple shards in parallel, one shard might write to the
cache while another one is reading this cache. Instead of updating the
file in place, write to a temporary file and swap the cache file using
os.replace(). This is an atomic operation and means shards will either
see the old state or the new one.
zahiraam pushed a commit to tahonermann/llvm-project that referenced this pull request Oct 24, 2023
When running multiple shards in parallel, one shard might write to the
cache while another one is reading this cache. Instead of updating the
file in place, write to a temporary file and swap the cache file using
os.replace(). This is an atomic operation and means shards will either
see the old state or the new one.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants