Skip to content

Commit d458a4a

Browse files
ktfdavidrohr
authored andcommitted
DPL: have input proxy wait for EoS
A race condition is currently possible where if there is no data still to be processed on the external and we quit too quickly missing the EoS.
1 parent 432f7c9 commit d458a4a

2 files changed

Lines changed: 26 additions & 3 deletions

File tree

Framework/Core/src/DataProcessingDevice.cxx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,12 @@ void DataProcessingDevice::doPrepare(DataProcessorContext& context)
965965
// to be completed. In the case of data source devices, as they do not have
966966
// real data input channels, they have to signal EndOfStream themselves.
967967
context.allDone = std::any_of(context.deviceContext->state->inputChannelInfos.begin(), context.deviceContext->state->inputChannelInfos.end(), [](const auto& info) {
968-
return info.parts.fParts.empty() == true && info.state != InputChannelState::Pull;
968+
if (info.channel) {
969+
LOGP(debug, "Input channel {}{} has {} parts left and is in state {}.", info.channel->GetName(), (info.id.value == ChannelIndex::INVALID ? " (non DPL)" : ""), info.parts.fParts.size(), (int)info.state);
970+
} else {
971+
LOGP(debug, "External channel {} is in state {}.", info.id.value, (int)info.state);
972+
}
973+
return (info.parts.fParts.empty() == true && info.state != InputChannelState::Pull);
969974
});
970975

971976
// Whether or not all the channels are completed
@@ -1016,6 +1021,9 @@ void DataProcessingDevice::doPrepare(DataProcessorContext& context)
10161021
LOGP(debug, "Flushing channel {} which is in state {} and has {} parts still pending.", channelSpec.name, (int)info.state, info.parts.Size());
10171022
continue;
10181023
}
1024+
if (info.channel == nullptr) {
1025+
continue;
1026+
}
10191027
auto& socket = info.channel->GetSocket();
10201028
// If we have pending events from a previous iteration,
10211029
// we do receive in any case.

Framework/Core/src/ExternalFairMQDeviceProxy.cxx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "Framework/CallbackService.h"
2222
#include "Framework/ControlService.h"
2323
#include "Framework/SourceInfoHeader.h"
24+
#include "Framework/ChannelInfo.h"
2425
#include "Framework/ConfigParamRegistry.h"
2526
#include "Framework/RateLimiter.h"
2627
#include "Framework/TimingInfo.h"
@@ -397,17 +398,27 @@ DataProcessorSpec specifyExternalFairMQDeviceProxy(char const* name,
397398
// will be multiple channels. At least we throw a more informative exception.
398399
// fair::mq::Device calls the custom init before the channels have been configured
399400
// so we do the check before starting in a dedicated callback
400-
auto channelConfigurationChecker = [channel, device]() {
401+
auto channelConfigurationChecker = [channel, device, &services = ctx.services()]() {
402+
auto& deviceState = services.get<DeviceState>();
401403
if (device->fChannels.count(channel) == 0) {
402404
throw std::runtime_error("the required out-of-band channel '" + channel + "' has not been configured, please check the name in the channel configuration");
403405
}
406+
LOGP(detail, "Injecting channel '{}' into DPL configuration", channel);
407+
// Converter should pump messages
408+
deviceState.inputChannelInfos.push_back(InputChannelInfo{
409+
.state = InputChannelState::Running,
410+
.hasPendingEvents = false,
411+
.readPolled = false,
412+
.channel = nullptr,
413+
.id = {ChannelIndex::INVALID},
414+
});
404415
};
405416
ctx.services().get<CallbackService>().set(CallbackService::Id::Start, channelConfigurationChecker);
406-
// Converter should pump messages
407417

408418
auto dataHandler = [device, converter,
409419
outputRoutes = std::move(outputRoutes),
410420
control = &ctx.services().get<ControlService>(),
421+
deviceState = &ctx.services().get<DeviceState>(),
411422
&timingInfo = ctx.services().get<TimingInfo>(),
412423
outputChannels = std::move(outputChannels)](fair::mq::Parts& inputs, int) {
413424
// pass a copy of the outputRoutes
@@ -436,6 +447,10 @@ DataProcessorSpec specifyExternalFairMQDeviceProxy(char const* name,
436447
converter(timingInfo, *device, inputs, channelRetriever);
437448

438449
if (doEos) {
450+
// Mark all input channels as closed
451+
for (auto& info : deviceState->inputChannelInfos) {
452+
info.state = InputChannelState::Completed;
453+
}
439454
control->endOfStream();
440455
}
441456
};

0 commit comments

Comments
 (0)