Skip to content

Commit 6ee5bba

Browse files
Backport #72870 to 24.11: Fix use-after-free in loadPathPrefixMap on thread pool exception
1 parent ff9e15b commit 6ee5bba

1 file changed

Lines changed: 69 additions & 61 deletions

File tree

src/Disks/ObjectStorages/MetadataStorageFromPlainRewritableObjectStorage.cpp

Lines changed: 69 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -126,72 +126,80 @@ std::shared_ptr<InMemoryDirectoryPathMap> loadPathPrefixMap(const std::string &
126126

127127
std::mutex mutex;
128128
InMemoryDirectoryPathMap::Map map;
129-
for (auto iterator = object_storage->iterate(metadata_key_prefix, 0); iterator->isValid(); iterator->next())
129+
try
130130
{
131-
++num_files;
132-
auto file = iterator->current();
133-
String path = file->getPath();
134-
auto remote_metadata_path = std::filesystem::path(path);
135-
if (remote_metadata_path.filename() != PREFIX_PATH_FILE_NAME)
136-
continue;
137-
138-
runner(
139-
[remote_metadata_path, path, &object_storage, &mutex, &map, &log, &settings, &metadata_key_prefix]
140-
{
141-
setThreadName("PlainRWMetaLoad");
131+
for (auto iterator = object_storage->iterate(metadata_key_prefix, 0); iterator->isValid(); iterator->next())
132+
{
133+
++num_files;
134+
auto file = iterator->current();
135+
String path = file->getPath();
136+
auto remote_metadata_path = std::filesystem::path(path);
137+
if (remote_metadata_path.filename() != PREFIX_PATH_FILE_NAME)
138+
continue;
139+
140+
runner(
141+
[remote_metadata_path, path, &object_storage, &mutex, &map, &log, &settings, &metadata_key_prefix]
142+
{
143+
setThreadName("PlainRWMetaLoad");
142144

143-
StoredObject object{path};
144-
String local_path;
145-
Poco::Timestamp last_modified{};
145+
StoredObject object{path};
146+
String local_path;
147+
Poco::Timestamp last_modified{};
146148

147-
try
148-
{
149-
auto read_buf = object_storage->readObject(object, settings);
150-
readStringUntilEOF(local_path, *read_buf);
151-
auto object_metadata = object_storage->tryGetObjectMetadata(path);
152-
/// It ok if a directory was removed just now.
153-
/// We support attaching a filesystem that is concurrently modified by someone else.
154-
if (!object_metadata)
155-
return;
156-
/// Assuming that local and the object storage clocks are synchronized.
157-
last_modified = object_metadata->last_modified;
158-
}
159-
#if USE_AWS_S3
160-
catch (const S3Exception & e)
161-
{
162-
/// It is ok if a directory was removed just now.
163-
if (e.getS3ErrorCode() == Aws::S3::S3Errors::NO_SUCH_KEY)
164-
return;
165-
throw;
166-
}
167-
#endif
168-
catch (...)
169-
{
170-
throw;
171-
}
149+
try
150+
{
151+
auto read_buf = object_storage->readObject(object, settings);
152+
readStringUntilEOF(local_path, *read_buf);
153+
auto object_metadata = object_storage->tryGetObjectMetadata(path);
154+
/// It ok if a directory was removed just now.
155+
/// We support attaching a filesystem that is concurrently modified by someone else.
156+
if (!object_metadata)
157+
return;
158+
/// Assuming that local and the object storage clocks are synchronized.
159+
last_modified = object_metadata->last_modified;
160+
}
161+
#if USE_AWS_S3
162+
catch (const S3Exception & e)
163+
{
164+
/// It is ok if a directory was removed just now.
165+
if (e.getS3ErrorCode() == Aws::S3::S3Errors::NO_SUCH_KEY)
166+
return;
167+
throw;
168+
}
169+
#endif
170+
catch (...)
171+
{
172+
throw;
173+
}
172174

173-
chassert(remote_metadata_path.has_parent_path());
174-
chassert(remote_metadata_path.string().starts_with(metadata_key_prefix));
175-
auto suffix = remote_metadata_path.string().substr(metadata_key_prefix.size());
176-
auto rel_path = std::filesystem::path(std::move(suffix));
177-
std::pair<Map::iterator, bool> res;
178-
{
179-
std::lock_guard lock(mutex);
180-
res = map.emplace(
181-
std::filesystem::path(local_path).parent_path(),
182-
InMemoryDirectoryPathMap::RemotePathInfo{rel_path.parent_path(), last_modified.epochTime(), {}});
183-
}
175+
chassert(remote_metadata_path.has_parent_path());
176+
chassert(remote_metadata_path.string().starts_with(metadata_key_prefix));
177+
auto suffix = remote_metadata_path.string().substr(metadata_key_prefix.size());
178+
auto rel_path = std::filesystem::path(std::move(suffix));
179+
std::pair<Map::iterator, bool> res;
180+
{
181+
std::lock_guard lock(mutex);
182+
res = map.emplace(
183+
std::filesystem::path(local_path).parent_path(),
184+
InMemoryDirectoryPathMap::RemotePathInfo{rel_path.parent_path(), last_modified.epochTime(), {}});
185+
}
184186

185-
/// This can happen if table replication is enabled, then the same local path is written
186-
/// in `prefix.path` of each replica.
187-
if (!res.second)
188-
LOG_WARNING(
189-
log,
190-
"The local path '{}' is already mapped to a remote path '{}', ignoring: '{}'",
191-
local_path,
192-
res.first->second.path,
193-
rel_path.parent_path().string());
194-
});
187+
/// This can happen if table replication is enabled, then the same local path is written
188+
/// in `prefix.path` of each replica.
189+
if (!res.second)
190+
LOG_WARNING(
191+
log,
192+
"The local path '{}' is already mapped to a remote path '{}', ignoring: '{}'",
193+
local_path,
194+
res.first->second.path,
195+
rel_path.parent_path().string());
196+
});
197+
}
198+
}
199+
catch (...)
200+
{
201+
runner.waitForAllToFinish();
202+
throw;
195203
}
196204

197205
runner.waitForAllToFinishAndRethrowFirstError();

0 commit comments

Comments
 (0)