Keep the raw file alive while it is read without the lock

GetRawImage takes the chunk address under hdf5_mutex, drops the lock, and then reads through a
borrowed RawFile*. ReadFile() and Close() both take that same lock and call Clear(), which empties
the dataset cache and closes the descriptor - so a read racing a close read through a freed object
and a recycled fd. Not reachable today, since the only callers of GetRawImage are the rugnux workers
and jfjoch_extract_hkl and neither closes concurrently, but the whole point of the change is that
the read happens outside the lock.

Share the RawFile rather than borrowing it, so the descriptor outlives a Clear() that races it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VfYvJT5Nb71suJCowRBn5z
This commit is contained in:
2026-08-23 12:44:04 +02:00
co-authored by Claude Opus 5
parent c254081e58
commit 92f2e0309e
2 changed files with 7 additions and 4 deletions
+2 -2
View File
@@ -116,7 +116,7 @@ HDF5ImageSource::GetDataset(const HDF5ImageLocator::Location &loc) const {
entry.algorithm = dcpl.GetCompression();
if (entry.direct_chunk && !loc.path.empty()) {
entry.raw = std::make_unique<RawFile>(loc.path);
entry.raw = std::make_shared<RawFile>(loc.path);
if (!entry.raw->IsOpen())
entry.raw.reset();
hid_t fcpl = H5Fget_create_plist(loc.file->GetID());
@@ -148,7 +148,7 @@ HDF5ImageSource::PrepareDirectRead(const HDF5ImageLocator::Location &loc) const
if (address == HADDR_UNDEF || size == 0)
return {};
return DirectChunk{ds.raw.get(), ds.user_block + address, static_cast<uint32_t>(size),
return DirectChunk{ds.raw, ds.user_block + address, static_cast<uint32_t>(size),
ds.width, ds.height, ds.mode, ds.algorithm};
}