mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
module: do not split a portable compile cache by uid
A portable compile cache is meant to be reused wherever the same module layout is found, which includes being generated once (at build time, say) and shipped read-only with an application for whoever runs it. On platforms with uids the cache subdirectory is suffixed with the uid of the user who created it, so such a cache is only ever found by that one user. Omit the suffix in portable mode: a user who cannot write to the directory still reads it, and a failed write is only a cache miss. Signed-off-by: Shelley Vohr <shelley.vohr@gmail.com> PR-URL: https://github.com/nodejs/node/pull/65293 Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
1 parent
9d94b6548a
commit
adad4d650d
5 files changed
+36
-10
No files matched your search
+3
-2
@@ -3736,8 +3736,9 @@ Enable the [module compile cache][] for the Node.js instance. See the documentat
|
||||
|
||||
### `NODE_COMPILE_CACHE_PORTABLE=1`
|
||||
|
||||
When set to 1, the [module compile cache][] can be reused across different directory
|
||||
locations as long as the module layout relative to the cache directory remains the same.
|
||||
When set to 1, the [module compile cache][] can be reused across different directory
|
||||
locations as long as the module layout relative to the cache directory remains the same,
|
||||
and by any user (the cache subdirectory is not suffixed with the creating user's uid).
|
||||
|
||||
### `NODE_DEBUG=module[,…]`
|
||||
|
||||
|
||||
@@ -407,6 +407,14 @@ to the cache directory remains the same. This would be done on a best-effort bas
|
||||
Node.js cannot compute the location of a module relative to the cache directory, the module
|
||||
will not be cached.
|
||||
|
||||
A portable cache is also not split by user: on platforms with uids the
|
||||
cache subdirectory of a non-portable cache is suffixed with the uid of the
|
||||
user who created it, so it is only found by that user, while a portable
|
||||
cache uses the same subdirectory for every user. This lets a cache generated
|
||||
once (for example at build time, then shipped read-only with an application)
|
||||
be read by whoever runs the code; a user who cannot write to the directory
|
||||
still reads it, and a failed write only means the module is compiled again.
|
||||
|
||||
There are two ways to enable the portable mode:
|
||||
|
||||
1. Using the portable option in [`module.enableCompileCache()`][]:
|
||||
|
||||
+3
-2
@@ -1860,8 +1860,9 @@ Enable the module compile cache for the Node.js instance. See the documentation
|
||||
module compile cache for details.
|
||||
.
|
||||
.It Ev NODE_COMPILE_CACHE_PORTABLE Ar 1
|
||||
When set to 1, the module compile cache can be reused across different directory
|
||||
locations as long as the module layout relative to the cache directory remains the same.
|
||||
When set to 1, the module compile cache can be reused across different directory
|
||||
locations as long as the module layout relative to the cache directory remains the same,
|
||||
and by any user (the cache subdirectory is not suffixed with the creating user's uid).
|
||||
.
|
||||
.It Ev NODE_DEBUG Ar module[,…]
|
||||
\fB','\fR-separated list of core modules that should print debug information.
|
||||
|
||||
+14
-6
@@ -44,16 +44,23 @@ uint32_t GetHash(const char* data, size_t size) {
|
||||
return crc32(crc, reinterpret_cast<const Bytef*>(data), size);
|
||||
}
|
||||
|
||||
std::string GetCacheVersionTag() {
|
||||
std::string GetCacheVersionTag(EnableOption option) {
|
||||
std::string tag = std::string(NODE_VERSION) + '-' + std::string(NODE_ARCH) +
|
||||
'-' + Uint32ToHex(ScriptCompiler::CachedDataVersionTag());
|
||||
#ifdef NODE_IMPLEMENTS_POSIX_CREDENTIALS
|
||||
// On platforms where uids are available, use different folders for
|
||||
// different users to avoid cache miss due to permission incompatibility.
|
||||
// On platforms where uids are not available, bare with the cache miss.
|
||||
// This should be fine on Windows, as there local directories tend to be
|
||||
// user-specific.
|
||||
std::string tag = std::string(NODE_VERSION) + '-' + std::string(NODE_ARCH) +
|
||||
'-' + Uint32ToHex(ScriptCompiler::CachedDataVersionTag());
|
||||
#ifdef NODE_IMPLEMENTS_POSIX_CREDENTIALS
|
||||
tag += '-' + std::to_string(getuid());
|
||||
// A portable cache is meant to be reused wherever the same layout is
|
||||
// found, including by other users (e.g. a cache generated at build time
|
||||
// and shipped read-only with an application), so it is not split by uid:
|
||||
// a user who cannot write to it still reads it, and a failed write is
|
||||
// only a cache miss.
|
||||
if (option != EnableOption::PORTABLE) {
|
||||
tag += '-' + std::to_string(getuid());
|
||||
}
|
||||
#endif
|
||||
return tag;
|
||||
}
|
||||
@@ -532,11 +539,12 @@ CompileCacheHandler::CompileCacheHandler(Environment* env)
|
||||
// Directory structure:
|
||||
// - Compile cache directory (from NODE_COMPILE_CACHE)
|
||||
// - $NODE_VERSION-$ARCH-$CACHE_DATA_VERSION_TAG-$UID
|
||||
// ($UID is omitted for a portable cache)
|
||||
// - $FILENAME_AND_MODULE_TYPE_HASH.cache: a hash of filename + module type
|
||||
CompileCacheEnableResult CompileCacheHandler::Enable(Environment* env,
|
||||
const std::string& dir,
|
||||
EnableOption option) {
|
||||
std::string cache_tag = GetCacheVersionTag();
|
||||
std::string cache_tag = GetCacheVersionTag(option);
|
||||
std::string absolute_cache_dir_base = PathResolve(env, {dir});
|
||||
std::string cache_dir_with_tag =
|
||||
absolute_cache_dir_base + kPathSeparator + cache_tag;
|
||||
|
||||
@@ -57,6 +57,14 @@ const NODE_TEST_COMPILE_CACHE_OPTIONS = JSON.stringify({ directory: cacheRel, po
|
||||
);
|
||||
}
|
||||
|
||||
// The cache subdirectory of a portable cache is not suffixed with the uid,
|
||||
// so a cache generated by one user is found by another.
|
||||
{
|
||||
const [tag] = fs.readdirSync(path.join(workDir, cacheRel));
|
||||
// $NODE_VERSION-$ARCH-$CACHE_DATA_VERSION_TAG, with no -$UID.
|
||||
assert.match(tag, new RegExp(`^${process.version}-${process.arch}-[0-9a-f]+$`));
|
||||
}
|
||||
|
||||
// Second run — moved directory, but same relative cache path
|
||||
{
|
||||
const movedWorkDir = `${workDir}_moved`;
|
||||
|
||||
Reference in new issue
Block a user