Files
Jungfraujoch/common/ZeroCopyReturnValue.cpp
T
leonarski_fandClaude Opus 5 89208697cb common: reset the slot status before putting it back on the free list
release() published the handle through ReleaseSlot and only then wrote
status = InPreparation. ReleaseSlot makes the handle available to
GetImageSlot immediately, and GetImageSlot hands back this very object
without resetting it, so the receiver could observe the stale Sending
status and throw "Trying to send image that is not in preparation",
aborting the collection - or take the opposite interleaving and leak the
slot.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 14:41:13 +02:00

70 lines
2.1 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "ZeroCopyReturnValue.h"
#include "ImageBuffer.h"
#include "ThreadSafeFIFO.h"
ZeroCopyReturnValue::ZeroCopyReturnValue(void *in_ptr, ImageBuffer &in_ctrl, uint32_t in_handle)
: ptr(in_ptr), payload_size(0), image_number(-1), buf_ctrl(in_ctrl), handle(in_handle),
indexed(false) {
}
void ZeroCopyReturnValue::SetImageNumber(int64_t in_image_number) {
image_number = in_image_number;
}
void ZeroCopyReturnValue::SetImageSize(size_t in_payload_size) {
payload_size = in_payload_size;
}
size_t ZeroCopyReturnValue::GetImageSize() const {
return payload_size;
}
void *ZeroCopyReturnValue::GetImage() const {
return ptr;
}
void ZeroCopyReturnValue::release() {
if (status == ImageBufferEntryStatus::InPreparation)
ReadyToSend();
if (status == ImageBufferEntryStatus::Sending) {
// Reset before releasing: ReleaseSlot puts the handle back on the free list, after which
// another thread can take this same object out of GetImageSlot() and read status.
status = ImageBufferEntryStatus::InPreparation;
buf_ctrl.ReleaseSlot(handle);
} else {
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Trying to send image that is not in preparation");
}
}
int64_t ZeroCopyReturnValue::GetImageNumber() const {
return image_number;
}
void ZeroCopyReturnValue::SetIndexed(bool input) {
indexed = input;
}
bool ZeroCopyReturnValue::IsIndexed() const {
return indexed;
}
uint32_t ZeroCopyReturnValue::GetHandle() const {
return handle;
}
void ZeroCopyReturnValue::ReadyToSend() {
if (status == ImageBufferEntryStatus::InPreparation) {
buf_ctrl.ReadyToSend(handle, image_number, payload_size, indexed);
status = ImageBufferEntryStatus::Sending;
} else {
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Trying to send image that is not in preparation");
}
}