From af8027d0f81d2c4892ee0ea156ea58e473a97165 Mon Sep 17 00:00:00 2001 From: "W. David Dagenhart" Date: Sat, 25 May 2024 00:13:03 +0200 Subject: [PATCH] Improve behavior after exception in begin/end transitions This PR covers job, stream, and ProcessBlock --- FWCore/Framework/bin/cmsRun.cpp | 9 +- FWCore/Framework/interface/EventProcessor.h | 9 + FWCore/Framework/interface/GlobalSchedule.h | 26 +- FWCore/Framework/interface/Schedule.h | 14 +- FWCore/Framework/interface/StreamSchedule.h | 41 +-- FWCore/Framework/interface/SubProcess.h | 11 +- FWCore/Framework/interface/WorkerManager.h | 12 +- FWCore/Framework/interface/maker/Worker.h | 27 +- FWCore/Framework/src/EventProcessor.cc | 189 +++++----- FWCore/Framework/src/GlobalSchedule.cc | 87 ++++- FWCore/Framework/src/Schedule.cc | 29 +- FWCore/Framework/src/StreamSchedule.cc | 98 +++++- FWCore/Framework/src/SubProcess.cc | 71 +++- FWCore/Framework/src/Worker.cc | 207 ++++++----- FWCore/Framework/src/WorkerManager.cc | 100 ++++-- .../test/one_outputmodule_t.cppunit.cc | 4 +- .../Framework/test/stream_filter_t.cppunit.cc | 20 +- .../test/stream_producer_t.cppunit.cc | 20 +- .../test_deepCall_unscheduled.log | 5 + .../test_onPath_unscheduled.log | 5 + .../plugins/ExceptionThrowingProducer.cc | 331 ++++++++++++++++-- FWCore/Integration/plugins/TestServiceOne.cc | 261 +++++++++++++- FWCore/Integration/plugins/TestServiceOne.h | 88 +++++ FWCore/Integration/test/BuildFile.xml | 2 +- .../run_TestFrameworkExceptionHandling.sh | 98 ++++-- .../testFrameworkExceptionHandling_cfg.py | 56 ++- .../test/unit_test_outputs/testGetBy1.log | 11 +- .../test/unit_test_outputs/testGetBy2.log | 5 + .../testSubProcess.grep2.txt | 29 +- .../interface/ActivityRegistry.h | 54 ++- .../ServiceRegistry/interface/GlobalContext.h | 5 + .../interface/ServiceRegistryfwd.h | 1 + .../ServiceRegistry/interface/StreamContext.h | 8 +- .../ServiceRegistry/src/ActivityRegistry.cc | 146 +------- FWCore/ServiceRegistry/src/GlobalContext.cc | 11 + FWCore/Services/plugins/Tracer.cc | 32 ++ FWCore/TestProcessor/src/TestProcessor.cc | 10 +- FWCore/Utilities/src/ExceptionCollector.cc | 4 +- .../plugins/RandomNumberGeneratorService.cc | 31 +- .../plugins/RandomNumberGeneratorService.h | 7 + Mixing/Base/interface/PileUp.h | 2 + Mixing/Base/src/BMixingModule.cc | 14 +- Mixing/Base/src/PileUp.cc | 30 +- Mixing/Base/src/SecondaryEventProvider.cc | 18 +- Mixing/Base/src/SecondaryEventProvider.h | 13 +- 45 files changed, 1663 insertions(+), 588 deletions(-) diff --git a/FWCore/Framework/bin/cmsRun.cpp b/FWCore/Framework/bin/cmsRun.cpp index 69da61ce3c999..eb7daeb22c950 100644 --- a/FWCore/Framework/bin/cmsRun.cpp +++ b/FWCore/Framework/bin/cmsRun.cpp @@ -267,8 +267,11 @@ int main(int argc, const char* argv[]) { TaskCleanupSentry sentry{proc.get()}; alwaysAddContext = false; + + proc.on(); context = "Calling beginJob"; proc->beginJob(); + // EventSetupsController uses pointers to the ParameterSet // owned by ProcessDesc while it is dealing with sharing of // ESProducers among the top-level process and the @@ -276,17 +279,15 @@ int main(int argc, const char* argv[]) { // alive until the beginJob transition has finished. processDesc.reset(); - alwaysAddContext = false; context = "Calling EventProcessor::runToCompletion (which does almost everything after beginJob and before endJob)"; - proc.on(); auto status = proc->runToCompletion(); if (status == edm::EventProcessor::epSignal) { returnCode = edm::errors::CaughtSignal; } - proc.off(); - context = "Calling endJob"; + proc.off(); + context = "Calling endJob and endStream"; proc->endJob(); }); return returnCode; diff --git a/FWCore/Framework/interface/EventProcessor.h b/FWCore/Framework/interface/EventProcessor.h index cb54d52085dd0..967b171e01fde 100644 --- a/FWCore/Framework/interface/EventProcessor.h +++ b/FWCore/Framework/interface/EventProcessor.h @@ -35,6 +35,8 @@ configured in the user's main() function, and is set running. #include "FWCore/Utilities/interface/get_underlying_safe.h" #include "FWCore/Utilities/interface/propagate_const.h" +#include "oneapi/tbb/task_group.h" + #include #include #include @@ -46,6 +48,7 @@ configured in the user's main() function, and is set running. namespace edm { + class ExceptionCollector; class ExceptionToActionTable; class BranchIDListHelper; class MergeableRunProductMetadata; @@ -120,6 +123,10 @@ namespace edm { */ void beginJob(); + void beginStreams(); + + void endStreams(ExceptionCollector&) noexcept; + /**This should be called before the EventProcessor is destroyed throws if any module's endJob throws an exception. */ @@ -351,6 +358,8 @@ namespace edm { std::shared_ptr sourceMutex_; PrincipalCache principalCache_; bool beginJobCalled_; + bool beginJobStartedModules_ = false; + bool beginJobSucceeded_ = false; bool shouldWeStop_; bool fileModeNoMerge_; std::string exceptionMessageFiles_; diff --git a/FWCore/Framework/interface/GlobalSchedule.h b/FWCore/Framework/interface/GlobalSchedule.h index f87b1f03789cb..cc439a160da12 100644 --- a/FWCore/Framework/interface/GlobalSchedule.h +++ b/FWCore/Framework/interface/GlobalSchedule.h @@ -17,6 +17,7 @@ #include "FWCore/MessageLogger/interface/ExceptionMessages.h" #include "FWCore/ServiceRegistry/interface/GlobalContext.h" #include "FWCore/ServiceRegistry/interface/ServiceRegistry.h" +#include "FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h" #include "FWCore/ServiceRegistry/interface/ServiceToken.h" #include "FWCore/Utilities/interface/Algorithms.h" #include "FWCore/Utilities/interface/BranchType.h" @@ -38,9 +39,7 @@ namespace edm { - class ActivityRegistry; class ExceptionCollector; - class ProcessContext; class PreallocationConfiguration; class ModuleRegistry; class TriggerResultInserter; @@ -76,7 +75,9 @@ namespace edm { void beginJob(ProductRegistry const&, eventsetup::ESRecordsToProductResolverIndices const&, - ProcessBlockHelperBase const&); + ProcessBlockHelperBase const&, + PathsAndConsumesOfModulesBase const&, + ProcessContext const&); void endJob(ExceptionCollector& collector); /// Return a vector allowing const access to all the @@ -118,7 +119,14 @@ namespace edm { std::shared_ptr actReg_; // We do not use propagate_const because the registry itself is mutable. std::vector> extraWorkers_; ProcessContext const* processContext_; + + // The next 4 variables use the same naming convention, even though we have no intention + // to ever have concurrent ProcessBlocks or Jobs. They are all related to the number of + // WorkerManagers needed for global transitions. unsigned int numberOfConcurrentLumis_; + unsigned int numberOfConcurrentRuns_; + static constexpr unsigned int numberOfConcurrentProcessBlocks_ = 1; + static constexpr unsigned int numberOfConcurrentJobs_ = 1; }; template @@ -155,6 +163,8 @@ namespace edm { unsigned int managerIndex = principal.index(); if constexpr (T::branchType_ == InRun) { managerIndex += numberOfConcurrentLumis_; + } else if constexpr (T::branchType_ == InProcess) { + managerIndex += (numberOfConcurrentLumis_ + numberOfConcurrentRuns_); } WorkerManager& workerManager = workerManagers_[managerIndex]; workerManager.resetAll(); @@ -184,10 +194,7 @@ namespace edm { ServiceRegistry::Operate op(token); convertException::wrap([this, globalContext]() { T::preScheduleSignal(actReg_.get(), globalContext); }); } catch (cms::Exception& ex) { - std::ostringstream ost; - ex.addContext("Handling pre signal, likely in a service function"); - exceptionContext(ost, *globalContext); - ex.addContext(ost.str()); + exceptionContext(ex, *globalContext, "Handling pre signal, likely in a service function"); throw; } } @@ -205,10 +212,7 @@ namespace edm { }); } catch (cms::Exception& ex) { if (not excpt) { - std::ostringstream ost; - ex.addContext("Handling post signal, likely in a service function"); - exceptionContext(ost, *globalContext); - ex.addContext(ost.str()); + exceptionContext(ex, *globalContext, "Handling post signal, likely in a service function"); excpt = std::current_exception(); } } diff --git a/FWCore/Framework/interface/Schedule.h b/FWCore/Framework/interface/Schedule.h index 1a5ba337d0b35..4216862fae441 100644 --- a/FWCore/Framework/interface/Schedule.h +++ b/FWCore/Framework/interface/Schedule.h @@ -74,9 +74,9 @@ #include "FWCore/MessageLogger/interface/JobReport.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h" #include "FWCore/Utilities/interface/Algorithms.h" #include "FWCore/Utilities/interface/BranchType.h" -#include "FWCore/Utilities/interface/ConvertException.h" #include "FWCore/Utilities/interface/Exception.h" #include "FWCore/Utilities/interface/StreamID.h" #include "FWCore/Utilities/interface/get_underlying_safe.h" @@ -85,6 +85,7 @@ #include #include #include +#include #include #include #include @@ -100,13 +101,11 @@ namespace edm { class ESRecordsToProductResolverIndices; } - class ActivityRegistry; class BranchIDListHelper; class EventTransitionInfo; class ExceptionCollector; class MergeableRunProductMetadata; class OutputModuleCommunicator; - class ProcessContext; class ProductRegistry; class PreallocationConfiguration; class StreamSchedule; @@ -171,11 +170,14 @@ namespace edm { void beginJob(ProductRegistry const&, eventsetup::ESRecordsToProductResolverIndices const&, - ProcessBlockHelperBase const&); + ProcessBlockHelperBase const&, + PathsAndConsumesOfModulesBase const&, + ProcessContext const&); void endJob(ExceptionCollector& collector); + void sendFwkSummaryToMessageLogger() const; - void beginStream(unsigned int); - void endStream(unsigned int); + void beginStream(unsigned int streamID); + void endStream(unsigned int streamID, ExceptionCollector& collector, std::mutex& collectorMutex) noexcept; // Write the luminosity block void writeLumiAsync(WaitingTaskHolder iTask, diff --git a/FWCore/Framework/interface/StreamSchedule.h b/FWCore/Framework/interface/StreamSchedule.h index ca727fa719335..09614920c13c9 100644 --- a/FWCore/Framework/interface/StreamSchedule.h +++ b/FWCore/Framework/interface/StreamSchedule.h @@ -75,7 +75,9 @@ #include "FWCore/MessageLogger/interface/JobReport.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" #include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/ServiceRegistry/interface/ServiceRegistry.h" #include "FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h" +#include "FWCore/ServiceRegistry/interface/ServiceToken.h" #include "FWCore/ServiceRegistry/interface/StreamContext.h" #include "FWCore/Concurrency/interface/FunctorTask.h" #include "FWCore/Concurrency/interface/WaitingTaskHolder.h" @@ -88,8 +90,10 @@ #include "FWCore/Utilities/interface/propagate_const.h" #include "FWCore/Utilities/interface/thread_safety_macros.h" +#include #include #include +#include #include #include #include @@ -111,8 +115,6 @@ namespace edm { class PathStatusInserter; class EndPathStatusInserter; class PreallocationConfiguration; - class WaitingTaskHolder; - class ConditionalTaskHelper; namespace service { @@ -123,7 +125,6 @@ namespace edm { public: typedef std::vector vstring; typedef std::vector TrigPaths; - typedef std::vector NonTrigPaths; typedef std::shared_ptr TrigResPtr; typedef std::shared_ptr TrigResConstPtr; typedef std::shared_ptr WorkerPtr; @@ -162,7 +163,7 @@ namespace edm { bool cleaningUpAfterException = false); void beginStream(); - void endStream(); + void endStream(ExceptionCollector& collector, std::mutex& collectorMutex) noexcept; StreamID streamID() const { return streamID_; } @@ -306,12 +307,9 @@ namespace edm { void preScheduleSignal(StreamContext const*) const; template - void postScheduleSignal(StreamContext const*, ServiceWeakToken const&, std::exception_ptr&) const noexcept; + void postScheduleSignal(StreamContext const*, std::exception_ptr&) const noexcept; - void handleException(StreamContext const&, - ServiceWeakToken const&, - bool cleaningUpAfterException, - std::exception_ptr&) const noexcept; + void handleException(StreamContext const&, bool cleaningUpAfterException, std::exception_ptr&) const noexcept; WorkerManager workerManagerBeginEnd_; WorkerManager workerManagerRuns_; @@ -370,11 +368,15 @@ namespace edm { auto doneTask = make_waiting_task([this, iHolder = std::move(iHolder), cleaningUpAfterException, weakToken]( std::exception_ptr const* iPtr) mutable { std::exception_ptr excpt; - if (iPtr) { - excpt = *iPtr; - handleException(streamContext_, weakToken, cleaningUpAfterException, excpt); - } - postScheduleSignal(&streamContext_, weakToken, excpt); + { + ServiceRegistry::Operate op(weakToken.lock()); + + if (iPtr) { + excpt = *iPtr; + handleException(streamContext_, cleaningUpAfterException, excpt); + } + postScheduleSignal(&streamContext_, excpt); + } // release service token before calling doneWaiting iHolder.doneWaiting(excpt); }); @@ -391,7 +393,10 @@ namespace edm { preScheduleSignal(&streamContext_); workerManager->resetAll(); } catch (...) { - h.doneWaiting(std::current_exception()); + // Just remember the exception at this point, + // let the destructor of h call doneWaiting() so the + // ServiceRegistry::Operator object is destroyed first + h.presetTaskAsFailed(std::current_exception()); return; } @@ -430,13 +435,9 @@ namespace edm { template void StreamSchedule::postScheduleSignal(StreamContext const* streamContext, - ServiceWeakToken const& weakToken, std::exception_ptr& excpt) const noexcept { try { - convertException::wrap([this, &weakToken, streamContext]() { - ServiceRegistry::Operate op(weakToken.lock()); - T::postScheduleSignal(actReg_.get(), streamContext); - }); + convertException::wrap([this, streamContext]() { T::postScheduleSignal(actReg_.get(), streamContext); }); } catch (cms::Exception& ex) { if (not excpt) { std::ostringstream ost; diff --git a/FWCore/Framework/interface/SubProcess.h b/FWCore/Framework/interface/SubProcess.h index 2a99f0578feff..5cc9ccce32ec9 100644 --- a/FWCore/Framework/interface/SubProcess.h +++ b/FWCore/Framework/interface/SubProcess.h @@ -13,6 +13,7 @@ #include "FWCore/Framework/interface/ProductSelector.h" #include "FWCore/ServiceRegistry/interface/ProcessContext.h" #include "FWCore/ServiceRegistry/interface/ServiceLegacy.h" +#include "FWCore/ServiceRegistry/interface/ServiceRegistry.h" #include "FWCore/ServiceRegistry/interface/ServiceToken.h" #include "FWCore/Utilities/interface/Algorithms.h" #include "FWCore/Utilities/interface/BranchType.h" @@ -23,6 +24,7 @@ #include #include +#include #include #include @@ -32,6 +34,7 @@ namespace edm { class BranchIDListHelper; class EventPrincipal; class EventSetupImpl; + class ExceptionCollector; class HistoryAppender; class LuminosityBlockPrincipal; class LumiTransitionInfo; @@ -86,7 +89,7 @@ namespace edm { std::vector keepOnlyConsumedUnscheduledModules(bool deleteModules); void doBeginJob(); - void doEndJob(); + void doEndJob(ExceptionCollector&); void doEventAsync(WaitingTaskHolder iHolder, EventPrincipal const& principal, @@ -113,8 +116,8 @@ namespace edm { LumiTransitionInfo const& iTransitionInfo, bool cleaningUpAfterException); - void doBeginStream(unsigned int); - void doEndStream(unsigned int); + void doBeginStream(unsigned int streamID); + void doEndStream(unsigned int streamID, ExceptionCollector& collector, std::mutex& collectorMutex) noexcept; void doStreamBeginRunAsync(WaitingTaskHolder iHolder, unsigned int iID, RunTransitionInfo const&); void doStreamEndRunAsync(WaitingTaskHolder iHolder, @@ -238,7 +241,7 @@ namespace edm { private: void beginJob(); - void endJob(); + void endJob(ExceptionCollector&); void processAsync(WaitingTaskHolder iHolder, EventPrincipal const& e, std::vector> const*); diff --git a/FWCore/Framework/interface/WorkerManager.h b/FWCore/Framework/interface/WorkerManager.h index 1462902ceace2..f3da4d96e60be 100644 --- a/FWCore/Framework/interface/WorkerManager.h +++ b/FWCore/Framework/interface/WorkerManager.h @@ -5,11 +5,13 @@ #include "FWCore/Framework/interface/Frameworkfwd.h" #include "FWCore/Framework/interface/UnscheduledCallProducer.h" #include "FWCore/Framework/interface/WorkerRegistry.h" +#include "FWCore/ServiceRegistry/interface/ParentContext.h" #include "FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h" #include "FWCore/Concurrency/interface/WaitingTaskHolder.h" #include "FWCore/Utilities/interface/StreamID.h" #include +#include #include #include #include @@ -70,12 +72,12 @@ namespace edm { void beginJob(ProductRegistry const& iRegistry, eventsetup::ESRecordsToProductResolverIndices const&, - ProcessBlockHelperBase const&); - void endJob(); - void endJob(ExceptionCollector& collector); + ProcessBlockHelperBase const&, + GlobalContext const&); + void endJob(ExceptionCollector&, GlobalContext const&); - void beginStream(StreamID iID, StreamContext& streamContext); - void endStream(StreamID iID, StreamContext& streamContext); + void beginStream(StreamID, StreamContext const&); + void endStream(StreamID, StreamContext const&, ExceptionCollector&, std::mutex& collectorMutex) noexcept; AllWorkers const& allWorkers() const { return allWorkers_; } AllWorkers const& unscheduledWorkers() const { return unscheduled_.workers(); } diff --git a/FWCore/Framework/interface/maker/Worker.h b/FWCore/Framework/interface/maker/Worker.h index 9f438164e1f69..06de21a714a68 100644 --- a/FWCore/Framework/interface/maker/Worker.h +++ b/FWCore/Framework/interface/maker/Worker.h @@ -43,6 +43,7 @@ the worker is reset(). #include "FWCore/ServiceRegistry/interface/PathContext.h" #include "FWCore/ServiceRegistry/interface/PlaceInPathContext.h" #include "FWCore/ServiceRegistry/interface/ServiceRegistry.h" +#include "FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h" #include "FWCore/Concurrency/interface/SerialTaskQueueChain.h" #include "FWCore/Concurrency/interface/LimitedTaskQueue.h" #include "FWCore/Concurrency/interface/FunctorTask.h" @@ -76,8 +77,6 @@ namespace edm { class ModuleProcessName; class ProductResolverIndexHelper; class ProductResolverIndexAndSkipBit; - class StreamID; - class StreamContext; class ProductRegistry; class ThinnedAssociationsHelper; @@ -179,10 +178,10 @@ namespace edm { void callWhenDoneAsync(WaitingTaskHolder task) { waitingTasks_.add(std::move(task)); } void skipOnPath(EventPrincipal const& iEvent); - void beginJob(); - void endJob(); - void beginStream(StreamID id, StreamContext& streamContext); - void endStream(StreamID id, StreamContext& streamContext); + void beginJob(GlobalContext const&); + void endJob(GlobalContext const&); + void beginStream(StreamID, StreamContext const&); + void endStream(StreamID, StreamContext const&); void respondToOpenInputFile(FileBlock const& fb) { implRespondToOpenInputFile(fb); } void respondToCloseInputFile(FileBlock const& fb) { implRespondToCloseInputFile(fb); } void respondToCloseOutputFile() { implRespondToCloseOutputFile(); } @@ -986,6 +985,7 @@ namespace edm { cpp.preModuleSignal(); auto returnValue = iWorker->implDoBeginProcessBlock(info.principal(), mcc); cpp.postModuleSignal(); + iWorker->beginSucceeded_ = true; return returnValue; } static void esPrefetchAsync( @@ -1028,11 +1028,16 @@ namespace edm { ActivityRegistry* actReg, ModuleCallingContext const* mcc, Arg::Context const* context) { - ModuleSignalSentry cpp(actReg, context, mcc); - cpp.preModuleSignal(); - auto returnValue = iWorker->implDoEndProcessBlock(info.principal(), mcc); - cpp.postModuleSignal(); - return returnValue; + if (iWorker->beginSucceeded_) { + iWorker->beginSucceeded_ = false; + + ModuleSignalSentry cpp(actReg, context, mcc); + cpp.preModuleSignal(); + auto returnValue = iWorker->implDoEndProcessBlock(info.principal(), mcc); + cpp.postModuleSignal(); + return returnValue; + } + return true; } static void esPrefetchAsync( Worker*, WaitingTaskHolder, ServiceToken const&, ProcessBlockTransitionInfo const&, Transition) noexcept {} diff --git a/FWCore/Framework/src/EventProcessor.cc b/FWCore/Framework/src/EventProcessor.cc index 40e24b05f4ab2..a3c4999c7341a 100644 --- a/FWCore/Framework/src/EventProcessor.cc +++ b/FWCore/Framework/src/EventProcessor.cc @@ -635,8 +635,6 @@ namespace edm { beginJobCalled_ = true; bk::beginJob(); - // StateSentry toerror(this); // should we add this ? - //make the services available ServiceRegistry::Operate operate(serviceToken_); service::SystemBounds bounds(preallocations_.numberOfStreams(), @@ -718,7 +716,6 @@ namespace edm { //} espController_->finishConfiguration(); actReg_->eventSetupConfigurationSignal_(esp_->recordsToResolverIndices(), processContext_); - actReg_->preBeginJobSignal_(pathsAndConsumesOfModules_, processContext_); try { convertException::wrap([&]() { input_->doBeginJob(); }); } catch (cms::Exception& ex) { @@ -726,104 +723,130 @@ namespace edm { throw; } - schedule_->beginJob(*preg_, esp_->recordsToResolverIndices(), *processBlockHelper_); - if (looper_) { - constexpr bool mustPrefetchMayGet = true; - auto const processBlockLookup = preg_->productLookup(InProcess); - auto const runLookup = preg_->productLookup(InRun); - auto const lumiLookup = preg_->productLookup(InLumi); - auto const eventLookup = preg_->productLookup(InEvent); - looper_->updateLookup(InProcess, *processBlockLookup, mustPrefetchMayGet); - looper_->updateLookup(InRun, *runLookup, mustPrefetchMayGet); - looper_->updateLookup(InLumi, *lumiLookup, mustPrefetchMayGet); - looper_->updateLookup(InEvent, *eventLookup, mustPrefetchMayGet); - looper_->updateLookup(esp_->recordsToResolverIndices()); - } - // toerror.succeeded(); // should we add this? - for_all(subProcesses_, [](auto& subProcess) { subProcess.doBeginJob(); }); - actReg_->postBeginJobSignal_(); + beginJobStartedModules_ = true; + + // If we execute the beginJob transition for any module then we execute it + // for all of the modules. We save the first exception and rethrow that + // after they all complete. + std::exception_ptr firstException; + CMS_SA_ALLOW try { + schedule_->beginJob( + *preg_, esp_->recordsToResolverIndices(), *processBlockHelper_, pathsAndConsumesOfModules_, processContext_); + } catch (...) { + firstException = std::current_exception(); + } + if (looper_ && !firstException) { + CMS_SA_ALLOW try { + constexpr bool mustPrefetchMayGet = true; + auto const processBlockLookup = preg_->productLookup(InProcess); + auto const runLookup = preg_->productLookup(InRun); + auto const lumiLookup = preg_->productLookup(InLumi); + auto const eventLookup = preg_->productLookup(InEvent); + looper_->updateLookup(InProcess, *processBlockLookup, mustPrefetchMayGet); + looper_->updateLookup(InRun, *runLookup, mustPrefetchMayGet); + looper_->updateLookup(InLumi, *lumiLookup, mustPrefetchMayGet); + looper_->updateLookup(InEvent, *eventLookup, mustPrefetchMayGet); + looper_->updateLookup(esp_->recordsToResolverIndices()); + } catch (...) { + firstException = std::current_exception(); + } + } + for (auto& subProcess : subProcesses_) { + CMS_SA_ALLOW try { subProcess.doBeginJob(); } catch (...) { + if (!firstException) { + firstException = std::current_exception(); + } + } + } + if (firstException) { + std::rethrow_exception(firstException); + } + beginJobSucceeded_ = true; + beginStreams(); + } + + void EventProcessor::beginStreams() { + // This will process streams concurrently, but not modules in the + // same stream or SubProcesses. oneapi::tbb::task_group group; - FinalWaitingTask last{group}; + FinalWaitingTask finalWaitingTask{group}; using namespace edm::waiting_task::chain; - first([this](auto nextTask) { + { + WaitingTaskHolder taskHolder(group, &finalWaitingTask); for (unsigned int i = 0; i < preallocations_.numberOfStreams(); ++i) { - first([i, this](auto nextTask) { - ServiceRegistry::Operate operate(serviceToken_); - schedule_->beginStream(i); - }) | ifThen(not subProcesses_.empty(), [this, i](auto nextTask) { - ServiceRegistry::Operate operate(serviceToken_); - for_all(subProcesses_, [i](auto& subProcess) { subProcess.doBeginStream(i); }); - }) | lastTask(nextTask); + first([this, i](auto nextTask) { + std::exception_ptr exceptionPtr; + { + ServiceRegistry::Operate operate(serviceToken_); + CMS_SA_ALLOW try { schedule_->beginStream(i); } catch (...) { + exceptionPtr = std::current_exception(); + } + for (auto& subProcess : subProcesses_) { + CMS_SA_ALLOW try { subProcess.doBeginStream(i); } catch (...) { + if (!exceptionPtr) { + exceptionPtr = std::current_exception(); + } + } + } + } + nextTask.doneWaiting(exceptionPtr); + }) | lastTask(taskHolder); } - }) | runLast(WaitingTaskHolder(group, &last)); - last.wait(); + } + finalWaitingTask.wait(); } - void EventProcessor::endJob() { - // Collects exceptions, so we don't throw before all operations are performed. - ExceptionCollector c( - "Multiple exceptions were thrown while executing endJob. An exception message follows for each.\n"); - - //make the services available - ServiceRegistry::Operate operate(serviceToken_); - - using namespace edm::waiting_task::chain; + void EventProcessor::endStreams(ExceptionCollector& collector) noexcept { + std::mutex collectorMutex; + // This will process streams concurrently, but not modules in the + // same stream or SubProcesses. oneapi::tbb::task_group group; - edm::FinalWaitingTask waitTask{group}; - + FinalWaitingTask finalWaitingTask{group}; + using namespace edm::waiting_task::chain; { - //handle endStream transitions - edm::WaitingTaskHolder taskHolder(group, &waitTask); - std::mutex collectorMutex; + WaitingTaskHolder taskHolder(group, &finalWaitingTask); for (unsigned int i = 0; i < preallocations_.numberOfStreams(); ++i) { - first([this, i, &c, &collectorMutex](auto nextTask) { - std::exception_ptr ep; - try { + first([this, i, &collector, &collectorMutex](auto nextTask) { + { ServiceRegistry::Operate operate(serviceToken_); - this->schedule_->endStream(i); - } catch (...) { - ep = std::current_exception(); - } - if (ep) { - std::lock_guard l(collectorMutex); - c.call([&ep]() { std::rethrow_exception(ep); }); - } - }) | then([this, i, &c, &collectorMutex](auto nextTask) { - for (auto& subProcess : subProcesses_) { - first([this, i, &c, &collectorMutex, &subProcess](auto nextTask) { - std::exception_ptr ep; - try { - ServiceRegistry::Operate operate(serviceToken_); - subProcess.doEndStream(i); - } catch (...) { - ep = std::current_exception(); - } - if (ep) { - std::lock_guard l(collectorMutex); - c.call([&ep]() { std::rethrow_exception(ep); }); - } - }) | lastTask(nextTask); + schedule_->endStream(i, collector, collectorMutex); + for (auto& subProcess : subProcesses_) { + subProcess.doEndStream(i, collector, collectorMutex); + } } }) | lastTask(taskHolder); } } - waitTask.waitNoThrow(); + finalWaitingTask.waitNoThrow(); + } - auto actReg = actReg_.get(); - c.call([actReg]() { actReg->preEndJobSignal_(); }); - schedule_->endJob(c); - for (auto& subProcess : subProcesses_) { - c.call(std::bind(&SubProcess::doEndJob, &subProcess)); - } - c.call(std::bind(&InputSource::doEndJob, input_.get())); - if (looper_) { - c.call(std::bind(&EDLooperBase::endOfJob, looper())); + void EventProcessor::endJob() { + // Collects exceptions, so we don't throw before all operations are performed. + ExceptionCollector c( + "Multiple exceptions were thrown while executing endStream and endJob. An exception message follows for " + "each.\n"); + + //make the services available + ServiceRegistry::Operate operate(serviceToken_); + + if (beginJobSucceeded_) { + endStreams(c); } - c.call([actReg]() { actReg->postEndJobSignal_(); }); - if (c.hasThrown()) { - c.rethrow(); + + if (beginJobStartedModules_) { + schedule_->endJob(c); + for (auto& subProcess : subProcesses_) { + subProcess.doEndJob(c); + } + c.call(std::bind(&InputSource::doEndJob, input_.get())); + if (looper_) { + c.call(std::bind(&EDLooperBase::endOfJob, looper())); + } + if (c.hasThrown()) { + c.rethrow(); + } } } diff --git a/FWCore/Framework/src/GlobalSchedule.cc b/FWCore/Framework/src/GlobalSchedule.cc index cfbd09e710abd..bb67bf0d85b29 100644 --- a/FWCore/Framework/src/GlobalSchedule.cc +++ b/FWCore/Framework/src/GlobalSchedule.cc @@ -11,12 +11,14 @@ #include "FWCore/ParameterSet/interface/Registry.h" #include "FWCore/Utilities/interface/Algorithms.h" #include "FWCore/Utilities/interface/Exception.h" +#include "FWCore/Utilities/interface/ExceptionCollector.h" #include #include #include #include #include +#include namespace edm { GlobalSchedule::GlobalSchedule( @@ -32,8 +34,12 @@ namespace edm { std::shared_ptr areg, std::shared_ptr processConfiguration, ProcessContext const* processContext) - : actReg_(areg), processContext_(processContext), numberOfConcurrentLumis_(prealloc.numberOfLuminosityBlocks()) { - unsigned int nManagers = prealloc.numberOfLuminosityBlocks() + prealloc.numberOfRuns(); + : actReg_(areg), + processContext_(processContext), + numberOfConcurrentLumis_(prealloc.numberOfLuminosityBlocks()), + numberOfConcurrentRuns_(prealloc.numberOfRuns()) { + unsigned int nManagers = prealloc.numberOfLuminosityBlocks() + prealloc.numberOfRuns() + + numberOfConcurrentProcessBlocks_ + numberOfConcurrentJobs_; workerManagers_.reserve(nManagers); for (unsigned int i = 0; i < nManagers; ++i) { workerManagers_.emplace_back(modReg, areg, actions); @@ -89,16 +95,79 @@ namespace edm { } // GlobalSchedule::GlobalSchedule - void GlobalSchedule::endJob(ExceptionCollector& collector) { workerManagers_[0].endJob(collector); } - void GlobalSchedule::beginJob(ProductRegistry const& iRegistry, eventsetup::ESRecordsToProductResolverIndices const& iESIndices, - ProcessBlockHelperBase const& processBlockHelperBase) { - workerManagers_[0].beginJob(iRegistry, iESIndices, processBlockHelperBase); + ProcessBlockHelperBase const& processBlockHelperBase, + PathsAndConsumesOfModulesBase const& pathsAndConsumesOfModules, + ProcessContext const& processContext) { + GlobalContext globalContext(GlobalContext::Transition::kBeginJob, processContext_); + unsigned int const managerIndex = + numberOfConcurrentLumis_ + numberOfConcurrentRuns_ + numberOfConcurrentProcessBlocks_; + + std::exception_ptr exceptionPtr; + CMS_SA_ALLOW try { + try { + convertException::wrap([this, &pathsAndConsumesOfModules, &processContext]() { + actReg_->preBeginJobSignal_(pathsAndConsumesOfModules, processContext); + }); + } catch (cms::Exception& ex) { + exceptionContext(ex, globalContext, "Handling pre signal, likely in a service function"); + throw; + } + workerManagers_[managerIndex].beginJob(iRegistry, iESIndices, processBlockHelperBase, globalContext); + } catch (...) { + exceptionPtr = std::current_exception(); + } + + try { + convertException::wrap([this]() { actReg_->postBeginJobSignal_(); }); + } catch (cms::Exception& ex) { + if (!exceptionPtr) { + exceptionContext(ex, globalContext, "Handling post signal, likely in a service function"); + exceptionPtr = std::current_exception(); + } + } + if (exceptionPtr) { + std::rethrow_exception(exceptionPtr); + } + } + + void GlobalSchedule::endJob(ExceptionCollector& collector) { + GlobalContext globalContext(GlobalContext::Transition::kEndJob, processContext_); + unsigned int const managerIndex = + numberOfConcurrentLumis_ + numberOfConcurrentRuns_ + numberOfConcurrentProcessBlocks_; + + std::exception_ptr exceptionPtr; + CMS_SA_ALLOW try { + try { + convertException::wrap([this]() { actReg_->preEndJobSignal_(); }); + } catch (cms::Exception& ex) { + exceptionContext(ex, globalContext, "Handling pre signal, likely in a service function"); + throw; + } + workerManagers_[managerIndex].endJob(collector, globalContext); + } catch (...) { + exceptionPtr = std::current_exception(); + } + + try { + convertException::wrap([this]() { actReg_->postEndJobSignal_(); }); + } catch (cms::Exception& ex) { + if (!exceptionPtr) { + exceptionContext(ex, globalContext, "Handling post signal, likely in a service function"); + exceptionPtr = std::current_exception(); + } + } + if (exceptionPtr) { + collector.call([&exceptionPtr]() { std::rethrow_exception(exceptionPtr); }); + } } void GlobalSchedule::replaceModule(maker::ModuleHolder* iMod, std::string const& iLabel) { Worker* found = nullptr; + unsigned int const jobManagerIndex = + numberOfConcurrentLumis_ + numberOfConcurrentRuns_ + numberOfConcurrentProcessBlocks_; + unsigned int managerIndex = 0; for (auto& wm : workerManagers_) { for (auto const& worker : wm.allWorkers()) { if (worker->description()->moduleLabel() == iLabel) { @@ -111,7 +180,11 @@ namespace edm { } iMod->replaceModuleFor(found); - found->beginJob(); + if (managerIndex == jobManagerIndex) { + GlobalContext globalContext(GlobalContext::Transition::kBeginJob, processContext_); + found->beginJob(globalContext); + } + ++managerIndex; } } diff --git a/FWCore/Framework/src/Schedule.cc b/FWCore/Framework/src/Schedule.cc index d2f84f203e196..fa70c32b5cde1 100644 --- a/FWCore/Framework/src/Schedule.cc +++ b/FWCore/Framework/src/Schedule.cc @@ -786,9 +786,16 @@ namespace edm { return; } - if (wantSummary_ == false) - return; + if (wantSummary_) { + try { + convertException::wrap([this]() { sendFwkSummaryToMessageLogger(); }); + } catch (cms::Exception const& ex) { + collector.addException(ex); + } + } + } + void Schedule::sendFwkSummaryToMessageLogger() const { //Function to loop over items in a container and periodically // flush to the message logger. auto logForEach = [](auto const& iContainer, auto iMessage) { @@ -1180,18 +1187,20 @@ namespace edm { void Schedule::beginJob(ProductRegistry const& iRegistry, eventsetup::ESRecordsToProductResolverIndices const& iESIndices, - ProcessBlockHelperBase const& processBlockHelperBase) { - globalSchedule_->beginJob(iRegistry, iESIndices, processBlockHelperBase); + ProcessBlockHelperBase const& processBlockHelperBase, + PathsAndConsumesOfModulesBase const& pathsAndConsumesOfModules, + ProcessContext const& processContext) { + globalSchedule_->beginJob(iRegistry, iESIndices, processBlockHelperBase, pathsAndConsumesOfModules, processContext); } - void Schedule::beginStream(unsigned int iStreamID) { - assert(iStreamID < streamSchedules_.size()); - streamSchedules_[iStreamID]->beginStream(); + void Schedule::beginStream(unsigned int streamID) { + assert(streamID < streamSchedules_.size()); + streamSchedules_[streamID]->beginStream(); } - void Schedule::endStream(unsigned int iStreamID) { - assert(iStreamID < streamSchedules_.size()); - streamSchedules_[iStreamID]->endStream(); + void Schedule::endStream(unsigned int streamID, ExceptionCollector& collector, std::mutex& collectorMutex) noexcept { + assert(streamID < streamSchedules_.size()); + streamSchedules_[streamID]->endStream(collector, collectorMutex); } void Schedule::processOneEventAsync(WaitingTaskHolder iTask, diff --git a/FWCore/Framework/src/StreamSchedule.cc b/FWCore/Framework/src/StreamSchedule.cc index 36c4efc143243..ccbee43c03f67 100644 --- a/FWCore/Framework/src/StreamSchedule.cc +++ b/FWCore/Framework/src/StreamSchedule.cc @@ -1,9 +1,11 @@ #include "FWCore/Framework/interface/StreamSchedule.h" #include "DataFormats/Provenance/interface/BranchIDListHelper.h" +#include "DataFormats/Provenance/interface/EventID.h" #include "DataFormats/Provenance/interface/ProcessConfiguration.h" #include "DataFormats/Provenance/interface/ProductRegistry.h" #include "DataFormats/Provenance/interface/ProductResolverIndexHelper.h" +#include "DataFormats/Provenance/interface/Timestamp.h" #include "FWCore/Framework/src/OutputModuleDescription.h" #include "FWCore/Framework/interface/TriggerNamesService.h" #include "FWCore/Framework/src/TriggerReport.h" @@ -21,11 +23,12 @@ #include "FWCore/ParameterSet/interface/ParameterSet.h" #include "FWCore/ParameterSet/interface/ParameterSetDescription.h" #include "FWCore/ParameterSet/interface/Registry.h" +#include "FWCore/ServiceRegistry/interface/ActivityRegistry.h" #include "FWCore/ServiceRegistry/interface/PathContext.h" #include "FWCore/Utilities/interface/Algorithms.h" -#include "FWCore/Utilities/interface/ConvertException.h" #include "FWCore/Utilities/interface/ExceptionCollector.h" -#include "FWCore/Concurrency/interface/WaitingTaskHolder.h" +#include "FWCore/Utilities/interface/LuminosityBlockIndex.h" +#include "FWCore/Utilities/interface/RunIndex.h" #include "LuminosityBlockProcessingStatus.h" #include "processEDAliases.h" @@ -38,7 +41,6 @@ #include #include #include -#include #include namespace edm { @@ -71,6 +73,26 @@ namespace edm { } } + class BeginStreamTraits { + public: + static void preScheduleSignal(ActivityRegistry* activityRegistry, StreamContext const* streamContext) { + activityRegistry->preBeginStreamSignal_(*streamContext); + } + static void postScheduleSignal(ActivityRegistry* activityRegistry, StreamContext const* streamContext) { + activityRegistry->postBeginStreamSignal_(*streamContext); + } + }; + + class EndStreamTraits { + public: + static void preScheduleSignal(ActivityRegistry* activityRegistry, StreamContext const* streamContext) { + activityRegistry->preEndStreamSignal_(*streamContext); + } + static void postScheduleSignal(ActivityRegistry* activityRegistry, StreamContext const* streamContext) { + activityRegistry->postEndStreamSignal_(*streamContext); + } + }; + // ----------------------------- // Here we make the trigger results inserter directly. This should @@ -982,15 +1004,76 @@ namespace edm { } } - void StreamSchedule::beginStream() { workerManagerBeginEnd_.beginStream(streamID_, streamContext_); } + void StreamSchedule::beginStream() { + streamContext_.setTransition(StreamContext::Transition::kBeginStream); + streamContext_.setEventID(EventID(0, 0, 0)); + streamContext_.setRunIndex(RunIndex::invalidRunIndex()); + streamContext_.setLuminosityBlockIndex(LuminosityBlockIndex::invalidLuminosityBlockIndex()); + streamContext_.setTimestamp(Timestamp()); + + std::exception_ptr exceptionInStream; + CMS_SA_ALLOW try { + preScheduleSignal(&streamContext_); + workerManagerBeginEnd_.beginStream(streamID_, streamContext_); + } catch (...) { + exceptionInStream = std::current_exception(); + } + + postScheduleSignal(&streamContext_, exceptionInStream); + + if (exceptionInStream) { + bool cleaningUpAfterException = false; + handleException(streamContext_, cleaningUpAfterException, exceptionInStream); + } + streamContext_.setTransition(StreamContext::Transition::kInvalid); + + if (exceptionInStream) { + std::rethrow_exception(exceptionInStream); + } + } + + void StreamSchedule::endStream(ExceptionCollector& collector, std::mutex& collectorMutex) noexcept { + streamContext_.setTransition(StreamContext::Transition::kEndStream); + streamContext_.setEventID(EventID(0, 0, 0)); + streamContext_.setRunIndex(RunIndex::invalidRunIndex()); + streamContext_.setLuminosityBlockIndex(LuminosityBlockIndex::invalidLuminosityBlockIndex()); + streamContext_.setTimestamp(Timestamp()); - void StreamSchedule::endStream() { workerManagerBeginEnd_.endStream(streamID_, streamContext_); } + std::exception_ptr exceptionInStream; + CMS_SA_ALLOW try { + preScheduleSignal(&streamContext_); + workerManagerBeginEnd_.endStream(streamID_, streamContext_, collector, collectorMutex); + } catch (...) { + exceptionInStream = std::current_exception(); + } + + postScheduleSignal(&streamContext_, exceptionInStream); + + if (exceptionInStream) { + std::lock_guard collectorLock(collectorMutex); + collector.call([&exceptionInStream]() { std::rethrow_exception(exceptionInStream); }); + } + streamContext_.setTransition(StreamContext::Transition::kInvalid); + } void StreamSchedule::replaceModule(maker::ModuleHolder* iMod, std::string const& iLabel) { for (auto const& worker : allWorkersBeginEnd()) { if (worker->description()->moduleLabel() == iLabel) { iMod->replaceModuleFor(worker); - worker->beginStream(streamID_, streamContext_); + + streamContext_.setTransition(StreamContext::Transition::kBeginStream); + streamContext_.setEventID(EventID(0, 0, 0)); + streamContext_.setRunIndex(RunIndex::invalidRunIndex()); + streamContext_.setLuminosityBlockIndex(LuminosityBlockIndex::invalidLuminosityBlockIndex()); + streamContext_.setTimestamp(Timestamp()); + try { + worker->beginStream(streamID_, streamContext_); + } catch (cms::Exception& ex) { + streamContext_.setTransition(StreamContext::Transition::kInvalid); + ex.addContext("Executing StreamSchedule::replaceModule"); + throw; + } + streamContext_.setTransition(StreamContext::Transition::kInvalid); break; } } @@ -1435,7 +1518,6 @@ namespace edm { } void StreamSchedule::handleException(StreamContext const& streamContext, - ServiceWeakToken const& weakToken, bool cleaningUpAfterException, std::exception_ptr& excpt) const noexcept { //add context information to the exception and print message @@ -1448,14 +1530,12 @@ namespace edm { if (ex.context().empty()) { exceptionContext(ost, streamContext); } - ServiceRegistry::Operate op(weakToken.lock()); addContextAndPrintException(ost.str().c_str(), ex, cleaningUpAfterException); excpt = std::current_exception(); } // We are already handling an earlier exception, so ignore it // if this signal results in another exception being thrown. CMS_SA_ALLOW try { - ServiceRegistry::Operate op(weakToken.lock()); actReg_->preStreamEarlyTerminationSignal_(streamContext, TerminationOrigin::ExceptionFromThisContext); } catch (...) { } diff --git a/FWCore/Framework/src/SubProcess.cc b/FWCore/Framework/src/SubProcess.cc index fa56a87230f8d..d62785eb57a7b 100644 --- a/FWCore/Framework/src/SubProcess.cc +++ b/FWCore/Framework/src/SubProcess.cc @@ -38,7 +38,9 @@ #include "FWCore/Concurrency/interface/WaitingTaskHolder.h" #include "FWCore/Concurrency/interface/WaitingTask.h" #include "FWCore/Concurrency/interface/chain_first.h" +#include "FWCore/Utilities/interface/ConvertException.h" #include "FWCore/Utilities/interface/ExceptionCollector.h" +#include "FWCore/Utilities/interface/thread_safety_macros.h" #include "boost/range/adaptor/reversed.hpp" @@ -292,9 +294,9 @@ namespace edm { return consumedByChildren; } - void SubProcess::doBeginJob() { this->beginJob(); } + void SubProcess::doBeginJob() { beginJob(); } - void SubProcess::doEndJob() { endJob(); } + void SubProcess::doEndJob(ExceptionCollector& collector) { endJob(collector); } void SubProcess::beginJob() { // If event selection is being used, the SubProcess class reads TriggerResults @@ -307,21 +309,35 @@ namespace edm { fixBranchIDListsForEDAliases(droppedBranchIDToKeptBranchID()); } ServiceRegistry::Operate operate(serviceToken_); - actReg_->preBeginJobSignal_(pathsAndConsumesOfModules_, processContext_); - schedule_->beginJob(*preg_, esp_->recordsToResolverIndices(), *processBlockHelper_); - for_all(subProcesses_, [](auto& subProcess) { subProcess.doBeginJob(); }); + + std::exception_ptr firstException; + CMS_SA_ALLOW try { + schedule_->beginJob( + *preg_, esp_->recordsToResolverIndices(), *processBlockHelper_, pathsAndConsumesOfModules_, processContext_); + } catch (...) { + firstException = std::current_exception(); + } + for (auto& subProcess : subProcesses_) { + CMS_SA_ALLOW try { subProcess.doBeginJob(); } catch (...) { + if (!firstException) { + firstException = std::current_exception(); + } + } + } + if (firstException) { + std::rethrow_exception(firstException); + } } - void SubProcess::endJob() { + void SubProcess::endJob(ExceptionCollector& collector) { ServiceRegistry::Operate operate(serviceToken_); - ExceptionCollector c( - "Multiple exceptions were thrown while executing endJob. An exception message follows for each."); - schedule_->endJob(c); - for (auto& subProcess : subProcesses_) { - c.call([&subProcess]() { subProcess.doEndJob(); }); + try { + convertException::wrap([this, &collector]() { schedule_->endJob(collector); }); + } catch (cms::Exception const& ex) { + collector.addException(ex); } - if (c.hasThrown()) { - c.rethrow(); + for (auto& subProcess : subProcesses_) { + subProcess.doEndJob(collector); } } @@ -689,16 +705,33 @@ namespace edm { lb->clearPrincipal(); } - void SubProcess::doBeginStream(unsigned int iID) { + void SubProcess::doBeginStream(unsigned int streamID) { ServiceRegistry::Operate operate(serviceToken_); - schedule_->beginStream(iID); - for_all(subProcesses_, [iID](auto& subProcess) { subProcess.doBeginStream(iID); }); + std::exception_ptr exceptionPtr; + CMS_SA_ALLOW try { schedule_->beginStream(streamID); } catch (...) { + exceptionPtr = std::current_exception(); + } + + for (auto& subProcess : subProcesses_) { + CMS_SA_ALLOW try { subProcess.doBeginStream(streamID); } catch (...) { + if (!exceptionPtr) { + exceptionPtr = std::current_exception(); + } + } + } + if (exceptionPtr) { + std::rethrow_exception(exceptionPtr); + } } - void SubProcess::doEndStream(unsigned int iID) { + void SubProcess::doEndStream(unsigned int streamID, + ExceptionCollector& collector, + std::mutex& collectorMutex) noexcept { ServiceRegistry::Operate operate(serviceToken_); - schedule_->endStream(iID); - for_all(subProcesses_, [iID](auto& subProcess) { subProcess.doEndStream(iID); }); + schedule_->endStream(streamID, collector, collectorMutex); + for (auto& subProcess : subProcesses_) { + subProcess.doEndStream(streamID, collector, collectorMutex); + } } void SubProcess::doStreamBeginRunAsync(WaitingTaskHolder iHolder, diff --git a/FWCore/Framework/src/Worker.cc b/FWCore/Framework/src/Worker.cc index 4d5b0c1def6ef..6a4a912b1ef34 100644 --- a/FWCore/Framework/src/Worker.cc +++ b/FWCore/Framework/src/Worker.cc @@ -17,72 +17,64 @@ namespace edm { namespace { - class ModuleBeginJobSignalSentry { + class ModuleBeginJobTraits { public: - ModuleBeginJobSignalSentry(ActivityRegistry* a, ModuleDescription const& md) : a_(a), md_(&md) { - if (a_) - a_->preModuleBeginJobSignal_(*md_); + using Context = GlobalContext; + static void preModuleSignal(ActivityRegistry* activityRegistry, + GlobalContext const*, + ModuleCallingContext const* moduleCallingContext) { + activityRegistry->preModuleBeginJobSignal_(*moduleCallingContext->moduleDescription()); } - ~ModuleBeginJobSignalSentry() { - if (a_) - a_->postModuleBeginJobSignal_(*md_); + static void postModuleSignal(ActivityRegistry* activityRegistry, + GlobalContext const*, + ModuleCallingContext const* moduleCallingContext) { + activityRegistry->postModuleBeginJobSignal_(*moduleCallingContext->moduleDescription()); } - - private: - ActivityRegistry* a_; // We do not use propagate_const because the registry itself is mutable. - ModuleDescription const* md_; }; - class ModuleEndJobSignalSentry { + class ModuleEndJobTraits { public: - ModuleEndJobSignalSentry(ActivityRegistry* a, ModuleDescription const& md) : a_(a), md_(&md) { - if (a_) - a_->preModuleEndJobSignal_(*md_); + using Context = GlobalContext; + static void preModuleSignal(ActivityRegistry* activityRegistry, + GlobalContext const*, + ModuleCallingContext const* moduleCallingContext) { + activityRegistry->preModuleEndJobSignal_(*moduleCallingContext->moduleDescription()); } - ~ModuleEndJobSignalSentry() { - if (a_) - a_->postModuleEndJobSignal_(*md_); + static void postModuleSignal(ActivityRegistry* activityRegistry, + GlobalContext const*, + ModuleCallingContext const* moduleCallingContext) { + activityRegistry->postModuleEndJobSignal_(*moduleCallingContext->moduleDescription()); } - - private: - ActivityRegistry* a_; // We do not use propagate_const because the registry itself is mutable. - ModuleDescription const* md_; }; - class ModuleBeginStreamSignalSentry { + class ModuleBeginStreamTraits { public: - ModuleBeginStreamSignalSentry(ActivityRegistry* a, StreamContext const& sc, ModuleCallingContext const& mcc) - : a_(a), sc_(sc), mcc_(mcc) { - if (a_) - a_->preModuleBeginStreamSignal_(sc_, mcc_); + using Context = StreamContext; + static void preModuleSignal(ActivityRegistry* activityRegistry, + StreamContext const* streamContext, + ModuleCallingContext const* moduleCallingContext) { + activityRegistry->preModuleBeginStreamSignal_(*streamContext, *moduleCallingContext); } - ~ModuleBeginStreamSignalSentry() { - if (a_) - a_->postModuleBeginStreamSignal_(sc_, mcc_); + static void postModuleSignal(ActivityRegistry* activityRegistry, + StreamContext const* streamContext, + ModuleCallingContext const* moduleCallingContext) { + activityRegistry->postModuleBeginStreamSignal_(*streamContext, *moduleCallingContext); } - - private: - ActivityRegistry* a_; // We do not use propagate_const because the registry itself is mutable. - StreamContext const& sc_; - ModuleCallingContext const& mcc_; }; - class ModuleEndStreamSignalSentry { + class ModuleEndStreamTraits { public: - ModuleEndStreamSignalSentry(ActivityRegistry* a, StreamContext const& sc, ModuleCallingContext const& mcc) - : a_(a), sc_(sc), mcc_(mcc) { - if (a_) - a_->preModuleEndStreamSignal_(sc_, mcc_); + using Context = StreamContext; + static void preModuleSignal(ActivityRegistry* activityRegistry, + StreamContext const* streamContext, + ModuleCallingContext const* moduleCallingContext) { + activityRegistry->preModuleEndStreamSignal_(*streamContext, *moduleCallingContext); } - ~ModuleEndStreamSignalSentry() { - if (a_) - a_->postModuleEndStreamSignal_(sc_, mcc_); + static void postModuleSignal(ActivityRegistry* activityRegistry, + StreamContext const* streamContext, + ModuleCallingContext const* moduleCallingContext) { + activityRegistry->postModuleEndStreamSignal_(*streamContext, *moduleCallingContext); } - - private: - ActivityRegistry* a_; // We do not use propagate_const because the registry itself is mutable. - StreamContext const& sc_; - ModuleCallingContext const& mcc_; }; } // namespace @@ -297,84 +289,83 @@ namespace edm { checkForShouldTryToContinue(*iDesc); } - void Worker::beginJob() { + void Worker::beginJob(GlobalContext const& globalContext) { + ParentContext parentContext(&globalContext); + ModuleContextSentry moduleContextSentry(&moduleCallingContext_, parentContext); + ModuleSignalSentry sentry(activityRegistry(), &globalContext, &moduleCallingContext_); + try { - convertException::wrap([&]() { - ModuleBeginJobSignalSentry cpp(actReg_.get(), *description()); + convertException::wrap([this, &sentry]() { + beginSucceeded_ = false; + sentry.preModuleSignal(); implBeginJob(); + sentry.postModuleSignal(); + beginSucceeded_ = true; }); } catch (cms::Exception& ex) { - state_ = Exception; - std::ostringstream ost; - ost << "Calling beginJob for module " << description()->moduleName() << "/'" << description()->moduleLabel() - << "'"; - ex.addContext(ost.str()); + exceptionContext(ex, moduleCallingContext_); throw; } } - void Worker::endJob() { - try { - convertException::wrap([&]() { - ModuleDescription const* desc = description(); - assert(desc != nullptr); - ModuleEndJobSignalSentry cpp(actReg_.get(), *desc); - implEndJob(); - }); - } catch (cms::Exception& ex) { - state_ = Exception; - std::ostringstream ost; - ost << "Calling endJob for module " << description()->moduleName() << "/'" << description()->moduleLabel() << "'"; - ex.addContext(ost.str()); - throw; + void Worker::endJob(GlobalContext const& globalContext) { + if (beginSucceeded_) { + beginSucceeded_ = false; + + ParentContext parentContext(&globalContext); + ModuleContextSentry moduleContextSentry(&moduleCallingContext_, parentContext); + ModuleSignalSentry sentry(activityRegistry(), &globalContext, &moduleCallingContext_); + + try { + convertException::wrap([this, &sentry]() { + sentry.preModuleSignal(); + implEndJob(); + sentry.postModuleSignal(); + }); + } catch (cms::Exception& ex) { + exceptionContext(ex, moduleCallingContext_); + throw; + } } } - void Worker::beginStream(StreamID id, StreamContext& streamContext) { + void Worker::beginStream(StreamID streamID, StreamContext const& streamContext) { + ParentContext parentContext(&streamContext); + ModuleContextSentry moduleContextSentry(&moduleCallingContext_, parentContext); + ModuleSignalSentry sentry(activityRegistry(), &streamContext, &moduleCallingContext_); + try { - convertException::wrap([&]() { - streamContext.setTransition(StreamContext::Transition::kBeginStream); - streamContext.setEventID(EventID(0, 0, 0)); - streamContext.setRunIndex(RunIndex::invalidRunIndex()); - streamContext.setLuminosityBlockIndex(LuminosityBlockIndex::invalidLuminosityBlockIndex()); - streamContext.setTimestamp(Timestamp()); - ParentContext parentContext(&streamContext); - ModuleContextSentry moduleContextSentry(&moduleCallingContext_, parentContext); - moduleCallingContext_.setState(ModuleCallingContext::State::kRunning); - ModuleBeginStreamSignalSentry beginSentry(actReg_.get(), streamContext, moduleCallingContext_); - implBeginStream(id); + convertException::wrap([this, &sentry, streamID]() { + beginSucceeded_ = false; + sentry.preModuleSignal(); + implBeginStream(streamID); + sentry.postModuleSignal(); + beginSucceeded_ = true; }); } catch (cms::Exception& ex) { - state_ = Exception; - std::ostringstream ost; - ost << "Calling beginStream for module " << description()->moduleName() << "/'" << description()->moduleLabel() - << "'"; - ex.addContext(ost.str()); + exceptionContext(ex, moduleCallingContext_); throw; } } - void Worker::endStream(StreamID id, StreamContext& streamContext) { - try { - convertException::wrap([&]() { - streamContext.setTransition(StreamContext::Transition::kEndStream); - streamContext.setEventID(EventID(0, 0, 0)); - streamContext.setRunIndex(RunIndex::invalidRunIndex()); - streamContext.setLuminosityBlockIndex(LuminosityBlockIndex::invalidLuminosityBlockIndex()); - streamContext.setTimestamp(Timestamp()); - ParentContext parentContext(&streamContext); - ModuleContextSentry moduleContextSentry(&moduleCallingContext_, parentContext); - moduleCallingContext_.setState(ModuleCallingContext::State::kRunning); - ModuleEndStreamSignalSentry endSentry(actReg_.get(), streamContext, moduleCallingContext_); - implEndStream(id); - }); - } catch (cms::Exception& ex) { - state_ = Exception; - std::ostringstream ost; - ost << "Calling endStream for module " << description()->moduleName() << "/'" << description()->moduleLabel() - << "'"; - ex.addContext(ost.str()); - throw; + void Worker::endStream(StreamID id, StreamContext const& streamContext) { + if (beginSucceeded_) { + beginSucceeded_ = false; + + ParentContext parentContext(&streamContext); + ModuleContextSentry moduleContextSentry(&moduleCallingContext_, parentContext); + ModuleSignalSentry sentry(activityRegistry(), &streamContext, &moduleCallingContext_); + + try { + convertException::wrap([this, &sentry, id]() { + sentry.preModuleSignal(); + implEndStream(id); + sentry.postModuleSignal(); + }); + } catch (cms::Exception& ex) { + exceptionContext(ex, moduleCallingContext_); + throw; + } } } diff --git a/FWCore/Framework/src/WorkerManager.cc b/FWCore/Framework/src/WorkerManager.cc index 461886b17bab2..92b20daa3f6f6 100644 --- a/FWCore/Framework/src/WorkerManager.cc +++ b/FWCore/Framework/src/WorkerManager.cc @@ -9,7 +9,9 @@ #include "FWCore/Utilities/interface/ConvertException.h" #include "FWCore/Utilities/interface/Exception.h" #include "FWCore/Utilities/interface/ExceptionCollector.h" +#include "FWCore/Utilities/interface/thread_safety_macros.h" +#include #include static const std::string kFilterType("EDFilter"); @@ -78,61 +80,85 @@ namespace edm { } } - void WorkerManager::endJob() { + void WorkerManager::beginJob(ProductRegistry const& iRegistry, + eventsetup::ESRecordsToProductResolverIndices const& iESIndices, + ProcessBlockHelperBase const& processBlockHelperBase, + GlobalContext const& globalContext) { + std::exception_ptr exceptionPtr; + CMS_SA_ALLOW try { + auto const processBlockLookup = iRegistry.productLookup(InProcess); + auto const runLookup = iRegistry.productLookup(InRun); + auto const lumiLookup = iRegistry.productLookup(InLumi); + auto const eventLookup = iRegistry.productLookup(InEvent); + if (!allWorkers_.empty()) { + auto const& processName = allWorkers_[0]->description()->processName(); + auto processBlockModuleToIndicies = processBlockLookup->indiciesForModulesInProcess(processName); + auto runModuleToIndicies = runLookup->indiciesForModulesInProcess(processName); + auto lumiModuleToIndicies = lumiLookup->indiciesForModulesInProcess(processName); + auto eventModuleToIndicies = eventLookup->indiciesForModulesInProcess(processName); + for (auto& worker : allWorkers_) { + worker->updateLookup(InProcess, *processBlockLookup); + worker->updateLookup(InRun, *runLookup); + worker->updateLookup(InLumi, *lumiLookup); + worker->updateLookup(InEvent, *eventLookup); + worker->updateLookup(iESIndices); + worker->resolvePutIndicies(InProcess, processBlockModuleToIndicies); + worker->resolvePutIndicies(InRun, runModuleToIndicies); + worker->resolvePutIndicies(InLumi, lumiModuleToIndicies); + worker->resolvePutIndicies(InEvent, eventModuleToIndicies); + worker->selectInputProcessBlocks(iRegistry, processBlockHelperBase); + } + } + } catch (...) { + exceptionPtr = std::current_exception(); + } + for (auto& worker : allWorkers_) { - worker->endJob(); + CMS_SA_ALLOW try { worker->beginJob(globalContext); } catch (...) { + if (!exceptionPtr) { + exceptionPtr = std::current_exception(); + } + } + } + if (exceptionPtr) { + std::rethrow_exception(exceptionPtr); } } - void WorkerManager::endJob(ExceptionCollector& collector) { + void WorkerManager::endJob(ExceptionCollector& collector, GlobalContext const& globalContext) { for (auto& worker : allWorkers_) { try { - convertException::wrap([&]() { worker->endJob(); }); + convertException::wrap([&worker, &globalContext]() { worker->endJob(globalContext); }); } catch (cms::Exception const& ex) { collector.addException(ex); } } } - void WorkerManager::beginJob(ProductRegistry const& iRegistry, - eventsetup::ESRecordsToProductResolverIndices const& iESIndices, - ProcessBlockHelperBase const& processBlockHelperBase) { - auto const processBlockLookup = iRegistry.productLookup(InProcess); - auto const runLookup = iRegistry.productLookup(InRun); - auto const lumiLookup = iRegistry.productLookup(InLumi); - auto const eventLookup = iRegistry.productLookup(InEvent); - if (!allWorkers_.empty()) { - auto const& processName = allWorkers_[0]->description()->processName(); - auto processBlockModuleToIndicies = processBlockLookup->indiciesForModulesInProcess(processName); - auto runModuleToIndicies = runLookup->indiciesForModulesInProcess(processName); - auto lumiModuleToIndicies = lumiLookup->indiciesForModulesInProcess(processName); - auto eventModuleToIndicies = eventLookup->indiciesForModulesInProcess(processName); - for (auto& worker : allWorkers_) { - worker->updateLookup(InProcess, *processBlockLookup); - worker->updateLookup(InRun, *runLookup); - worker->updateLookup(InLumi, *lumiLookup); - worker->updateLookup(InEvent, *eventLookup); - worker->updateLookup(iESIndices); - worker->resolvePutIndicies(InProcess, processBlockModuleToIndicies); - worker->resolvePutIndicies(InRun, runModuleToIndicies); - worker->resolvePutIndicies(InLumi, lumiModuleToIndicies); - worker->resolvePutIndicies(InEvent, eventModuleToIndicies); - worker->selectInputProcessBlocks(iRegistry, processBlockHelperBase); + void WorkerManager::beginStream(StreamID streamID, StreamContext const& streamContext) { + std::exception_ptr exceptionPtr; + for (auto& worker : allWorkers_) { + CMS_SA_ALLOW try { worker->beginStream(streamID, streamContext); } catch (...) { + if (!exceptionPtr) { + exceptionPtr = std::current_exception(); + } } - - for_all(allWorkers_, std::bind(&Worker::beginJob, std::placeholders::_1)); } - } - - void WorkerManager::beginStream(StreamID iID, StreamContext& streamContext) { - for (auto& worker : allWorkers_) { - worker->beginStream(iID, streamContext); + if (exceptionPtr) { + std::rethrow_exception(exceptionPtr); } } - void WorkerManager::endStream(StreamID iID, StreamContext& streamContext) { + void WorkerManager::endStream(StreamID streamID, + StreamContext const& streamContext, + ExceptionCollector& collector, + std::mutex& collectorMutex) noexcept { for (auto& worker : allWorkers_) { - worker->endStream(iID, streamContext); + CMS_SA_ALLOW try { worker->endStream(streamID, streamContext); } catch (...) { + std::exception_ptr exceptionPtr = std::current_exception(); + std::lock_guard collectorLock(collectorMutex); + collector.call([&exceptionPtr]() { std::rethrow_exception(exceptionPtr); }); + } } } diff --git a/FWCore/Framework/test/one_outputmodule_t.cppunit.cc b/FWCore/Framework/test/one_outputmodule_t.cppunit.cc index a195292e661f0..fc4fab558f97f 100644 --- a/FWCore/Framework/test/one_outputmodule_t.cppunit.cc +++ b/FWCore/Framework/test/one_outputmodule_t.cppunit.cc @@ -23,6 +23,7 @@ #include "FWCore/Utilities/interface/GlobalIdentifier.h" #include "FWCore/Framework/interface/TriggerNamesService.h" #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h" +#include "FWCore/ServiceRegistry/interface/GlobalContext.h" #include "FWCore/ServiceRegistry/interface/ParentContext.h" #include "FWCore/ServiceRegistry/interface/Service.h" #include "FWCore/ServiceRegistry/interface/ServiceRegistry.h" @@ -390,7 +391,8 @@ void testOneOutputModule::testTransitions(std::shared_ptr iMod, Expectations iMod->doPreallocate(m_preallocConfig); edm::WorkerT w{iMod, m_desc, m_params.actions_}; - w.beginJob(); + edm::GlobalContext globalContext(edm::GlobalContext::Transition::kBeginJob, nullptr); + w.beginJob(globalContext); edm::OutputModuleCommunicatorT comm(iMod.get()); for (auto& keyVal : m_transToFunc) { testTransition(iMod, &w, &comm, keyVal.first, iExpect, keyVal.second); diff --git a/FWCore/Framework/test/stream_filter_t.cppunit.cc b/FWCore/Framework/test/stream_filter_t.cppunit.cc index 6ad7449a1b73d..1005d88352f47 100644 --- a/FWCore/Framework/test/stream_filter_t.cppunit.cc +++ b/FWCore/Framework/test/stream_filter_t.cppunit.cc @@ -22,6 +22,7 @@ #include "DataFormats/Provenance/interface/BranchIDListHelper.h" #include "DataFormats/Provenance/interface/ThinnedAssociationsHelper.h" #include "FWCore/Framework/interface/HistoryAppender.h" +#include "FWCore/ServiceRegistry/interface/GlobalContext.h" #include "FWCore/ServiceRegistry/interface/ParentContext.h" #include "FWCore/ServiceRegistry/interface/StreamContext.h" #include "FWCore/Concurrency/interface/FinalWaitingTask.h" @@ -465,7 +466,10 @@ testStreamFilter::testStreamFilter() m_actReg.reset(new edm::ActivityRegistry); //For each transition, bind a lambda which will call the proper method of the Worker - m_transToFunc[Trans::kBeginJob] = [](edm::Worker* iBase) { iBase->beginJob(); }; + m_transToFunc[Trans::kBeginJob] = [](edm::Worker* iBase) { + edm::GlobalContext globalContext(edm::GlobalContext::Transition::kBeginJob, nullptr); + iBase->beginJob(globalContext); + }; m_transToFunc[Trans::kBeginStream] = [](edm::Worker* iBase) { edm::StreamContext streamContext(s_streamID0, nullptr); iBase->beginStream(s_streamID0, streamContext); @@ -552,7 +556,10 @@ testStreamFilter::testStreamFilter() edm::StreamContext streamContext(s_streamID0, nullptr); iBase->endStream(s_streamID0, streamContext); }; - m_transToFunc[Trans::kEndJob] = [](edm::Worker* iBase) { iBase->endJob(); }; + m_transToFunc[Trans::kEndJob] = [](edm::Worker* iBase) { + edm::GlobalContext globalContext(edm::GlobalContext::Transition::kEndJob, nullptr); + iBase->endJob(globalContext); + }; } namespace { @@ -587,14 +594,17 @@ template void testStreamFilter::testTransitions(std::shared_ptr iMod, Expectations const& iExpect) { oneapi::tbb::global_control control(oneapi::tbb::global_control::max_allowed_parallelism, 1); - edm::WorkerT wOther{iMod, m_desc, nullptr}; + edm::WorkerT wBeginJobEndJob{iMod, m_desc, nullptr}; + edm::WorkerT wBeginStreamEndStream{iMod, m_desc, nullptr}; edm::WorkerT wGlobalLumi{iMod, m_desc, nullptr}; edm::WorkerT wStreamLumi{iMod, m_desc, nullptr}; edm::WorkerT wGlobalRun{iMod, m_desc, nullptr}; edm::WorkerT wStreamRun{iMod, m_desc, nullptr}; for (auto& keyVal : m_transToFunc) { - edm::Worker* worker = &wOther; - if (keyVal.first == Trans::kStreamBeginLuminosityBlock || keyVal.first == Trans::kStreamEndLuminosityBlock) { + edm::Worker* worker = &wBeginJobEndJob; + if (keyVal.first == Trans::kBeginStream || keyVal.first == Trans::kEndStream) { + worker = &wBeginStreamEndStream; + } else if (keyVal.first == Trans::kStreamBeginLuminosityBlock || keyVal.first == Trans::kStreamEndLuminosityBlock) { worker = &wStreamLumi; } else if (keyVal.first == Trans::kGlobalBeginLuminosityBlock || keyVal.first == Trans::kGlobalEndLuminosityBlock) { worker = &wGlobalLumi; diff --git a/FWCore/Framework/test/stream_producer_t.cppunit.cc b/FWCore/Framework/test/stream_producer_t.cppunit.cc index c2a3f00eb8d98..e39a35eb291fd 100644 --- a/FWCore/Framework/test/stream_producer_t.cppunit.cc +++ b/FWCore/Framework/test/stream_producer_t.cppunit.cc @@ -22,6 +22,7 @@ #include "DataFormats/Provenance/interface/BranchIDListHelper.h" #include "DataFormats/Provenance/interface/ThinnedAssociationsHelper.h" #include "FWCore/Framework/interface/HistoryAppender.h" +#include "FWCore/ServiceRegistry/interface/GlobalContext.h" #include "FWCore/ServiceRegistry/interface/ParentContext.h" #include "FWCore/ServiceRegistry/interface/StreamContext.h" #include "FWCore/Concurrency/interface/FinalWaitingTask.h" @@ -426,7 +427,10 @@ testStreamProducer::testStreamProducer() m_actReg.reset(new edm::ActivityRegistry); //For each transition, bind a lambda which will call the proper method of the Worker - m_transToFunc[Trans::kBeginJob] = [](edm::Worker* iBase) { iBase->beginJob(); }; + m_transToFunc[Trans::kBeginJob] = [](edm::Worker* iBase) { + edm::GlobalContext globalContext(edm::GlobalContext::Transition::kBeginJob, nullptr); + iBase->beginJob(globalContext); + }; m_transToFunc[Trans::kBeginStream] = [](edm::Worker* iBase) { edm::StreamContext streamContext(s_streamID0, nullptr); iBase->beginStream(s_streamID0, streamContext); @@ -513,7 +517,10 @@ testStreamProducer::testStreamProducer() edm::StreamContext streamContext(s_streamID0, nullptr); iBase->endStream(s_streamID0, streamContext); }; - m_transToFunc[Trans::kEndJob] = [](edm::Worker* iBase) { iBase->endJob(); }; + m_transToFunc[Trans::kEndJob] = [](edm::Worker* iBase) { + edm::GlobalContext globalContext(edm::GlobalContext::Transition::kEndJob, nullptr); + iBase->endJob(globalContext); + }; } namespace { @@ -548,14 +555,17 @@ template void testStreamProducer::testTransitions(std::shared_ptr iMod, Expectations const& iExpect) { oneapi::tbb::global_control control(oneapi::tbb::global_control::max_allowed_parallelism, 1); - edm::WorkerT wOther{iMod, m_desc, nullptr}; + edm::WorkerT wBeginJobEndJob{iMod, m_desc, nullptr}; + edm::WorkerT wBeginStreamEndStream{iMod, m_desc, nullptr}; edm::WorkerT wGlobalLumi{iMod, m_desc, nullptr}; edm::WorkerT wStreamLumi{iMod, m_desc, nullptr}; edm::WorkerT wGlobalRun{iMod, m_desc, nullptr}; edm::WorkerT wStreamRun{iMod, m_desc, nullptr}; for (auto& keyVal : m_transToFunc) { - edm::Worker* worker = &wOther; - if (keyVal.first == Trans::kStreamBeginLuminosityBlock || keyVal.first == Trans::kStreamEndLuminosityBlock) { + edm::Worker* worker = &wBeginJobEndJob; + if (keyVal.first == Trans::kBeginStream || keyVal.first == Trans::kEndStream) { + worker = &wBeginStreamEndStream; + } else if (keyVal.first == Trans::kStreamBeginLuminosityBlock || keyVal.first == Trans::kStreamEndLuminosityBlock) { worker = &wStreamLumi; } else if (keyVal.first == Trans::kGlobalBeginLuminosityBlock || keyVal.first == Trans::kGlobalEndLuminosityBlock) { worker = &wGlobalLumi; diff --git a/FWCore/Framework/test/unit_test_outputs/test_deepCall_unscheduled.log b/FWCore/Framework/test/unit_test_outputs/test_deepCall_unscheduled.log index 1687159d906e0..56af862934c07 100644 --- a/FWCore/Framework/test/unit_test_outputs/test_deepCall_unscheduled.log +++ b/FWCore/Framework/test/unit_test_outputs/test_deepCall_unscheduled.log @@ -35,6 +35,7 @@ Module type=IntProducer, Module label=one, Parameter Set ID=dd3aecb8f6531b74585c ++++ starting: begin job for module with label 'p' id = 2 ++++ finished: begin job for module with label 'p' id = 2 ++ finished: begin job +++ starting: begin stream 0 ++++ starting: begin stream for module: stream = 0 label = 'get' id = 3 ++++ finished: begin stream for module: stream = 0 label = 'get' id = 3 ++++ starting: begin stream for module: stream = 0 label = 'one' id = 4 @@ -67,6 +68,7 @@ ModuleCallingContext state = Running ++++ finished: begin stream for module: stream = 0 label = 'result2' id = 6 ++++ starting: begin stream for module: stream = 0 label = 'result4' id = 7 ++++ finished: begin stream for module: stream = 0 label = 'result4' id = 7 +++ finished: begin stream 0 ++++ starting: begin process block ++++ finished: begin process block ++++ queuing: EventSetup synchronization run: 1 lumi: 0 event: 0 @@ -544,6 +546,7 @@ ModuleCallingContext state = Running ++++ finished: end process block ++++ starting: write process block ++++ finished: write process block +++ starting: end stream 0 ++++ starting: end stream for module: stream = 0 label = 'get' id = 3 ++++ finished: end stream for module: stream = 0 label = 'get' id = 3 ++++ starting: end stream for module: stream = 0 label = 'one' id = 4 @@ -576,6 +579,8 @@ ModuleCallingContext state = Running ++++ finished: end stream for module: stream = 0 label = 'result2' id = 6 ++++ starting: end stream for module: stream = 0 label = 'result4' id = 7 ++++ finished: end stream for module: stream = 0 label = 'result4' id = 7 +++ finished: end stream 0 +++ starting: end job ++++ starting: end job for module with label 'one' id = 4 Module type=IntProducer, Module label=one, Parameter Set ID=dd3aecb8f6531b74585c9fe89286679e ++++ finished: end job for module with label 'one' id = 4 diff --git a/FWCore/Framework/test/unit_test_outputs/test_onPath_unscheduled.log b/FWCore/Framework/test/unit_test_outputs/test_onPath_unscheduled.log index 3d5809c5bcc42..7981650d927f6 100644 --- a/FWCore/Framework/test/unit_test_outputs/test_onPath_unscheduled.log +++ b/FWCore/Framework/test/unit_test_outputs/test_onPath_unscheduled.log @@ -27,6 +27,7 @@ ++++ starting: begin job for module with label 'p' id = 2 ++++ finished: begin job for module with label 'p' id = 2 ++ finished: begin job +++ starting: begin stream 0 ++++ starting: begin stream for module: stream = 0 label = 'one' id = 3 ++++ finished: begin stream for module: stream = 0 label = 'one' id = 3 ++++ starting: begin stream for module: stream = 0 label = 'getOne' id = 4 @@ -35,6 +36,7 @@ ++++ finished: begin stream for module: stream = 0 label = 'two' id = 5 ++++ starting: begin stream for module: stream = 0 label = 'getTwo' id = 6 ++++ finished: begin stream for module: stream = 0 label = 'getTwo' id = 6 +++ finished: begin stream 0 ++++ starting: begin process block ++++ finished: begin process block ++++ queuing: EventSetup synchronization run: 1 lumi: 0 event: 0 @@ -168,6 +170,7 @@ ++++ finished: end process block ++++ starting: write process block ++++ finished: write process block +++ starting: end stream 0 ++++ starting: end stream for module: stream = 0 label = 'one' id = 3 ++++ finished: end stream for module: stream = 0 label = 'one' id = 3 ++++ starting: end stream for module: stream = 0 label = 'getOne' id = 4 @@ -176,6 +179,8 @@ ++++ finished: end stream for module: stream = 0 label = 'two' id = 5 ++++ starting: end stream for module: stream = 0 label = 'getTwo' id = 6 ++++ finished: end stream for module: stream = 0 label = 'getTwo' id = 6 +++ finished: end stream 0 +++ starting: end job ++++ starting: end job for module with label 'one' id = 3 ++++ finished: end job for module with label 'one' id = 3 ++++ starting: end job for module with label 'getOne' id = 4 diff --git a/FWCore/Integration/plugins/ExceptionThrowingProducer.cc b/FWCore/Integration/plugins/ExceptionThrowingProducer.cc index c4ad2acc55dc1..797287bacf79b 100644 --- a/FWCore/Integration/plugins/ExceptionThrowingProducer.cc +++ b/FWCore/Integration/plugins/ExceptionThrowingProducer.cc @@ -25,6 +25,7 @@ #include "FWCore/ParameterSet/interface/ParameterSetDescription.h" #include "FWCore/ServiceRegistry/interface/Service.h" #include "FWCore/Utilities/interface/Exception.h" +#include "FWCore/Utilities/interface/StreamID.h" #include #include @@ -33,6 +34,11 @@ constexpr unsigned int kTestStreams = 4; constexpr unsigned int kUnset = std::numeric_limits::max(); constexpr unsigned int kNumberOfTestModules = 2; +// 3 modules configured plus TriggerResultsInserter plus PathStatusInserter plus EndPathStatusInserter +constexpr unsigned int kNumberOfModulesWithJobTransitions = 6; +constexpr unsigned int kNumberOfModulesWithStreamTransitions = 3; +constexpr unsigned int kNumberOfModulesWithProcessBlockTransitions = 2; +constexpr unsigned int kStreamToThrowOn = 2; namespace edmtest { @@ -40,11 +46,19 @@ namespace edmtest { struct Cache {}; } // namespace - class ExceptionThrowingProducer - : public edm::global::EDProducer, edm::RunCache, edm::LuminosityBlockCache> { + class ExceptionThrowingProducer : public edm::global::EDProducer, + edm::RunCache, + edm::LuminosityBlockCache, + edm::WatchProcessBlock> { public: explicit ExceptionThrowingProducer(edm::ParameterSet const&); + ~ExceptionThrowingProducer() noexcept(false) override; + ExceptionThrowingProducer(const ExceptionThrowingProducer&) = delete; + ExceptionThrowingProducer& operator=(const ExceptionThrowingProducer&) = delete; + ExceptionThrowingProducer(ExceptionThrowingProducer&&) = delete; + ExceptionThrowingProducer& operator=(ExceptionThrowingProducer&&) = delete; + void produce(edm::StreamID, edm::Event&, edm::EventSetup const&) const override; std::shared_ptr globalBeginRun(edm::Run const&, edm::EventSetup const&) const override; @@ -58,23 +72,41 @@ namespace edmtest { void streamBeginLuminosityBlock(edm::StreamID, edm::LuminosityBlock const&, edm::EventSetup const&) const override; void streamEndLuminosityBlock(edm::StreamID, edm::LuminosityBlock const&, edm::EventSetup const&) const override; void streamEndRun(edm::StreamID, edm::Run const&, edm::EventSetup const&) const override; + void endStream(edm::StreamID) const override; + + void beginProcessBlock(edm::ProcessBlock const& processBlock) override; + void endProcessBlock(edm::ProcessBlock const& processBlock) override; + void beginJob() override; void endJob() override; static void fillDescriptions(edm::ConfigurationDescriptions&); private: - bool verbose_; - - edm::EventID eventIDThrowOnEvent_; - edm::EventID eventIDThrowOnGlobalBeginRun_; - edm::EventID eventIDThrowOnGlobalBeginLumi_; - edm::EventID eventIDThrowOnGlobalEndRun_; - edm::EventID eventIDThrowOnGlobalEndLumi_; - edm::EventID eventIDThrowOnStreamBeginRun_; - edm::EventID eventIDThrowOnStreamBeginLumi_; - edm::EventID eventIDThrowOnStreamEndRun_; - edm::EventID eventIDThrowOnStreamEndLumi_; + const bool verbose_; + + const edm::EventID eventIDThrowOnEvent_; + const edm::EventID eventIDThrowOnGlobalBeginRun_; + const edm::EventID eventIDThrowOnGlobalBeginLumi_; + const edm::EventID eventIDThrowOnGlobalEndRun_; + const edm::EventID eventIDThrowOnGlobalEndLumi_; + const edm::EventID eventIDThrowOnStreamBeginRun_; + const edm::EventID eventIDThrowOnStreamBeginLumi_; + const edm::EventID eventIDThrowOnStreamEndRun_; + const edm::EventID eventIDThrowOnStreamEndLumi_; + const bool throwInBeginJob_; + const bool throwInBeginStream_; + const bool throwInBeginProcessBlock_; + const bool throwInEndProcessBlock_; + const bool throwInEndStream_; + const bool throwInEndJob_; + + unsigned int nBeginJob_ = 0; + mutable std::atomic nBeginStream_{0}; + unsigned int nBeginProcessBlock_ = 0; + unsigned int nEndProcessBlock_ = 0; + mutable std::atomic nEndStream_{0}; + unsigned int nEndJob_ = 0; mutable std::vector nStreamBeginLumi_; mutable std::vector nStreamEndLumi_; @@ -86,19 +118,31 @@ namespace edmtest { mutable std::atomic nGlobalBeginRun_{0}; mutable std::atomic nGlobalEndRun_{0}; - unsigned int expectedStreamBeginLumi_; - unsigned int expectedOffsetNoStreamEndLumi_; + const unsigned int expectedNBeginJob_; + const unsigned int expectedNBeginStream_; + const unsigned int expectedNBeginProcessBlock_; + const unsigned int expectedNEndProcessBlock_; + const unsigned int expectedNEndStream_; + const unsigned int expectedNEndJob_; + const bool expectNoRunsProcessed_; + + const unsigned int expectedOffsetNoEndJob_; + const unsigned int expectedOffsetNoEndStream_; + const unsigned int expectedOffsetNoEndProcessBlock_; + + const unsigned int expectedStreamBeginLumi_; + const unsigned int expectedOffsetNoStreamEndLumi_; mutable unsigned int streamWithBeginLumiException_ = kUnset; - unsigned int expectedGlobalBeginLumi_; - unsigned int expectedOffsetNoGlobalEndLumi_; - unsigned int expectedOffsetNoWriteLumi_; + const unsigned int expectedGlobalBeginLumi_; + const unsigned int expectedOffsetNoGlobalEndLumi_; + const unsigned int expectedOffsetNoWriteLumi_; - unsigned int expectedStreamBeginRun_; - unsigned int expectedOffsetNoStreamEndRun_; + const unsigned int expectedStreamBeginRun_; + const unsigned int expectedOffsetNoStreamEndRun_; mutable unsigned int streamWithBeginRunException_ = kUnset; - unsigned int expectedGlobalBeginRun_; - unsigned int expectedOffsetNoGlobalEndRun_; - unsigned int expectedOffsetNoWriteRun_; + const unsigned int expectedGlobalBeginRun_; + const unsigned int expectedOffsetNoGlobalEndRun_; + const unsigned int expectedOffsetNoWriteRun_; mutable std::atomic streamBeginLumiExceptionOccurred_ = false; mutable std::atomic streamEndLumiExceptionOccurred_ = false; @@ -120,10 +164,26 @@ namespace edmtest { eventIDThrowOnStreamBeginLumi_(pset.getUntrackedParameter("eventIDThrowOnStreamBeginLumi")), eventIDThrowOnStreamEndRun_(pset.getUntrackedParameter("eventIDThrowOnStreamEndRun")), eventIDThrowOnStreamEndLumi_(pset.getUntrackedParameter("eventIDThrowOnStreamEndLumi")), + throwInBeginJob_(pset.getUntrackedParameter("throwInBeginJob")), + throwInBeginStream_(pset.getUntrackedParameter("throwInBeginStream")), + throwInBeginProcessBlock_(pset.getUntrackedParameter("throwInBeginProcessBlock")), + throwInEndProcessBlock_(pset.getUntrackedParameter("throwInEndProcessBlock")), + throwInEndStream_(pset.getUntrackedParameter("throwInEndStream")), + throwInEndJob_(pset.getUntrackedParameter("throwInEndJob")), nStreamBeginLumi_(kTestStreams, 0), nStreamEndLumi_(kTestStreams, 0), nStreamBeginRun_(kTestStreams, 0), nStreamEndRun_(kTestStreams, 0), + expectedNBeginJob_(pset.getUntrackedParameter("expectedNBeginJob")), + expectedNBeginStream_(pset.getUntrackedParameter("expectedNBeginStream")), + expectedNBeginProcessBlock_(pset.getUntrackedParameter("expectedNBeginProcessBlock")), + expectedNEndProcessBlock_(pset.getUntrackedParameter("expectedNEndProcessBlock")), + expectedNEndStream_(pset.getUntrackedParameter("expectedNEndStream")), + expectedNEndJob_(pset.getUntrackedParameter("expectedNEndJob")), + expectNoRunsProcessed_(pset.getUntrackedParameter("expectNoRunsProcessed")), + expectedOffsetNoEndJob_(pset.getUntrackedParameter("expectedOffsetNoEndJob")), + expectedOffsetNoEndStream_(pset.getUntrackedParameter("expectedOffsetNoEndStream")), + expectedOffsetNoEndProcessBlock_(pset.getUntrackedParameter("expectedOffsetNoEndProcessBlock")), expectedStreamBeginLumi_(pset.getUntrackedParameter("expectedStreamBeginLumi")), expectedOffsetNoStreamEndLumi_(pset.getUntrackedParameter("expectedOffsetNoStreamEndLumi")), expectedGlobalBeginLumi_(pset.getUntrackedParameter("expectedGlobalBeginLumi")), @@ -135,6 +195,40 @@ namespace edmtest { expectedOffsetNoGlobalEndRun_(pset.getUntrackedParameter("expectedOffsetNoGlobalEndRun")), expectedOffsetNoWriteRun_(pset.getUntrackedParameter("expectedOffsetNoWriteRun")) {} + ExceptionThrowingProducer::~ExceptionThrowingProducer() noexcept(false) { + if (nBeginJob_ != expectedNBeginJob_) { + edm::LogAbsolute("ExceptionThrowingProducer") + << "ExceptionThrowingProducer::beginJob did not run expected number of times."; + edm::LogAbsolute("ExceptionThrowingProducer") << "At least one test in ExceptionThrowingProducer FAILED"; + } else if (nEndJob_ != expectedNEndJob_) { + edm::LogAbsolute("ExceptionThrowingProducer") + << "ExceptionThrowingProducer::endJob did not run expected number of times."; + edm::LogAbsolute("ExceptionThrowingProducer") << "At least one test in ExceptionThrowingProducer FAILED"; + } else if (nEndJob_ == 0u && nBeginProcessBlock_ == 0 && nEndProcessBlock_ == 0 && nBeginStream_.load() == 0 && + nEndStream_.load() == 0 && nGlobalBeginRun_.load() == 0 && nGlobalEndRun_.load() == 0) { + edm::LogAbsolute("ExceptionThrowingProducer") << "All tests in ExceptionThrowingProducer PASSED"; + } + + edm::Service serviceOne; + + if (verbose_) { + edm::LogAbsolute("ExceptionThrowingProducer") << "serviceOne->nPostEndJob = " << serviceOne->nPostEndJob(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPreModuleEndJob = " << serviceOne->nPreModuleEndJob(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPostModuleEndJob = " << serviceOne->nPostModuleEndJob(); + } + + if (serviceOne->nPostEndJob() != nBeginJob_ || + serviceOne->nPreModuleEndJob() != nBeginJob_ * kNumberOfModulesWithJobTransitions - expectedOffsetNoEndJob_ || + serviceOne->nPostModuleEndJob() != nBeginJob_ * kNumberOfModulesWithJobTransitions - expectedOffsetNoEndJob_) { + edm::LogAbsolute("ExceptionThrowingProducer") + << "FAILED: Unexpected number of service end job related signals in TestServiceOne, checking while in " + "ExceptionThrowingProducer destructor"; + edm::LogAbsolute("ExceptionThrowingProducer") << "At least one test in ExceptionThrowingProducer FAILED"; + } + } + void ExceptionThrowingProducer::produce(edm::StreamID, edm::Event& event, edm::EventSetup const&) const { if (event.id() == eventIDThrowOnEvent_) { throw cms::Exception("IntentionalTestException") @@ -187,7 +281,13 @@ namespace edmtest { } } - std::unique_ptr ExceptionThrowingProducer::beginStream(edm::StreamID) const { + std::unique_ptr ExceptionThrowingProducer::beginStream(edm::StreamID streamID) const { + ++nBeginStream_; + if (throwInBeginStream_ && streamID.value() == kStreamToThrowOn) { + throw cms::Exception("IntentionalTestException") + << "ExceptionThrowingProducer::beginStream, module configured to throw during beginStream for stream: " + << kStreamToThrowOn; + } return std::make_unique(); } @@ -265,9 +365,79 @@ namespace edmtest { } } + void ExceptionThrowingProducer::endStream(edm::StreamID streamID) const { + ++nEndStream_; + if (throwInEndStream_ && streamID.value() == kStreamToThrowOn) { + throw cms::Exception("IntentionalTestException") + << "ExceptionThrowingProducer::endStream, module configured to throw during endStream for stream: " + << kStreamToThrowOn; + } + } + + void ExceptionThrowingProducer::beginProcessBlock(edm::ProcessBlock const& processBlock) { + ++nBeginProcessBlock_; + if (throwInBeginProcessBlock_) { + throw cms::Exception("IntentionalTestException") + << "ExceptionThrowingProducer::beginProcessBlock, module configured to throw during beginProcessBlock"; + } + } + + void ExceptionThrowingProducer::endProcessBlock(edm::ProcessBlock const& processBlock) { + ++nEndProcessBlock_; + if (throwInEndProcessBlock_) { + throw cms::Exception("IntentionalTestException") + << "ExceptionThrowingProducer::endProcessBlock, module configured to throw during endProcessBlock"; + } + } + + void ExceptionThrowingProducer::beginJob() { + ++nBeginJob_; + if (throwInBeginJob_) { + throw cms::Exception("IntentionalTestException") + << "ExceptionThrowingProducer::beginJob, module configured to throw during beginJob"; + } + } + void ExceptionThrowingProducer::endJob() { + ++nEndJob_; + bool testsPass = true; + if (nBeginStream_.load() != expectedNBeginStream_) { + edm::LogAbsolute("ExceptionThrowingProducer") + << "FAILED: Unexpected number of beginStream transitions, saw: " << nBeginStream_.load() + << " expected: " << expectedNBeginStream_; + testsPass = false; + } + + if (nBeginProcessBlock_ != expectedNBeginProcessBlock_) { + edm::LogAbsolute("ExceptionThrowingProducer") + << "FAILED: Unexpected number of beginProcessBlock transitions, saw: " << nBeginProcessBlock_ + << " expected: " << expectedNBeginProcessBlock_; + testsPass = false; + } + + if (nEndProcessBlock_ != expectedNEndProcessBlock_) { + edm::LogAbsolute("ExceptionThrowingProducer") + << "FAILED: Unexpected number of endProcessBlock transitions, saw: " << nEndProcessBlock_ + << " expected: " << expectedNEndProcessBlock_; + testsPass = false; + } + + if (nEndStream_.load() != expectedNEndStream_) { + edm::LogAbsolute("ExceptionThrowingProducer") + << "FAILED: Unexpected number of endStream transitions, saw: " << nEndStream_.load() + << " expected: " << expectedNEndStream_; + testsPass = false; + } + + if (expectNoRunsProcessed_ && nGlobalBeginRun_.load() != 0) { + edm::LogAbsolute("ExceptionThrowingProducer") + << "FAILED: Unexpected number of globalBeginRun transitions, saw: " << nGlobalBeginRun_.load() + << " expected: " << 0; + testsPass = false; + } + unsigned int totalStreamBeginLumi = 0; unsigned int i = 0; for (auto const& nStreamBeginLumi : nStreamBeginLumi_) { @@ -358,6 +528,45 @@ namespace edmtest { } edm::Service serviceOne; + if (serviceOne->nPreBeginJob() != nBeginJob_ || serviceOne->nPostBeginJob() != nBeginJob_ || + serviceOne->nPreEndJob() != nBeginJob_ || + serviceOne->nPreModuleBeginJob() != nBeginJob_ * kNumberOfModulesWithJobTransitions || + serviceOne->nPostModuleBeginJob() != nBeginJob_ * kNumberOfModulesWithJobTransitions) { + edm::LogAbsolute("ExceptionThrowingProducer") + << "FAILED: Unexpected number of service transitions in TestServiceOne, beginJob and endJob"; + testsPass = false; + } + + if (serviceOne->nPreBeginStream() != nBeginStream_ || serviceOne->nPostBeginStream() != nBeginStream_ || + serviceOne->nPreEndStream() != nBeginStream_ || serviceOne->nPostEndStream() != nBeginStream_ || + serviceOne->nPreModuleBeginStream() != nBeginStream_ * kNumberOfModulesWithStreamTransitions || + serviceOne->nPostModuleBeginStream() != nBeginStream_ * kNumberOfModulesWithStreamTransitions || + serviceOne->nPreModuleEndStream() != + nBeginStream_ * kNumberOfModulesWithStreamTransitions - expectedOffsetNoEndStream_ || + serviceOne->nPostModuleEndStream() != + nBeginStream_ * kNumberOfModulesWithStreamTransitions - expectedOffsetNoEndStream_) { + edm::LogAbsolute("ExceptionThrowingProducer") + << "FAILED: Unexpected number of service transitions in TestServiceOne, beginStream and endStream"; + testsPass = false; + } + + if (serviceOne->nPreBeginProcessBlock() != nBeginProcessBlock_ || + serviceOne->nPostBeginProcessBlock() != nBeginProcessBlock_ || + serviceOne->nPreEndProcessBlock() != nBeginProcessBlock_ || + serviceOne->nPostEndProcessBlock() != nBeginProcessBlock_ || + serviceOne->nPreModuleBeginProcessBlock() != + nBeginProcessBlock_ * kNumberOfModulesWithProcessBlockTransitions || + serviceOne->nPostModuleBeginProcessBlock() != + nBeginProcessBlock_ * kNumberOfModulesWithProcessBlockTransitions || + serviceOne->nPreModuleEndProcessBlock() != + nBeginProcessBlock_ * kNumberOfModulesWithProcessBlockTransitions - expectedOffsetNoEndProcessBlock_ || + serviceOne->nPostModuleEndProcessBlock() != + nBeginProcessBlock_ * kNumberOfModulesWithProcessBlockTransitions - expectedOffsetNoEndProcessBlock_) { + edm::LogAbsolute("ExceptionThrowingProducer") << "FAILED: Unexpected number of service transitions in " + "TestServiceOne, beginProcessBlock and endProcessBlock"; + testsPass = false; + } + if (serviceOne->nPreStreamBeginLumi() != totalStreamBeginLumi || serviceOne->nPostStreamBeginLumi() != totalStreamBeginLumi || serviceOne->nPreStreamEndLumi() != totalStreamBeginLumi || @@ -486,10 +695,60 @@ namespace edmtest { } if (verbose_) { + edm::LogAbsolute("ExceptionThrowingProducer") << "nBeginJob_ = " << nBeginJob_; + edm::LogAbsolute("ExceptionThrowingProducer") << "nBeginStream_ = " << nBeginStream_.load(); + edm::LogAbsolute("ExceptionThrowingProducer") << "nBeginProcessBlock_ = " << nBeginProcessBlock_; + edm::LogAbsolute("ExceptionThrowingProducer") << "nEndProcessBlock_ = " << nEndProcessBlock_; + edm::LogAbsolute("ExceptionThrowingProducer") << "nEndStream_ = " << nEndStream_.load(); + edm::LogAbsolute("ExceptionThrowingProducer") << "nEndJob_ = " << nEndJob_ << "\n"; + edm::LogAbsolute("ExceptionThrowingProducer") << "nGlobalBeginLumi_ = " << nGlobalBeginLumi_; edm::LogAbsolute("ExceptionThrowingProducer") << "nGlobalEndLumi_ = " << nGlobalEndLumi_; edm::LogAbsolute("ExceptionThrowingProducer") << "nGlobalBeginRun_ = " << nGlobalBeginRun_; - edm::LogAbsolute("ExceptionThrowingProducer") << "nGlobalEndRun_ = " << nGlobalEndRun_; + edm::LogAbsolute("ExceptionThrowingProducer") << "nGlobalEndRun_ = " << nGlobalEndRun_ << "\n"; + + edm::LogAbsolute("ExceptionThrowingProducer") << "serviceOne->nPreBeginJob = " << serviceOne->nPreBeginJob(); + edm::LogAbsolute("ExceptionThrowingProducer") << "serviceOne->nPostBeginJob = " << serviceOne->nPostBeginJob(); + edm::LogAbsolute("ExceptionThrowingProducer") << "serviceOne->nPreEndJob = " << serviceOne->nPreEndJob(); + + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPreModuleBeginJob = " << serviceOne->nPreModuleBeginJob(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPostModuleBeginJob = " << serviceOne->nPostModuleBeginJob() << "\n"; + + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPreBeginStream = " << serviceOne->nPreBeginStream(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPostBeginStream = " << serviceOne->nPostBeginStream(); + edm::LogAbsolute("ExceptionThrowingProducer") << "serviceOne->nPreEndStream = " << serviceOne->nPreEndStream(); + edm::LogAbsolute("ExceptionThrowingProducer") << "serviceOne->nPostEndStream = " << serviceOne->nPostEndStream(); + + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPreModuleBeginStream = " << serviceOne->nPreModuleBeginStream(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPostModuleBeginStream = " << serviceOne->nPostModuleBeginStream(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPreModuleEndStream = " << serviceOne->nPreModuleEndStream(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPostModuleEndStream = " << serviceOne->nPostModuleEndStream() << "\n"; + + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPreBeginProcessBlock = " << serviceOne->nPreBeginProcessBlock(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPostBeginProcessBlock = " << serviceOne->nPostBeginProcessBlock(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPreEndProcessBlock = " << serviceOne->nPreEndProcessBlock(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPostEndProcessBlock = " << serviceOne->nPostEndProcessBlock(); + + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPreModuleBeginProcessBlock = " << serviceOne->nPreModuleBeginProcessBlock(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPostModuleBeginProcessBlock = " << serviceOne->nPostModuleBeginProcessBlock(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPreModuleEndProcessBlock = " << serviceOne->nPreModuleEndProcessBlock(); + edm::LogAbsolute("ExceptionThrowingProducer") + << "serviceOne->nPostModuleEndProcessBlock = " << serviceOne->nPostModuleEndProcessBlock() << "\n"; edm::LogAbsolute("ExceptionThrowingProducer") << "serviceOne->nPreStreamBeginLumi = " << serviceOne->nPreStreamBeginLumi(); @@ -573,6 +832,11 @@ namespace edmtest { } else { edm::LogAbsolute("ExceptionThrowingProducer") << "At least one test in ExceptionThrowingProducer FAILED"; } + + if (throwInEndJob_) { + throw cms::Exception("IntentionalTestException") + << "ExceptionThrowingProducer::endJob, module configured to throw during endJob"; + } } void ExceptionThrowingProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { @@ -589,6 +853,23 @@ namespace edmtest { desc.addUntracked("eventIDThrowOnStreamEndRun", invalidEventID); desc.addUntracked("eventIDThrowOnStreamEndLumi", invalidEventID); + desc.addUntracked("throwInBeginJob", false); + desc.addUntracked("throwInBeginStream", false); + desc.addUntracked("throwInBeginProcessBlock", false); + desc.addUntracked("throwInEndProcessBlock", false); + desc.addUntracked("throwInEndStream", false); + desc.addUntracked("throwInEndJob", false); + + desc.addUntracked("expectedNBeginJob", 1); + desc.addUntracked("expectedNBeginStream", 4); + desc.addUntracked("expectedNBeginProcessBlock", 1); + desc.addUntracked("expectedNEndProcessBlock", 1); + desc.addUntracked("expectedNEndStream", 4); + desc.addUntracked("expectedNEndJob", 1); + desc.addUntracked("expectNoRunsProcessed", false); + desc.addUntracked("expectedOffsetNoEndJob", 0); + desc.addUntracked("expectedOffsetNoEndStream", 0); + desc.addUntracked("expectedOffsetNoEndProcessBlock", 0); desc.addUntracked("expectedStreamBeginLumi", kUnset); desc.addUntracked("expectedOffsetNoStreamEndLumi", 0); desc.addUntracked("expectedGlobalBeginLumi", 0); diff --git a/FWCore/Integration/plugins/TestServiceOne.cc b/FWCore/Integration/plugins/TestServiceOne.cc index ba803f94b2d12..b2b17f9bc02da 100644 --- a/FWCore/Integration/plugins/TestServiceOne.cc +++ b/FWCore/Integration/plugins/TestServiceOne.cc @@ -57,8 +57,35 @@ namespace edmtest { TestServiceOne::TestServiceOne(edm::ParameterSet const& iPS, edm::ActivityRegistry& iRegistry) : verbose_(iPS.getUntrackedParameter("verbose")), printTimestamps_(iPS.getUntrackedParameter("printTimestamps")) { + iRegistry.watchPreBeginJob(this, &TestServiceOne::preBeginJob); + iRegistry.watchPostBeginJob(this, &TestServiceOne::postBeginJob); + iRegistry.watchPreEndJob(this, &TestServiceOne::preEndJob); + iRegistry.watchPostEndJob(this, &TestServiceOne::postEndJob); + + iRegistry.watchPreModuleBeginJob(this, &TestServiceOne::preModuleBeginJob); + iRegistry.watchPostModuleBeginJob(this, &TestServiceOne::postModuleBeginJob); + iRegistry.watchPreModuleEndJob(this, &TestServiceOne::preModuleEndJob); + iRegistry.watchPostModuleEndJob(this, &TestServiceOne::postModuleEndJob); + + iRegistry.watchPreBeginStream(this, &TestServiceOne::preBeginStream); + iRegistry.watchPostBeginStream(this, &TestServiceOne::postBeginStream); + iRegistry.watchPreEndStream(this, &TestServiceOne::preEndStream); + iRegistry.watchPostEndStream(this, &TestServiceOne::postEndStream); + + iRegistry.watchPreModuleBeginStream(this, &TestServiceOne::preModuleBeginStream); + iRegistry.watchPostModuleBeginStream(this, &TestServiceOne::postModuleBeginStream); + iRegistry.watchPreModuleEndStream(this, &TestServiceOne::preModuleEndStream); + iRegistry.watchPostModuleEndStream(this, &TestServiceOne::postModuleEndStream); + iRegistry.watchPreBeginProcessBlock(this, &TestServiceOne::preBeginProcessBlock); + iRegistry.watchPostBeginProcessBlock(this, &TestServiceOne::postBeginProcessBlock); iRegistry.watchPreEndProcessBlock(this, &TestServiceOne::preEndProcessBlock); + iRegistry.watchPostEndProcessBlock(this, &TestServiceOne::postEndProcessBlock); + + iRegistry.watchPreModuleBeginProcessBlock(this, &TestServiceOne::preModuleBeginProcessBlock); + iRegistry.watchPostModuleBeginProcessBlock(this, &TestServiceOne::postModuleBeginProcessBlock); + iRegistry.watchPreModuleEndProcessBlock(this, &TestServiceOne::preModuleEndProcessBlock); + iRegistry.watchPostModuleEndProcessBlock(this, &TestServiceOne::postModuleEndProcessBlock); iRegistry.watchPreStreamBeginLumi(this, &TestServiceOne::preStreamBeginLumi); iRegistry.watchPostStreamBeginLumi(this, &TestServiceOne::postStreamBeginLumi); @@ -115,15 +142,211 @@ namespace edmtest { descriptions.add("TestServiceOne", desc); } - void TestServiceOne::preBeginProcessBlock(GlobalContext const&) { + void TestServiceOne::preBeginJob(edm::PathsAndConsumesOfModulesBase const&, edm::ProcessContext const&) { + ++nPreBeginJob_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalIndent << "TestServiceOne::preBeginJob " << TimeStamper(printTimestamps_); + } + } + + void TestServiceOne::postBeginJob() { + ++nPostBeginJob_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalIndent << "TestServiceOne::postBeginJob " << TimeStamper(printTimestamps_); + } + } + + void TestServiceOne::preEndJob() { + ++nPreEndJob_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalIndent << "TestServiceOne::preEndJob " << TimeStamper(printTimestamps_); + } + } + + void TestServiceOne::postEndJob() { + ++nPostEndJob_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalIndent << "TestServiceOne::postEndJob " << TimeStamper(printTimestamps_); + } + } + + void TestServiceOne::preModuleBeginJob(edm::ModuleDescription const& desc) { + ++nPreModuleBeginJob_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalModuleIndent << "TestServiceOne::preModuleBeginJob " << TimeStamper(printTimestamps_) + << " label = " << desc.moduleLabel(); + } + } + + void TestServiceOne::postModuleBeginJob(edm::ModuleDescription const& desc) { + ++nPostModuleBeginJob_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalModuleIndent << "TestServiceOne::postModuleBeginJob " << TimeStamper(printTimestamps_) + << " label = " << desc.moduleLabel(); + } + } + + void TestServiceOne::preModuleEndJob(edm::ModuleDescription const& desc) { + ++nPreModuleEndJob_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalModuleIndent << "TestServiceOne::preModuleEndJob " << TimeStamper(printTimestamps_) + << " label = " << desc.moduleLabel(); + } + } + + void TestServiceOne::postModuleEndJob(edm::ModuleDescription const& desc) { + ++nPostModuleEndJob_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalModuleIndent << "TestServiceOne::postModuleEndJob " << TimeStamper(printTimestamps_) + << " label = " << desc.moduleLabel(); + } + } + + void TestServiceOne::preBeginStream(edm::StreamContext const& sc) { + ++nPreBeginStream_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << streamIndent << "TestServiceOne::preBeginStream " << TimeStamper(printTimestamps_) + << " stream = " << sc.streamID(); + } + } + + void TestServiceOne::postBeginStream(edm::StreamContext const& sc) { + ++nPostBeginStream_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << streamIndent << "TestServiceOne::postBeginStream " << TimeStamper(printTimestamps_) + << " stream = " << sc.streamID(); + } + } + + void TestServiceOne::preEndStream(edm::StreamContext const& sc) { + ++nPreEndStream_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << streamIndent << "TestServiceOne::preEndStream " << TimeStamper(printTimestamps_) + << " stream = " << sc.streamID(); + } + } + + void TestServiceOne::postEndStream(edm::StreamContext const& sc) { + ++nPostEndStream_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << streamIndent << "TestServiceOne::postEndStream " << TimeStamper(printTimestamps_) + << " stream = " << sc.streamID(); + } + } + + void TestServiceOne::preModuleBeginStream(edm::StreamContext const& sc, edm::ModuleCallingContext const& mcc) { + ++nPreModuleBeginStream_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << streamModuleIndent << "TestServiceOne::preModuleBeginStream " << TimeStamper(printTimestamps_) + << " stream = " << sc.streamID() << " label = " << mcc.moduleDescription()->moduleLabel(); + } + } + + void TestServiceOne::postModuleBeginStream(edm::StreamContext const& sc, edm::ModuleCallingContext const& mcc) { + ++nPostModuleBeginStream_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << streamModuleIndent << "TestServiceOne::postModuleBeginStream " << TimeStamper(printTimestamps_) + << " stream = " << sc.streamID() << " label = " << mcc.moduleDescription()->moduleLabel(); + } + } + + void TestServiceOne::preModuleEndStream(edm::StreamContext const& sc, edm::ModuleCallingContext const& mcc) { + ++nPreModuleEndStream_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << streamModuleIndent << "TestServiceOne::preModuleEndStream " << TimeStamper(printTimestamps_) + << " stream = " << sc.streamID() << " label = " << mcc.moduleDescription()->moduleLabel(); + } + } + + void TestServiceOne::postModuleEndStream(edm::StreamContext const& sc, edm::ModuleCallingContext const& mcc) { + ++nPostModuleEndStream_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << streamModuleIndent << "TestServiceOne::postModuleEndStream " << TimeStamper(printTimestamps_) + << " stream = " << sc.streamID() << " label = " << mcc.moduleDescription()->moduleLabel(); + } + } + + void TestServiceOne::preBeginProcessBlock(edm::GlobalContext const&) { + ++nPreBeginProcessBlock_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalIndent << "TestServiceOne::preBeginProcessBlock " << TimeStamper(printTimestamps_); + } + } + + void TestServiceOne::postBeginProcessBlock(edm::GlobalContext const&) { + ++nPostBeginProcessBlock_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalIndent << "TestServiceOne::postBeginProcessBlock " << TimeStamper(printTimestamps_); + } + } + + void TestServiceOne::preEndProcessBlock(edm::GlobalContext const&) { + ++nPreEndProcessBlock_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalIndent << "TestServiceOne::preEndProcessBlock " << TimeStamper(printTimestamps_); + } + } + + void TestServiceOne::postEndProcessBlock(edm::GlobalContext const&) { + ++nPostEndProcessBlock_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalIndent << "TestServiceOne::postEndProcessBlock " << TimeStamper(printTimestamps_); + } + } + + void TestServiceOne::preModuleBeginProcessBlock(edm::GlobalContext const&, edm::ModuleCallingContext const& mcc) { + ++nPreModuleBeginProcessBlock_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalModuleIndent << "TestServiceOne::preModuleBeginProcessBlock " << TimeStamper(printTimestamps_) + << " label = " << mcc.moduleDescription()->moduleLabel(); + } + } + + void TestServiceOne::postModuleBeginProcessBlock(edm::GlobalContext const&, edm::ModuleCallingContext const& mcc) { + ++nPostModuleBeginProcessBlock_; if (verbose_) { - edm::LogAbsolute("TestServiceOne") << "test message from TestServiceOne::preBeginProcessBlock"; + edm::LogAbsolute out("TestServiceOne"); + out << globalModuleIndent << "TestServiceOne::postModuleBeginProcessBlock " << TimeStamper(printTimestamps_) + << " label = " << mcc.moduleDescription()->moduleLabel(); } } - void TestServiceOne::preEndProcessBlock(GlobalContext const&) { + void TestServiceOne::preModuleEndProcessBlock(edm::GlobalContext const&, edm::ModuleCallingContext const& mcc) { + ++nPreModuleEndProcessBlock_; if (verbose_) { - edm::LogAbsolute("TestServiceOne") << "test message from TestServiceOne::preEndProcessBlock"; + edm::LogAbsolute out("TestServiceOne"); + out << globalModuleIndent << "TestServiceOne::preModuleEndProcessBlock " << TimeStamper(printTimestamps_) + << " label = " << mcc.moduleDescription()->moduleLabel(); + } + } + + void TestServiceOne::postModuleEndProcessBlock(edm::GlobalContext const&, edm::ModuleCallingContext const& mcc) { + ++nPostModuleEndProcessBlock_; + if (verbose_) { + edm::LogAbsolute out("TestServiceOne"); + out << globalModuleIndent << "TestServiceOne::postModuleEndProcessBlock " << TimeStamper(printTimestamps_) + << " label = " << mcc.moduleDescription()->moduleLabel(); } } @@ -467,6 +690,36 @@ namespace edmtest { } } + unsigned int TestServiceOne::nPreBeginJob() const { return nPreBeginJob_.load(); } + unsigned int TestServiceOne::nPostBeginJob() const { return nPostBeginJob_.load(); } + unsigned int TestServiceOne::nPreEndJob() const { return nPreEndJob_.load(); } + unsigned int TestServiceOne::nPostEndJob() const { return nPostEndJob_.load(); } + + unsigned int TestServiceOne::nPreModuleBeginJob() const { return nPreModuleBeginJob_.load(); } + unsigned int TestServiceOne::nPostModuleBeginJob() const { return nPostModuleBeginJob_.load(); } + unsigned int TestServiceOne::nPreModuleEndJob() const { return nPreModuleEndJob_.load(); } + unsigned int TestServiceOne::nPostModuleEndJob() const { return nPostModuleEndJob_.load(); } + + unsigned int TestServiceOne::nPreBeginStream() const { return nPreBeginStream_.load(); } + unsigned int TestServiceOne::nPostBeginStream() const { return nPostBeginStream_.load(); } + unsigned int TestServiceOne::nPreEndStream() const { return nPreEndStream_.load(); } + unsigned int TestServiceOne::nPostEndStream() const { return nPostEndStream_.load(); } + + unsigned int TestServiceOne::nPreModuleBeginStream() const { return nPreModuleBeginStream_.load(); } + unsigned int TestServiceOne::nPostModuleBeginStream() const { return nPostModuleBeginStream_.load(); } + unsigned int TestServiceOne::nPreModuleEndStream() const { return nPreModuleEndStream_.load(); } + unsigned int TestServiceOne::nPostModuleEndStream() const { return nPostModuleEndStream_.load(); } + + unsigned int TestServiceOne::nPreBeginProcessBlock() const { return nPreBeginProcessBlock_.load(); } + unsigned int TestServiceOne::nPostBeginProcessBlock() const { return nPostBeginProcessBlock_.load(); } + unsigned int TestServiceOne::nPreEndProcessBlock() const { return nPreEndProcessBlock_.load(); } + unsigned int TestServiceOne::nPostEndProcessBlock() const { return nPostEndProcessBlock_.load(); } + + unsigned int TestServiceOne::nPreModuleBeginProcessBlock() const { return nPreModuleBeginProcessBlock_.load(); } + unsigned int TestServiceOne::nPostModuleBeginProcessBlock() const { return nPostModuleBeginProcessBlock_.load(); } + unsigned int TestServiceOne::nPreModuleEndProcessBlock() const { return nPreModuleEndProcessBlock_.load(); } + unsigned int TestServiceOne::nPostModuleEndProcessBlock() const { return nPostModuleEndProcessBlock_.load(); } + unsigned int TestServiceOne::nPreStreamBeginLumi() const { return nPreStreamBeginLumi_.load(); } unsigned int TestServiceOne::nPostStreamBeginLumi() const { return nPostStreamBeginLumi_.load(); } unsigned int TestServiceOne::nPreStreamEndLumi() const { return nPreStreamEndLumi_.load(); } diff --git a/FWCore/Integration/plugins/TestServiceOne.h b/FWCore/Integration/plugins/TestServiceOne.h index b86a3bb00ba2a..170c17f159288 100644 --- a/FWCore/Integration/plugins/TestServiceOne.h +++ b/FWCore/Integration/plugins/TestServiceOne.h @@ -14,6 +14,7 @@ // Original Author: W. David Dagenhart // Created: 13 March 2024 +#include "DataFormats/Provenance/interface/ProvenanceFwd.h" #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" #include "FWCore/ParameterSet/interface/ParameterSet.h" #include "FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h" @@ -28,8 +29,35 @@ namespace edmtest { static void fillDescriptions(edm::ConfigurationDescriptions&); + void preBeginJob(edm::PathsAndConsumesOfModulesBase const&, edm::ProcessContext const&); + void postBeginJob(); + void preEndJob(); + void postEndJob(); + + void preModuleBeginJob(edm::ModuleDescription const&); + void postModuleBeginJob(edm::ModuleDescription const&); + void preModuleEndJob(edm::ModuleDescription const&); + void postModuleEndJob(edm::ModuleDescription const&); + + void preBeginStream(edm::StreamContext const&); + void postBeginStream(edm::StreamContext const&); + void preEndStream(edm::StreamContext const&); + void postEndStream(edm::StreamContext const&); + + void preModuleBeginStream(edm::StreamContext const&, edm::ModuleCallingContext const&); + void postModuleBeginStream(edm::StreamContext const&, edm::ModuleCallingContext const&); + void preModuleEndStream(edm::StreamContext const&, edm::ModuleCallingContext const&); + void postModuleEndStream(edm::StreamContext const&, edm::ModuleCallingContext const&); + void preBeginProcessBlock(edm::GlobalContext const&); + void postBeginProcessBlock(edm::GlobalContext const&); void preEndProcessBlock(edm::GlobalContext const&); + void postEndProcessBlock(edm::GlobalContext const&); + + void preModuleBeginProcessBlock(edm::GlobalContext const&, edm::ModuleCallingContext const&); + void postModuleBeginProcessBlock(edm::GlobalContext const&, edm::ModuleCallingContext const&); + void preModuleEndProcessBlock(edm::GlobalContext const&, edm::ModuleCallingContext const&); + void postModuleEndProcessBlock(edm::GlobalContext const&, edm::ModuleCallingContext const&); void preStreamBeginLumi(edm::StreamContext const&); void postStreamBeginLumi(edm::StreamContext const&); @@ -77,6 +105,36 @@ namespace edmtest { void preGlobalWriteRun(edm::GlobalContext const&); void postGlobalWriteRun(edm::GlobalContext const&); + unsigned int nPreBeginJob() const; + unsigned int nPostBeginJob() const; + unsigned int nPreEndJob() const; + unsigned int nPostEndJob() const; + + unsigned int nPreModuleBeginJob() const; + unsigned int nPostModuleBeginJob() const; + unsigned int nPreModuleEndJob() const; + unsigned int nPostModuleEndJob() const; + + unsigned int nPreBeginStream() const; + unsigned int nPostBeginStream() const; + unsigned int nPreEndStream() const; + unsigned int nPostEndStream() const; + + unsigned int nPreModuleBeginStream() const; + unsigned int nPostModuleBeginStream() const; + unsigned int nPreModuleEndStream() const; + unsigned int nPostModuleEndStream() const; + + unsigned int nPreBeginProcessBlock() const; + unsigned int nPostBeginProcessBlock() const; + unsigned int nPreEndProcessBlock() const; + unsigned int nPostEndProcessBlock() const; + + unsigned int nPreModuleBeginProcessBlock() const; + unsigned int nPostModuleBeginProcessBlock() const; + unsigned int nPreModuleEndProcessBlock() const; + unsigned int nPostModuleEndProcessBlock() const; + unsigned int nPreStreamBeginLumi() const; unsigned int nPostStreamBeginLumi() const; unsigned int nPreStreamEndLumi() const; @@ -127,6 +185,36 @@ namespace edmtest { bool verbose_; bool printTimestamps_; + std::atomic nPreBeginJob_ = 0; + std::atomic nPostBeginJob_ = 0; + std::atomic nPreEndJob_ = 0; + std::atomic nPostEndJob_ = 0; + + std::atomic nPreModuleBeginJob_ = 0; + std::atomic nPostModuleBeginJob_ = 0; + std::atomic nPreModuleEndJob_ = 0; + std::atomic nPostModuleEndJob_ = 0; + + std::atomic nPreBeginStream_ = 0; + std::atomic nPostBeginStream_ = 0; + std::atomic nPreEndStream_ = 0; + std::atomic nPostEndStream_ = 0; + + std::atomic nPreModuleBeginStream_ = 0; + std::atomic nPostModuleBeginStream_ = 0; + std::atomic nPreModuleEndStream_ = 0; + std::atomic nPostModuleEndStream_ = 0; + + std::atomic nPreBeginProcessBlock_ = 0; + std::atomic nPostBeginProcessBlock_ = 0; + std::atomic nPreEndProcessBlock_ = 0; + std::atomic nPostEndProcessBlock_ = 0; + + std::atomic nPreModuleBeginProcessBlock_ = 0; + std::atomic nPostModuleBeginProcessBlock_ = 0; + std::atomic nPreModuleEndProcessBlock_ = 0; + std::atomic nPostModuleEndProcessBlock_ = 0; + std::atomic nPreStreamBeginLumi_ = 0; std::atomic nPostStreamBeginLumi_ = 0; std::atomic nPreStreamEndLumi_ = 0; diff --git a/FWCore/Integration/test/BuildFile.xml b/FWCore/Integration/test/BuildFile.xml index 9a56a76ce0497..6b0c0eb407ac7 100644 --- a/FWCore/Integration/test/BuildFile.xml +++ b/FWCore/Integration/test/BuildFile.xml @@ -115,7 +115,7 @@ - + diff --git a/FWCore/Integration/test/run_TestFrameworkExceptionHandling.sh b/FWCore/Integration/test/run_TestFrameworkExceptionHandling.sh index 43105ec766563..aa5f77f563cf0 100755 --- a/FWCore/Integration/test/run_TestFrameworkExceptionHandling.sh +++ b/FWCore/Integration/test/run_TestFrameworkExceptionHandling.sh @@ -5,79 +5,121 @@ LOCAL_TEST_DIR=${SCRAM_TEST_PATH} function die { echo Failure $1: status $2 ; exit $2 ; } logfile=testFrameworkExceptionHandling$1.log -echo $logfile cmsRun ${LOCAL_TEST_DIR}/testFrameworkExceptionHandling_cfg.py testNumber=$1 &> $logfile && die "cmsRun testFrameworkExceptionHandling_cfg.py testNumber=$1" 1 +echo "There are two instances of ExceptionThrowingProducer with different module labels in this test." +echo "Usually one of them is configured to throw an intentional exception (an exception message should" +echo "always show up in the log file). The shell script and both modules run tests on how the Framework" +echo "handles the exception. The modules separately report in the log and here whether those tests PASSED" +echo "or FAILED." +echo "" + +grep "ExceptionThrowingProducer FAILED" $logfile && die " - FAILED because found the following string in the log file: ExceptionThrowingProducer FAILED " 1 +grep "ExceptionThrowingProducer PASSED" $logfile || die " - FAILED because cannot find the following string in the log file: ExceptionThrowingProducer PASSED " $? + # Look for the content that we expect to be in the exception messages. # The first five should be the same in all log files. # The other two or three are different for each case. -grep "Begin Fatal Exception" $logfile || die " - Cannot find the following string in the exception message: Begin Fatal Exception " $? +grep -q "Begin Fatal Exception" $logfile || die " - Cannot find the following string in the exception message: Begin Fatal Exception " $? -grep "An exception of category 'IntentionalTestException' occurred while" $logfile || die " - Cannot find the following string in the exception message: An exception of category 'IntentionalTestException' occurred while " $? +grep -q "An exception of category 'IntentionalTestException' occurred while" $logfile || die " - Cannot find the following string in the exception message: An exception of category 'IntentionalTestException' occurred while " $? -grep "Calling method for module ExceptionThrowingProducer/'throwException'" $logfile || die " - Cannot find the following string in the exception message: Calling method for module ExceptionThrowingProducer/'throwException' " $? +grep -q "Calling method for module ExceptionThrowingProducer/'throwException'" $logfile || die " - Cannot find the following string in the exception message: Calling method for module ExceptionThrowingProducer/'throwException' " $? -grep "Exception Message:" $logfile || die " - Cannot find the following string in the exception message: Exception Message: " $? +grep -q "Exception Message:" $logfile || die " - Cannot find the following string in the exception message: Exception Message: " $? -grep "End Fatal Exception" $logfile || die " - Cannot find the following string in the exception message: End Fatal Exception " $? - -grep "ExceptionThrowingProducer PASSED" $logfile || die " - FAILED because cannot find the following string in the log file: ExceptionThrowingProducer PASSED " $? -grep "ExceptionThrowingProducer FAILED" $logfile && die " - FAILED because found the following string in the log file: ExceptionThrowingProducer FAILED " 1 +grep -q "End Fatal Exception" $logfile || die " - Cannot find the following string in the exception message: End Fatal Exception " $? if [ $1 -eq 1 ] then - grep "Processing Event run: 3 lumi: 1 event: 5" $logfile || die " - Cannot find the following string in the exception message: Processing Event run: 3 lumi: 1 event: 5 " $? - grep "Running path 'path1'" $logfile || die " - Cannot find the following string in the exception message: Running path 'path1' " $? - grep "ExceptionThrowingProducer::produce, module configured to throw on: run: 3 lumi: 1 event: 5" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::produce, module configured to throw on: run: 3 lumi: 1 event: 5 " $? + grep -q "Processing Event run: 3 lumi: 1 event: 5" $logfile || die " - Cannot find the following string in the exception message: Processing Event run: 3 lumi: 1 event: 5 " $? + grep -q "Running path 'path1'" $logfile || die " - Cannot find the following string in the exception message: Running path 'path1' " $? + grep -q "ExceptionThrowingProducer::produce, module configured to throw on: run: 3 lumi: 1 event: 5" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::produce, module configured to throw on: run: 3 lumi: 1 event: 5 " $? fi if [ $1 -eq 2 ] then - grep "Processing global begin Run run: 4" $logfile || die " - Cannot find the following string in the exception message: Processing global begin Run run: 4 " $? - grep "ExceptionThrowingProducer::globalBeginRun, module configured to throw on: run: 4 lumi: 0 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::globalBeginRun, module configured to throw on: run: 4 lumi: 0 event: 0 " $? + grep -q "Processing global begin Run run: 4" $logfile || die " - Cannot find the following string in the exception message: Processing global begin Run run: 4 " $? + grep -q "ExceptionThrowingProducer::globalBeginRun, module configured to throw on: run: 4 lumi: 0 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::globalBeginRun, module configured to throw on: run: 4 lumi: 0 event: 0 " $? fi if [ $1 -eq 3 ] then - grep "Processing global begin LuminosityBlock run: 4 luminosityBlock: 1" $logfile || die " - Cannot find the following string in the exception message: Processing global begin LuminosityBlock run: 4 luminosityBlock: 1 " $? - grep "ExceptionThrowingProducer::globalBeginLuminosityBlock, module configured to throw on: run: 4 lumi: 1 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::globalBeginLuminosityBlock, module configured to throw on: run: 4 lumi: 1 event: 0 " $? + grep -q "Processing global begin LuminosityBlock run: 4 luminosityBlock: 1" $logfile || die " - Cannot find the following string in the exception message: Processing global begin LuminosityBlock run: 4 luminosityBlock: 1 " $? + grep -q "ExceptionThrowingProducer::globalBeginLuminosityBlock, module configured to throw on: run: 4 lumi: 1 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::globalBeginLuminosityBlock, module configured to throw on: run: 4 lumi: 1 event: 0 " $? fi if [ $1 -eq 4 ] then - grep "Processing global end Run run: 3" $logfile || die " - Cannot find the following string in the exception message: Processing global end Run run: 3 " $? - grep "ExceptionThrowingProducer::globalEndRun, module configured to throw on: run: 3 lumi: 0 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::globalEndRun, module configured to throw on: run: 3 lumi: 0 event: 0 " $? + grep -q "Processing global end Run run: 3" $logfile || die " - Cannot find the following string in the exception message: Processing global end Run run: 3 " $? + grep -q "ExceptionThrowingProducer::globalEndRun, module configured to throw on: run: 3 lumi: 0 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::globalEndRun, module configured to throw on: run: 3 lumi: 0 event: 0 " $? fi if [ $1 -eq 5 ] then - grep "Processing global end LuminosityBlock run: 3 luminosityBlock: 1" $logfile || die " - Cannot find the following string in the exception message: Processing global end LuminosityBlock run: 3 luminosityBlock: 1 " $? - grep "ExceptionThrowingProducer::globalEndLuminosityBlock, module configured to throw on: run: 3 lumi: 1 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::globalEndLuminosityBlock, module configured to throw on: run: 3 lumi: 1 event: 0 " $? + grep -q "Processing global end LuminosityBlock run: 3 luminosityBlock: 1" $logfile || die " - Cannot find the following string in the exception message: Processing global end LuminosityBlock run: 3 luminosityBlock: 1 " $? + grep -q "ExceptionThrowingProducer::globalEndLuminosityBlock, module configured to throw on: run: 3 lumi: 1 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::globalEndLuminosityBlock, module configured to throw on: run: 3 lumi: 1 event: 0 " $? fi if [ $1 -eq 6 ] then - grep "Processing stream begin Run run: 4" $logfile || die " - Cannot find the following string in the exception message: Processing stream begin Run run: 4 " $? - grep "ExceptionThrowingProducer::streamBeginRun, module configured to throw on: run: 4 lumi: 0 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::streamBeginRun, module configured to throw on: run: 4 lumi: 0 event: 0 " $? + grep -q "Processing stream begin Run run: 4" $logfile || die " - Cannot find the following string in the exception message: Processing stream begin Run run: 4 " $? + grep -q "ExceptionThrowingProducer::streamBeginRun, module configured to throw on: run: 4 lumi: 0 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::streamBeginRun, module configured to throw on: run: 4 lumi: 0 event: 0 " $? fi if [ $1 -eq 7 ] then - grep "Processing stream begin LuminosityBlock run: 4 luminosityBlock: 1" $logfile || die " - Cannot find the following string in the exception message: Processing stream begin LuminosityBlock run: 4 luminosityBlock: 1 " $? - grep "ExceptionThrowingProducer::streamBeginLuminosityBlock, module configured to throw on: run: 4 lumi: 1 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::streamBeginLuminosityBlock, module configured to throw on: run: 4 lumi: 1 event: 0 " $? + grep -q "Processing stream begin LuminosityBlock run: 4 luminosityBlock: 1" $logfile || die " - Cannot find the following string in the exception message: Processing stream begin LuminosityBlock run: 4 luminosityBlock: 1 " $? + grep -q "ExceptionThrowingProducer::streamBeginLuminosityBlock, module configured to throw on: run: 4 lumi: 1 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::streamBeginLuminosityBlock, module configured to throw on: run: 4 lumi: 1 event: 0 " $? fi if [ $1 -eq 8 ] then - grep "Processing stream end Run run: 3" $logfile || die " - Cannot find the following string in the exception message: Processing stream end Run run: 3 " $? - grep "ExceptionThrowingProducer::streamEndRun, module configured to throw on: run: 3 lumi: 0 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::streamEndRun, module configured to throw on: run: 3 lumi: 0 event: 0 " $? + grep -q "Processing stream end Run run: 3" $logfile || die " - Cannot find the following string in the exception message: Processing stream end Run run: 3 " $? + grep -q "ExceptionThrowingProducer::streamEndRun, module configured to throw on: run: 3 lumi: 0 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::streamEndRun, module configured to throw on: run: 3 lumi: 0 event: 0 " $? fi if [ $1 -eq 9 ] then - grep "Processing stream end LuminosityBlock run: 3 luminosityBlock: 1" $logfile || die " - Cannot find the following string in the exception message: Processing stream end LuminosityBlock run: 3 luminosityBlock: 1 " $? - grep "ExceptionThrowingProducer::streamEndLuminosityBlock, module configured to throw on: run: 3 lumi: 1 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::streamEndLuminosityBlock, module configured to throw on: run: 3 lumi: 1 event: 0 " $? + grep -q "Processing stream end LuminosityBlock run: 3 luminosityBlock: 1" $logfile || die " - Cannot find the following string in the exception message: Processing stream end LuminosityBlock run: 3 luminosityBlock: 1 " $? + grep -q "ExceptionThrowingProducer::streamEndLuminosityBlock, module configured to throw on: run: 3 lumi: 1 event: 0" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::streamEndLuminosityBlock, module configured to throw on: run: 3 lumi: 1 event: 0 " $? +fi + +if [ $1 -eq 10 ] +then + grep -q "Processing begin Job" $logfile || die " - Cannot find the following string in the exception message: Processing begin Job " $? + grep -q "ExceptionThrowingProducer::beginJob, module configured to throw during beginJob" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::beginJob, module configured to throw during beginJob " $? +fi + +if [ $1 -eq 11 ] +then + grep -q "Processing begin Stream stream: 2" $logfile || die " - Cannot find the following string in the exception message: Processing begin Stream stream: 2 " $? + grep -q "ExceptionThrowingProducer::beginStream, module configured to throw during beginStream for stream: 2" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::beginStream, module configured to throw during beginStream for stream: 2 " $? +fi + +if [ $1 -eq 12 ] +then + grep -q "Processing begin ProcessBlock" $logfile || die " - Cannot find the following string in the exception message: Processing begin ProcessBlock " $? + grep -q "ExceptionThrowingProducer::beginProcessBlock, module configured to throw during beginProcessBlock" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::beginProcessBlock, module configured to throw during beginProcessBlock " $? +fi + +if [ $1 -eq 13 ] +then + grep -q "Processing end ProcessBlock" $logfile || die " - Cannot find the following string in the exception message: Processing end ProcessBlock " $? + grep -q "ExceptionThrowingProducer::endProcessBlock, module configured to throw during endProcessBlock" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::endProcessBlock, module configured to throw during endProcessBlock " $? +fi + +if [ $1 -eq 14 ] +then + grep -q "Processing end Stream stream: 2" $logfile || die " - Cannot find the following string in the exception message: Processing end Stream stream: 2 " $? + grep -q "ExceptionThrowingProducer::endStream, module configured to throw during endStream for stream: 2" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::endStream, module configured to throw during endStream for stream: 2 " $? +fi + +if [ $1 -eq 15 ] +then + grep -q "Processing endJob" $logfile || die " - Cannot find the following string in the exception message: Processing endJob " $? + grep -q "ExceptionThrowingProducer::endJob, module configured to throw during endJob" $logfile || die " - Cannot find the following string in the exception message: ExceptionThrowingProducer::endJob, module configured to throw during endJob " $? fi exit 0 diff --git a/FWCore/Integration/test/testFrameworkExceptionHandling_cfg.py b/FWCore/Integration/test/testFrameworkExceptionHandling_cfg.py index 01d854ccb36a6..ec8fe43ac799e 100644 --- a/FWCore/Integration/test/testFrameworkExceptionHandling_cfg.py +++ b/FWCore/Integration/test/testFrameworkExceptionHandling_cfg.py @@ -3,7 +3,7 @@ # # cmsRun FWCore/Integration/test/testFrameworkExceptionHandling_cfg.py testNumber=1 # -# with the value assigned to testNumber having a value from 1 to 9. +# with the value assigned to testNumber having a value from 1 to 16. # That value specifies which transition to throw an exception in. # If the value is not specified, then no exception is thrown. @@ -20,6 +20,9 @@ process = cms.Process("TEST") +process.load("FWCore.MessageService.MessageLogger_cfi") +process.MessageLogger.cerr.FwkReport.reportEvery = 100 + from FWCore.ParameterSet.VarParsing import VarParsing process.TestServiceOne = cms.Service("TestServiceOne", @@ -62,7 +65,9 @@ process.busy1 = cms.EDProducer("BusyWaitIntProducer",ivalue = cms.int32(1), iterations = cms.uint32(10*1000*1000)) -process.throwException = cms.EDProducer("ExceptionThrowingProducer") +process.throwException = cms.EDProducer("ExceptionThrowingProducer", + verbose = cms.untracked.bool(False) +) process.doNotThrowException = cms.EDProducer("ExceptionThrowingProducer") print('testNumber', options.testNumber) @@ -111,14 +116,51 @@ process.doNotThrowException.expectedOffsetNoStreamEndLumi = cms.untracked.uint32(1) elif options.testNumber == 8: process.throwException.eventIDThrowOnStreamEndRun = cms.untracked.EventID(3, 0, 0) - process.throwException.expectedStreamBeginRun = cms.untracked.uint32(3) - process.doNotThrowException.expectedStreamBeginRun = cms.untracked.uint32(3) elif options.testNumber == 9: process.throwException.eventIDThrowOnStreamEndLumi = cms.untracked.EventID(3, 1, 0) - process.throwException.expectedStreamBeginLumi = cms.untracked.uint32(3) - process.doNotThrowException.expectedStreamBeginLumi = cms.untracked.uint32(3) +elif options.testNumber == 10: + process.throwException.throwInBeginJob = cms.untracked.bool(True) + process.throwException.expectedNEndJob = cms.untracked.uint32(0) + process.throwException.expectedOffsetNoEndJob = cms.untracked.uint32(1) + process.doNotThrowException.expectedNBeginStream = cms.untracked.uint32(0) + process.doNotThrowException.expectedNBeginProcessBlock = cms.untracked.uint32(0) + process.doNotThrowException.expectedNEndProcessBlock = cms.untracked.uint32(0) + process.doNotThrowException.expectedNEndStream = cms.untracked.uint32(0) + process.doNotThrowException.expectNoRunsProcessed = cms.untracked.bool(True) + process.doNotThrowException.expectedOffsetNoEndJob = cms.untracked.uint32(1) +elif options.testNumber == 11: + process.throwException.throwInBeginStream = cms.untracked.bool(True) + process.throwException.expectedNBeginStream = cms.untracked.uint32(4) + process.throwException.expectedNBeginProcessBlock = cms.untracked.uint32(0) + process.throwException.expectedNEndProcessBlock = cms.untracked.uint32(0) + process.throwException.expectedNEndStream = cms.untracked.uint32(3) + process.throwException.expectNoRunsProcessed = cms.untracked.bool(True) + process.throwException.expectedOffsetNoEndStream = cms.untracked.uint32(1) + process.doNotThrowException.expectedNBeginStream = cms.untracked.uint32(4) + process.doNotThrowException.expectedNBeginProcessBlock = cms.untracked.uint32(0) + process.doNotThrowException.expectedNEndProcessBlock = cms.untracked.uint32(0) + process.doNotThrowException.expectedNEndStream = cms.untracked.uint32(4) + process.doNotThrowException.expectNoRunsProcessed = cms.untracked.bool(True) + process.doNotThrowException.expectedOffsetNoEndStream = cms.untracked.uint32(1) +elif options.testNumber == 12: + process.throwException.throwInBeginProcessBlock = cms.untracked.bool(True) + process.throwException.expectedNEndProcessBlock = cms.untracked.uint32(0) + process.throwException.expectNoRunsProcessed = cms.untracked.bool(True) + process.throwException.expectedOffsetNoEndProcessBlock = cms.untracked.uint32(1) + process.doNotThrowException.expectNoRunsProcessed = cms.untracked.bool(True) + process.doNotThrowException.expectedOffsetNoEndProcessBlock = cms.untracked.uint32(1) +elif options.testNumber == 13: + process.throwException.throwInEndProcessBlock = cms.untracked.bool(True) +elif options.testNumber == 14: + process.throwException.throwInEndStream = cms.untracked.bool(True) +elif options.testNumber == 15: + process.throwException.throwInEndJob = cms.untracked.bool(True) +# This one does not throw. It is not used in the unit test but was useful +# when manually debugging the test itself and manually debugging other things. +elif options.testNumber == 16: + process.throwException.throwInEndJob = cms.untracked.bool(False) else: - print("The parameter named testNumber is out of range. An exception will not be thrown. Supported values range from 1 to 9.") + print("The parameter named testNumber is out of range. An exception will not be thrown. Supported values range from 1 to 16.") print("The proper syntax for setting the parameter is:") print("") print (" cmsRun FWCore/Integration/test/testFrameworkExceptionHandling_cfg.py testNumber=1") diff --git a/FWCore/Integration/test/unit_test_outputs/testGetBy1.log b/FWCore/Integration/test/unit_test_outputs/testGetBy1.log index 1c8cb0b469217..1e3716de3d9a5 100644 --- a/FWCore/Integration/test/unit_test_outputs/testGetBy1.log +++ b/FWCore/Integration/test/unit_test_outputs/testGetBy1.log @@ -64,8 +64,9 @@ Module type=TestFindProduct, Module label=a1, Parameter Set ID=a7caa43fcf5ef35de ++++ finished: begin job for module with label 'TriggerResults' id = 1 ++++ starting: begin job for module with label 'p' id = 2 ++++ finished: begin job for module with label 'p' id = 2 -++ starting: begin job ++ finished: begin job +++ starting: begin job +++ starting: begin stream 0 ++++ starting: begin stream for module: stream = 0 label = 'intProducer' id = 3 ++++ finished: begin stream for module: stream = 0 label = 'intProducer' id = 3 ++++ starting: begin stream for module: stream = 0 label = 'a1' id = 4 @@ -132,6 +133,9 @@ ModuleCallingContext state = Running ++++ finished: begin stream for module: stream = 0 label = 'intProducerU' id = 12 ++++ starting: begin stream for module: stream = 0 label = 'intVectorProducer' id = 13 ++++ finished: begin stream for module: stream = 0 label = 'intVectorProducer' id = 13 +++ finished: begin stream 0 +++ starting: begin stream 0 +++ finished: begin stream 0 ++++ starting: begin process block GlobalContext: transition = BeginProcessBlock run: 0 luminosityBlock: 0 @@ -1661,6 +1665,7 @@ GlobalContext: transition = WriteProcessBlock ProcessContext: COPY 6f4335e86de793448be83fe14f12dcb7 parent ProcessContext: PROD1 cf8fb4a5e3c9a108eac33826b2a17969 +++ starting: end stream 0 ++++ starting: end stream for module: stream = 0 label = 'intProducer' id = 3 ++++ finished: end stream for module: stream = 0 label = 'intProducer' id = 3 ++++ starting: end stream for module: stream = 0 label = 'a1' id = 4 @@ -1727,6 +1732,10 @@ ModuleCallingContext state = Running ++++ finished: end stream for module: stream = 0 label = 'intProducerU' id = 12 ++++ starting: end stream for module: stream = 0 label = 'intVectorProducer' id = 13 ++++ finished: end stream for module: stream = 0 label = 'intVectorProducer' id = 13 +++ finished: end stream 0 +++ starting: end stream 0 +++ finished: end stream 0 +++ starting: end job ++++ starting: end job for module with label 'intProducerA' id = 8 Module type=IntProducer, Module label=intProducerA, Parameter Set ID=56ea7c8bbb02df4e1c3b945954838318 ++++ finished: end job for module with label 'intProducerA' id = 8 diff --git a/FWCore/Integration/test/unit_test_outputs/testGetBy2.log b/FWCore/Integration/test/unit_test_outputs/testGetBy2.log index 01f56b3888bf7..5174e63568eda 100644 --- a/FWCore/Integration/test/unit_test_outputs/testGetBy2.log +++ b/FWCore/Integration/test/unit_test_outputs/testGetBy2.log @@ -35,6 +35,7 @@ Module type=IntProducer, Module label=intProducer, Parameter Set ID=b4b90439a301 ++++ starting: begin job for module with label 'p' id = 2 ++++ finished: begin job for module with label 'p' id = 2 ++ finished: begin job +++ starting: begin stream 0 ++++ starting: begin stream for module: stream = 0 label = 'intProducer' id = 3 StreamContext: StreamID = 0 transition = BeginStream run: 0 lumi: 0 event: 0 @@ -65,6 +66,7 @@ ModuleCallingContext state = Running ++++ finished: begin stream for module: stream = 0 label = 'intProducerU' id = 5 ++++ starting: begin stream for module: stream = 0 label = 'intVectorProducer' id = 6 ++++ finished: begin stream for module: stream = 0 label = 'intVectorProducer' id = 6 +++ finished: begin stream 0 ++++ starting: begin process block GlobalContext: transition = BeginProcessBlock run: 0 luminosityBlock: 0 @@ -812,6 +814,7 @@ GlobalContext: transition = WriteProcessBlock runIndex = 4294967295 luminosityBlockIndex = 4294967295 unixTime = 0 microsecondOffset = 0 ProcessContext: PROD2 9a42d7e4995aeb2a3c9d04a3ef0f3879 +++ starting: end stream 0 ++++ starting: end stream for module: stream = 0 label = 'intProducer' id = 3 StreamContext: StreamID = 0 transition = EndStream run: 0 lumi: 0 event: 0 @@ -842,6 +845,8 @@ ModuleCallingContext state = Running ++++ finished: end stream for module: stream = 0 label = 'intProducerU' id = 5 ++++ starting: end stream for module: stream = 0 label = 'intVectorProducer' id = 6 ++++ finished: end stream for module: stream = 0 label = 'intVectorProducer' id = 6 +++ finished: end stream 0 +++ starting: end job ++++ starting: end job for module with label 'intProducerU' id = 5 ++++ finished: end job for module with label 'intProducerU' id = 5 ++++ starting: end job for module with label 'intVectorProducer' id = 6 diff --git a/FWCore/Integration/test/unit_test_outputs/testSubProcess.grep2.txt b/FWCore/Integration/test/unit_test_outputs/testSubProcess.grep2.txt index cd422f6637d0b..39627f4eab9de 100644 --- a/FWCore/Integration/test/unit_test_outputs/testSubProcess.grep2.txt +++ b/FWCore/Integration/test/unit_test_outputs/testSubProcess.grep2.txt @@ -72,6 +72,7 @@ ++++ finished: constructing module with label 'out' id = 35 ++ preallocate: 1 concurrent runs, 1 concurrent luminosity sections, 1 streams ++ starting: begin job +++ finished: begin job ++ starting: begin job ++ starting: begin job ++++ starting: begin job for module with label 'thingWithMergeProducer' id = 5 @@ -147,7 +148,11 @@ ++++ finished: begin job for module with label 'path3' id = 27 ++++ starting: begin job for module with label 'path4' id = 28 ++++ finished: begin job for module with label 'path4' id = 28 -++ finished: begin job +++ starting: begin stream 0 +++ finished: begin stream 0 +++ starting: begin stream 0 +++ finished: begin stream 0 +++ starting: begin stream 0 ++++ starting: begin stream for module: stream = 0 label = 'thingWithMergeProducer' id = 5 ++++ finished: begin stream for module: stream = 0 label = 'thingWithMergeProducer' id = 5 ++++ starting: begin stream for module: stream = 0 label = 'get' id = 6 @@ -162,6 +167,10 @@ ++++ finished: begin stream for module: stream = 0 label = 'getInt' id = 10 ++++ starting: begin stream for module: stream = 0 label = 'noPut' id = 11 ++++ finished: begin stream for module: stream = 0 label = 'noPut' id = 11 +++ finished: begin stream 0 +++ starting: begin stream 0 +++ finished: begin stream 0 +++ starting: begin stream 0 ++++ starting: begin stream for module: stream = 0 label = 'thingWithMergeProducer' id = 17 ++++ finished: begin stream for module: stream = 0 label = 'thingWithMergeProducer' id = 17 ++++ starting: begin stream for module: stream = 0 label = 'test' id = 18 @@ -176,6 +185,8 @@ ++++ finished: begin stream for module: stream = 0 label = 'dependsOnNoPut' id = 22 ++++ starting: begin stream for module: stream = 0 label = 'out' id = 23 ++++ finished: begin stream for module: stream = 0 label = 'out' id = 23 +++ finished: begin stream 0 +++ starting: begin stream 0 ++++ starting: begin stream for module: stream = 0 label = 'thingWithMergeProducer' id = 29 ++++ finished: begin stream for module: stream = 0 label = 'thingWithMergeProducer' id = 29 ++++ starting: begin stream for module: stream = 0 label = 'test' id = 30 @@ -190,6 +201,7 @@ ++++ finished: begin stream for module: stream = 0 label = 'dependsOnNoPut' id = 34 ++++ starting: begin stream for module: stream = 0 label = 'out' id = 35 ++++ finished: begin stream for module: stream = 0 label = 'out' id = 35 +++ finished: begin stream 0 ++++ starting: begin process block ++++ finished: begin process block ++++ starting: begin process block @@ -7339,6 +7351,11 @@ ++++++ starting: write process block for module: label = 'out' id = 23 ++++++ finished: write process block for module: label = 'out' id = 23 ++++ finished: write process block +++ starting: end stream 0 +++ finished: end stream 0 +++ starting: end stream 0 +++ finished: end stream 0 +++ starting: end stream 0 ++++ starting: end stream for module: stream = 0 label = 'thingWithMergeProducer' id = 5 ++++ finished: end stream for module: stream = 0 label = 'thingWithMergeProducer' id = 5 ++++ starting: end stream for module: stream = 0 label = 'get' id = 6 @@ -7353,6 +7370,10 @@ ++++ finished: end stream for module: stream = 0 label = 'getInt' id = 10 ++++ starting: end stream for module: stream = 0 label = 'noPut' id = 11 ++++ finished: end stream for module: stream = 0 label = 'noPut' id = 11 +++ finished: end stream 0 +++ starting: end stream 0 +++ finished: end stream 0 +++ starting: end stream 0 ++++ starting: end stream for module: stream = 0 label = 'thingWithMergeProducer' id = 17 ++++ finished: end stream for module: stream = 0 label = 'thingWithMergeProducer' id = 17 ++++ starting: end stream for module: stream = 0 label = 'test' id = 18 @@ -7367,6 +7388,8 @@ ++++ finished: end stream for module: stream = 0 label = 'dependsOnNoPut' id = 22 ++++ starting: end stream for module: stream = 0 label = 'out' id = 23 ++++ finished: end stream for module: stream = 0 label = 'out' id = 23 +++ finished: end stream 0 +++ starting: end stream 0 ++++ starting: end stream for module: stream = 0 label = 'thingWithMergeProducer' id = 29 ++++ finished: end stream for module: stream = 0 label = 'thingWithMergeProducer' id = 29 ++++ starting: end stream for module: stream = 0 label = 'test' id = 30 @@ -7381,6 +7404,9 @@ ++++ finished: end stream for module: stream = 0 label = 'dependsOnNoPut' id = 34 ++++ starting: end stream for module: stream = 0 label = 'out' id = 35 ++++ finished: end stream for module: stream = 0 label = 'out' id = 35 +++ finished: end stream 0 +++ starting: end job +++ finished: end job ++++ starting: end job for module with label 'thingWithMergeProducer' id = 5 ++++ finished: end job for module with label 'thingWithMergeProducer' id = 5 ++++ starting: end job for module with label 'get' id = 6 @@ -7451,4 +7477,3 @@ ++++ finished: end job for module with label 'path3' id = 27 ++++ starting: end job for module with label 'path4' id = 28 ++++ finished: end job for module with label 'path4' id = 28 -++ finished: end job diff --git a/FWCore/ServiceRegistry/interface/ActivityRegistry.h b/FWCore/ServiceRegistry/interface/ActivityRegistry.h index b8d2a78e1f015..62cbd79d7eecf 100644 --- a/FWCore/ServiceRegistry/interface/ActivityRegistry.h +++ b/FWCore/ServiceRegistry/interface/ActivityRegistry.h @@ -1,11 +1,11 @@ +// -*- C++ -*- #ifndef FWCore_ServiceRegistry_ActivityRegistry_h #define FWCore_ServiceRegistry_ActivityRegistry_h -// -*- C++ -*- // // Package: ServiceRegistry // Class : ActivityRegistry // -/**\class ActivityRegistry ActivityRegistry.h FWCore/ServiceRegistry/interface/ActivityRegistry.h +/**\class edm::ActivityRegistry Description: Registry holding the signals that Services can subscribe to @@ -28,11 +28,27 @@ to this file that go beyond the obvious cut and paste type of edits. 1. The number at the end of the AR_WATCH_USING_METHOD_X macro definition is the number of function arguments. It will not compile if you use the wrong number there. - 2. Use connect or connect_front depending on whether the callback function + 2. Inside the watch function definition, choose either connect or + connect_front depending on whether the callback function should be called for different services in the order the Services were - constructed or in reverse order. Begin signals are usually forward and - End signals in reverse, but if the service does not depend on other services - and vice versa this does not matter. + constructed or in reverse order (actually the code base allows establishing + an order different from construction order, but in practice it is + usually the construction order). This only matters for services that + both depend on one another and where this dependence relies on the order + the services execute a particular transition. If a service does not + depend on another service, this choice does not matter (most services + fall in this category). Most transition signals are implemented with + the Pre signals forward and the Post signals in reverse order. + The transition level signals for BeginJob and EndJob are implemented with + the Begin signals forward and End signals in reverse order. As far as I + know, no one has ever carefully surveyed existing services to determine + which services depend on this ordering. My suspicion is that for most services + and most transitions it does not matter which ordering has been implemented. + If you are implementing a new transition, then the choice could only matter + for the services that start watching that transition. Unless there is some + reason to do otherwise, the recommended choice is following the pattern of + Pre transitions forward and Post transitions in reverse. If you make another + choice, please document your reasoning with comments in the code. 3. The signal needs to be added to either connectGlobals or connectLocals in the ActivityRegistry.cc file, depending on whether a signal is seen by children or parents when there are SubProcesses. For example, source @@ -181,6 +197,26 @@ namespace edm { void watchPostEndJob(PostEndJob::slot_type const& iSlot) { postEndJobSignal_.connect_front(iSlot); } AR_WATCH_USING_METHOD_0(watchPostEndJob) + typedef signalslot::Signal PreBeginStream; + PreBeginStream preBeginStreamSignal_; + void watchPreBeginStream(PreBeginStream::slot_type const& iSlot) { preBeginStreamSignal_.connect(iSlot); } + AR_WATCH_USING_METHOD_1(watchPreBeginStream) + + typedef signalslot::Signal PostBeginStream; + PostBeginStream postBeginStreamSignal_; + void watchPostBeginStream(PostBeginStream::slot_type const& iSlot) { postBeginStreamSignal_.connect_front(iSlot); } + AR_WATCH_USING_METHOD_1(watchPostBeginStream) + + typedef signalslot::Signal PreEndStream; + PreEndStream preEndStreamSignal_; + void watchPreEndStream(PreEndStream::slot_type const& iSlot) { preEndStreamSignal_.connect(iSlot); } + AR_WATCH_USING_METHOD_1(watchPreEndStream) + + typedef signalslot::Signal PostEndStream; + PostEndStream postEndStreamSignal_; + void watchPostEndStream(PostEndStream::slot_type const& iSlot) { postEndStreamSignal_.connect_front(iSlot); } + AR_WATCH_USING_METHOD_1(watchPostEndStream) + typedef signalslot::Signal JobFailure; /// signal is emitted if event processing or end-of-job /// processing fails with an uncaught exception. @@ -649,9 +685,9 @@ namespace edm { Unlike the case in the Run, Lumi, and Event loops, the Module descriptor (often passed by pointer or reference as an argument named desc) in the construction phase is NOT - at some permanent fixed address during the construction phase. - Therefore, any optimization of caching the module name keying - off of address of the descriptor will NOT be valid during + at some permanent fixed address during the construction phase. + Therefore, any optimization of caching the module name keying + off of address of the descriptor will NOT be valid during such functions. mf / cj 9/11/09 */ diff --git a/FWCore/ServiceRegistry/interface/GlobalContext.h b/FWCore/ServiceRegistry/interface/GlobalContext.h index 4ec0312a6eddc..18e60e0bfa323 100644 --- a/FWCore/ServiceRegistry/interface/GlobalContext.h +++ b/FWCore/ServiceRegistry/interface/GlobalContext.h @@ -23,6 +23,10 @@ information about the current state of global processing. #include #include +namespace cms { + class Exception; +} + namespace edm { class ProcessContext; @@ -76,6 +80,7 @@ namespace edm { void exceptionContext(std::ostream&, GlobalContext const&); std::ostream& operator<<(std::ostream&, GlobalContext const&); + void exceptionContext(cms::Exception&, GlobalContext const&, char const* context); std::string_view transitionName(GlobalContext::Transition); } // namespace edm diff --git a/FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h b/FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h index 42bb6fdcddec6..7894bb7e6cb1c 100644 --- a/FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h +++ b/FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h @@ -6,6 +6,7 @@ namespace edm { class GlobalContext; class ModuleCallingContext; class ParentContext; + class PathsAndConsumesOfModulesBase; class ProcessContext; class ServiceToken; class StreamContext; diff --git a/FWCore/ServiceRegistry/interface/StreamContext.h b/FWCore/ServiceRegistry/interface/StreamContext.h index e45b991fd6c86..c6cd170670c59 100644 --- a/FWCore/ServiceRegistry/interface/StreamContext.h +++ b/FWCore/ServiceRegistry/interface/StreamContext.h @@ -6,10 +6,10 @@ Description: Holds pointer to ProcessContext, StreamID, transition, EventID and timestamp. This is intended primarily to be passed to Services - as an argument to their callback functions. - - Usage: - + as an argument to their callback functions. It is also + used internally by the Framework to hold information + that can be added to exception messages about the + context where an exception was thrown. */ // diff --git a/FWCore/ServiceRegistry/src/ActivityRegistry.cc b/FWCore/ServiceRegistry/src/ActivityRegistry.cc index 0da045a80e699..38556bc64d6ad 100644 --- a/FWCore/ServiceRegistry/src/ActivityRegistry.cc +++ b/FWCore/ServiceRegistry/src/ActivityRegistry.cc @@ -18,41 +18,6 @@ #include "FWCore/Utilities/interface/Algorithms.h" #include "FWCore/Utilities/interface/Exception.h" -// -// constants, enums and typedefs -// - -// -// static data member definitions -// - -// -// constructors and destructor -// -//ActivityRegistry::ActivityRegistry() { -//} - -// ActivityRegistry::ActivityRegistry(ActivityRegistry const& rhs) { -// // do actual copying here; -// } - -//ActivityRegistry::~ActivityRegistry() { -//} - -// -// assignment operators -// -// ActivityRegistry const& ActivityRegistry::operator=(ActivityRegistry const& rhs) { -// //An exception safe implementation is -// ActivityRegistry temp(rhs); -// swap(rhs); -// -// return *this; -// } - -// -// member functions -// namespace edm { namespace { template @@ -135,6 +100,12 @@ namespace edm { void ActivityRegistry::connectLocals(ActivityRegistry& iOther) { preBeginJobSignal_.connect(std::cref(iOther.preBeginJobSignal_)); + preBeginStreamSignal_.connect(std::cref(iOther.preBeginStreamSignal_)); + postBeginStreamSignal_.connect(std::cref(iOther.postBeginStreamSignal_)); + + preEndStreamSignal_.connect(std::cref(iOther.preEndStreamSignal_)); + postEndStreamSignal_.connect(std::cref(iOther.postEndStreamSignal_)); + preModuleBeginStreamSignal_.connect(std::cref(iOther.preModuleBeginStreamSignal_)); postModuleBeginStreamSignal_.connect(std::cref(iOther.postModuleBeginStreamSignal_)); @@ -192,36 +163,6 @@ namespace edm { prePathEventSignal_.connect(std::cref(iOther.prePathEventSignal_)); postPathEventSignal_.connect(std::cref(iOther.postPathEventSignal_)); - //preProcessEventSignal_.connect(std::cref(iOther.preProcessEventSignal_)); - //postProcessEventSignal_.connect(std::cref(iOther.postProcessEventSignal_)); - - //preBeginRunSignal_.connect(std::cref(iOther.preBeginRunSignal_)); - //postBeginRunSignal_.connect(std::cref(iOther.postBeginRunSignal_)); - - //preEndRunSignal_.connect(std::cref(iOther.preEndRunSignal_)); - //postEndRunSignal_.connect(std::cref(iOther.postEndRunSignal_)); - - //preBeginLumiSignal_.connect(std::cref(iOther.preBeginLumiSignal_)); - //postBeginLumiSignal_.connect(std::cref(iOther.postBeginLumiSignal_)); - - //preEndLumiSignal_.connect(std::cref(iOther.preEndLumiSignal_)); - //postEndLumiSignal_.connect(std::cref(iOther.postEndLumiSignal_)); - - //preProcessPathSignal_.connect(std::cref(iOther.preProcessPathSignal_)); - //postProcessPathSignal_.connect(std::cref(iOther.postProcessPathSignal_)); - - //prePathBeginRunSignal_.connect(std::cref(iOther.prePathBeginRunSignal_)); - //postPathBeginRunSignal_.connect(std::cref(iOther.postPathBeginRunSignal_)); - - //prePathEndRunSignal_.connect(std::cref(iOther.prePathEndRunSignal_)); - //postPathEndRunSignal_.connect(std::cref(iOther.postPathEndRunSignal_)); - - //prePathBeginLumiSignal_.connect(std::cref(iOther.prePathBeginLumiSignal_)); - //postPathBeginLumiSignal_.connect(std::cref(iOther.postPathBeginLumiSignal_)); - - //prePathEndLumiSignal_.connect(std::cref(iOther.prePathEndLumiSignal_)); - //postPathEndLumiSignal_.connect(std::cref(iOther.postPathEndLumiSignal_)); - preModuleConstructionSignal_.connect(std::cref(iOther.preModuleConstructionSignal_)); postModuleConstructionSignal_.connect(std::cref(iOther.postModuleConstructionSignal_)); @@ -316,21 +257,6 @@ namespace edm { postESModuleAcquireSignal_.connect(std::cref(iOther.postESModuleAcquireSignal_)); postESModuleRegistrationSignal_.connect(std::cref(iOther.postESModuleRegistrationSignal_)); - - //preModuleSignal_.connect(std::cref(iOther.preModuleSignal_)); - //postModuleSignal_.connect(std::cref(iOther.postModuleSignal_)); - - //preModuleBeginRunSignal_.connect(std::cref(iOther.preModuleBeginRunSignal_)); - //postModuleBeginRunSignal_.connect(std::cref(iOther.postModuleBeginRunSignal_)); - - //preModuleEndRunSignal_.connect(std::cref(iOther.preModuleEndRunSignal_)); - //postModuleEndRunSignal_.connect(std::cref(iOther.postModuleEndRunSignal_)); - - //preModuleBeginLumiSignal_.connect(std::cref(iOther.preModuleBeginLumiSignal_)); - //postModuleBeginLumiSignal_.connect(std::cref(iOther.postModuleBeginLumiSignal_)); - - //preModuleEndLumiSignal_.connect(std::cref(iOther.preModuleEndLumiSignal_)); - //postModuleEndLumiSignal_.connect(std::cref(iOther.postModuleEndLumiSignal_)); } void ActivityRegistry::connect(ActivityRegistry& iOther) { @@ -376,6 +302,12 @@ namespace edm { copySlotsToFrom(preCloseFileSignal_, iOther.preCloseFileSignal_); copySlotsToFromReverse(postCloseFileSignal_, iOther.postCloseFileSignal_); + copySlotsToFrom(preBeginStreamSignal_, iOther.preBeginStreamSignal_); + copySlotsToFromReverse(postBeginStreamSignal_, iOther.postBeginStreamSignal_); + + copySlotsToFrom(preEndStreamSignal_, iOther.preEndStreamSignal_); + copySlotsToFromReverse(postEndStreamSignal_, iOther.postEndStreamSignal_); + copySlotsToFrom(preModuleBeginStreamSignal_, iOther.preModuleBeginStreamSignal_); copySlotsToFromReverse(postModuleBeginStreamSignal_, iOther.postModuleBeginStreamSignal_); @@ -437,37 +369,6 @@ namespace edm { copySlotsToFrom(preGlobalEarlyTerminationSignal_, iOther.preGlobalEarlyTerminationSignal_); copySlotsToFrom(preSourceEarlyTerminationSignal_, iOther.preSourceEarlyTerminationSignal_); - /* - copySlotsToFrom(preProcessEventSignal_, iOther.preProcessEventSignal_); - copySlotsToFromReverse(postProcessEventSignal_, iOther.postProcessEventSignal_); - - copySlotsToFrom(preBeginRunSignal_, iOther.preBeginRunSignal_); - copySlotsToFromReverse(postBeginRunSignal_, iOther.postBeginRunSignal_); - - copySlotsToFrom(preEndRunSignal_, iOther.preEndRunSignal_); - copySlotsToFromReverse(postEndRunSignal_, iOther.postEndRunSignal_); - - copySlotsToFrom(preBeginLumiSignal_, iOther.preBeginLumiSignal_); - copySlotsToFromReverse(postBeginLumiSignal_, iOther.postBeginLumiSignal_); - - copySlotsToFrom(preEndLumiSignal_, iOther.preEndLumiSignal_); - copySlotsToFromReverse(postEndLumiSignal_, iOther.postEndLumiSignal_); - - copySlotsToFrom(preProcessPathSignal_, iOther.preProcessPathSignal_); - copySlotsToFromReverse(postProcessPathSignal_, iOther.postProcessPathSignal_); - - copySlotsToFrom(prePathBeginRunSignal_, iOther.prePathBeginRunSignal_); - copySlotsToFromReverse(postPathBeginRunSignal_, iOther.postPathBeginRunSignal_); - - copySlotsToFrom(prePathEndRunSignal_, iOther.prePathEndRunSignal_); - copySlotsToFromReverse(postPathEndRunSignal_, iOther.postPathEndRunSignal_); - - copySlotsToFrom(prePathBeginLumiSignal_, iOther.prePathBeginLumiSignal_); - copySlotsToFromReverse(postPathBeginLumiSignal_, iOther.postPathBeginLumiSignal_); - - copySlotsToFrom(prePathEndLumiSignal_, iOther.prePathEndLumiSignal_); - copySlotsToFromReverse(postPathEndLumiSignal_, iOther.postPathEndLumiSignal_); -*/ copySlotsToFrom(preModuleConstructionSignal_, iOther.preModuleConstructionSignal_); copySlotsToFromReverse(postModuleConstructionSignal_, iOther.postModuleConstructionSignal_); @@ -562,22 +463,7 @@ namespace edm { copySlotsToFromReverse(postESModuleAcquireSignal_, iOther.postESModuleAcquireSignal_); copySlotsToFromReverse(postESModuleRegistrationSignal_, iOther.postESModuleRegistrationSignal_); - /* - copySlotsToFrom(preModuleSignal_, iOther.preModuleSignal_); - copySlotsToFromReverse(postModuleSignal_, iOther.postModuleSignal_); - - copySlotsToFrom(preModuleBeginRunSignal_, iOther.preModuleBeginRunSignal_); - copySlotsToFromReverse(postModuleBeginRunSignal_, iOther.postModuleBeginRunSignal_); - - copySlotsToFrom(preModuleEndRunSignal_, iOther.preModuleEndRunSignal_); - copySlotsToFromReverse(postModuleEndRunSignal_, iOther.postModuleEndRunSignal_); - copySlotsToFrom(preModuleBeginLumiSignal_, iOther.preModuleBeginLumiSignal_); - copySlotsToFromReverse(postModuleBeginLumiSignal_, iOther.postModuleBeginLumiSignal_); - - copySlotsToFrom(preModuleEndLumiSignal_, iOther.preModuleEndLumiSignal_); - copySlotsToFromReverse(postModuleEndLumiSignal_, iOther.postModuleEndLumiSignal_); - */ copySlotsToFrom(preSourceConstructionSignal_, iOther.preSourceConstructionSignal_); copySlotsToFromReverse(postSourceConstructionSignal_, iOther.postSourceConstructionSignal_); @@ -585,12 +471,4 @@ namespace edm { copySlotsToFrom(preESSyncIOVSignal_, iOther.preESSyncIOVSignal_); copySlotsToFromReverse(postESSyncIOVSignal_, iOther.postESSyncIOVSignal_); } - - // - // const member functions - // - - // - // static member functions - // } // namespace edm diff --git a/FWCore/ServiceRegistry/src/GlobalContext.cc b/FWCore/ServiceRegistry/src/GlobalContext.cc index 702c04f118476..f4db9e475001d 100644 --- a/FWCore/ServiceRegistry/src/GlobalContext.cc +++ b/FWCore/ServiceRegistry/src/GlobalContext.cc @@ -1,7 +1,9 @@ #include "FWCore/ServiceRegistry/interface/GlobalContext.h" #include "FWCore/ServiceRegistry/interface/ProcessContext.h" +#include "FWCore/Utilities/interface/Exception.h" #include +#include namespace edm { @@ -118,6 +120,15 @@ namespace edm { } } + void exceptionContext(cms::Exception& ex, GlobalContext const& globalContext, char const* context) { + std::ostringstream ost; + if (context && *context != '\0') { + ex.addContext(context); + } + exceptionContext(ost, globalContext); + ex.addContext(ost.str()); + } + std::string_view transitionName(GlobalContext::Transition iTrans) { switch (iTrans) { case GlobalContext::Transition::kBeginJob: diff --git a/FWCore/Services/plugins/Tracer.cc b/FWCore/Services/plugins/Tracer.cc index 9b97ca8cfa1b2..4f8756dbc2438 100644 --- a/FWCore/Services/plugins/Tracer.cc +++ b/FWCore/Services/plugins/Tracer.cc @@ -65,8 +65,14 @@ namespace edm { void preBeginJob(PathsAndConsumesOfModulesBase const&, ProcessContext const&); void postBeginJob(); + void preEndJob(); void postEndJob(); + void preBeginStream(StreamContext const&); + void postBeginStream(StreamContext const&); + void preEndStream(StreamContext const&); + void postEndStream(StreamContext const&); + void preSourceEvent(StreamID); void postSourceEvent(StreamID); @@ -269,8 +275,14 @@ Tracer::Tracer(ParameterSet const& iPS, ActivityRegistry& iRegistry) iRegistry.watchPreBeginJob(this, &Tracer::preBeginJob); iRegistry.watchPostBeginJob(this, &Tracer::postBeginJob); + iRegistry.watchPreEndJob(this, &Tracer::preEndJob); iRegistry.watchPostEndJob(this, &Tracer::postEndJob); + iRegistry.watchPreBeginStream(this, &Tracer::preBeginStream); + iRegistry.watchPostBeginStream(this, &Tracer::postBeginStream); + iRegistry.watchPreEndStream(this, &Tracer::preEndStream); + iRegistry.watchPostEndStream(this, &Tracer::postEndStream); + iRegistry.watchPreSourceEvent(this, &Tracer::preSourceEvent); iRegistry.watchPostSourceEvent(this, &Tracer::postSourceEvent); @@ -605,10 +617,30 @@ void Tracer::postBeginJob() { LogAbsolute("Tracer") << TimeStamper(printTimestamps_) << indention_ << " finished: begin job"; } +void Tracer::preEndJob() { + LogAbsolute("Tracer") << TimeStamper(printTimestamps_) << indention_ << " starting: end job"; +} + void Tracer::postEndJob() { LogAbsolute("Tracer") << TimeStamper(printTimestamps_) << indention_ << " finished: end job"; } +void Tracer::preBeginStream(StreamContext const& sc) { + LogAbsolute("Tracer") << TimeStamper(printTimestamps_) << indention_ << " starting: begin stream " << sc.streamID(); +} + +void Tracer::postBeginStream(StreamContext const& sc) { + LogAbsolute("Tracer") << TimeStamper(printTimestamps_) << indention_ << " finished: begin stream " << sc.streamID(); +} + +void Tracer::preEndStream(StreamContext const& sc) { + LogAbsolute("Tracer") << TimeStamper(printTimestamps_) << indention_ << " starting: end stream " << sc.streamID(); +} + +void Tracer::postEndStream(StreamContext const& sc) { + LogAbsolute("Tracer") << TimeStamper(printTimestamps_) << indention_ << " finished: end stream " << sc.streamID(); +} + void Tracer::preSourceEvent(StreamID sid) { LogAbsolute("Tracer") << TimeStamper(printTimestamps_) << indention_ << indention_ << " starting: source event"; } diff --git a/FWCore/TestProcessor/src/TestProcessor.cc b/FWCore/TestProcessor/src/TestProcessor.cc index 6662bea40e534..16bb6f39bc2be 100644 --- a/FWCore/TestProcessor/src/TestProcessor.cc +++ b/FWCore/TestProcessor/src/TestProcessor.cc @@ -52,6 +52,8 @@ #include "DataFormats/Provenance/interface/ParentageRegistry.h" +#include + #define xstr(s) str(s) #define str(s) #s @@ -417,10 +419,9 @@ namespace edm { actReg_->eventSetupConfigurationSignal_(esp_->recordsToResolverIndices(), processContext_); //NOTE: this may throw //checkForModuleDependencyCorrectness(pathsAndConsumesOfModules, false); - actReg_->preBeginJobSignal_(pathsAndConsumesOfModules, processContext_); - schedule_->beginJob(*preg_, esp_->recordsToResolverIndices(), *processBlockHelper_); - actReg_->postBeginJobSignal_(); + schedule_->beginJob( + *preg_, esp_->recordsToResolverIndices(), *processBlockHelper_, pathsAndConsumesOfModules, processContext_); for (unsigned int i = 0; i < preallocations_.numberOfStreams(); ++i) { schedule_->beginStream(i); @@ -686,13 +687,14 @@ namespace edm { // Collects exceptions, so we don't throw before all operations are performed. ExceptionCollector c( "Multiple exceptions were thrown while executing endJob. An exception message follows for each.\n"); + std::mutex collectorMutex; //make the services available ServiceRegistry::Operate operate(serviceToken_); //NOTE: this really should go elsewhere in the future for (unsigned int i = 0; i < preallocations_.numberOfStreams(); ++i) { - c.call([this, i]() { this->schedule_->endStream(i); }); + schedule_->endStream(i, c, collectorMutex); } auto actReg = actReg_.get(); c.call([actReg]() { actReg->preEndJobSignal_(); }); diff --git a/FWCore/Utilities/src/ExceptionCollector.cc b/FWCore/Utilities/src/ExceptionCollector.cc index b31f9b556449d..be7eec89596f9 100644 --- a/FWCore/Utilities/src/ExceptionCollector.cc +++ b/FWCore/Utilities/src/ExceptionCollector.cc @@ -44,7 +44,9 @@ namespace edm { firstException_.reset(ex.clone()); accumulatedExceptions_ = std::make_unique(ex.returnCode(), initialMessage_); } - *accumulatedExceptions_ << nExceptions_ << "\n" << ex.explainSelf(); + *accumulatedExceptions_ << "----- Exception " << nExceptions_ << " -----" + << "\n" + << ex.explainSelf(); } } diff --git a/IOMC/RandomEngine/plugins/RandomNumberGeneratorService.cc b/IOMC/RandomEngine/plugins/RandomNumberGeneratorService.cc index 8d83e4a6a3841..ae77696a8d98b 100644 --- a/IOMC/RandomEngine/plugins/RandomNumberGeneratorService.cc +++ b/IOMC/RandomEngine/plugins/RandomNumberGeneratorService.cc @@ -192,6 +192,11 @@ namespace edm { activityRegistry.watchPreallocate(this, &RandomNumberGeneratorService::preallocate); + activityRegistry.watchPreBeginJob(this, &RandomNumberGeneratorService::preBeginJob); + activityRegistry.watchPostBeginJob(this, &RandomNumberGeneratorService::postBeginJob); + activityRegistry.watchPreEndJob(this, &RandomNumberGeneratorService::preEndJob); + activityRegistry.watchPostEndJob(this, &RandomNumberGeneratorService::postEndJob); + if (enableChecking_) { activityRegistry.watchPreModuleBeginStream(this, &RandomNumberGeneratorService::preModuleBeginStream); activityRegistry.watchPostModuleBeginStream(this, &RandomNumberGeneratorService::postModuleBeginStream); @@ -222,11 +227,11 @@ namespace edm { CLHEP::HepRandomEngine& RandomNumberGeneratorService::getEngine(StreamID const& streamID) { ModuleCallingContext const* mcc = CurrentModuleOnThread::getCurrentModuleOnThread(); - if (mcc == nullptr) { + if (mcc == nullptr || beginJobEndJobActive_) { throw Exception(errors::LogicError) << "RandomNumberGeneratorService::getEngine\n" "Requested a random number engine from the RandomNumberGeneratorService\n" - "when no module was active. ModuleCallingContext is null\n"; + "while ModuleCallingContext is null or during beginJob or endJob transitions.\n"; } unsigned int moduleID = mcc->moduleDescription()->id(); @@ -256,11 +261,11 @@ namespace edm { CLHEP::HepRandomEngine& RandomNumberGeneratorService::getEngine(LuminosityBlockIndex const& lumiIndex) { ModuleCallingContext const* mcc = CurrentModuleOnThread::getCurrentModuleOnThread(); - if (mcc == nullptr) { + if (mcc == nullptr || beginJobEndJobActive_) { throw Exception(errors::LogicError) << "RandomNumberGeneratorService::getEngine\n" "Requested a random number engine from the RandomNumberGeneratorService\n" - "when no module was active. ModuleCallingContext is null\n"; + "while ModuleCallingContext is null or during beginJob or endJob transitions.\n"; } unsigned int moduleID = mcc->moduleDescription()->id(); @@ -302,11 +307,11 @@ namespace edm { std::uint32_t RandomNumberGeneratorService::mySeed() const { std::string label; ModuleCallingContext const* mcc = CurrentModuleOnThread::getCurrentModuleOnThread(); - if (mcc == nullptr) { + if (mcc == nullptr || beginJobEndJobActive_) { throw Exception(errors::LogicError) - << "RandomNumberGeneratorService::getEngine()\n" - "Requested a random number engine from the RandomNumberGeneratorService\n" - "from an unallowed transition. ModuleCallingContext is null\n"; + << "RandomNumberGeneratorService::mySeed()\n" + "Requested a random number seed from the RandomNumberGeneratorService\n" + "while ModuleCallingContext is null or during beginJob or endJob transitions.\n"; } else { label = mcc->moduleDescription()->moduleLabel(); } @@ -423,6 +428,16 @@ namespace edm { } } + void RandomNumberGeneratorService::preBeginJob(PathsAndConsumesOfModulesBase const&, ProcessContext const&) { + beginJobEndJobActive_ = true; + } + + void RandomNumberGeneratorService::postBeginJob() { beginJobEndJobActive_ = false; } + + void RandomNumberGeneratorService::preEndJob() { beginJobEndJobActive_ = true; } + + void RandomNumberGeneratorService::postEndJob() { beginJobEndJobActive_ = false; } + void RandomNumberGeneratorService::preBeginLumi(LuminosityBlock const& lumi) { if (!restoreStateTag_.label().empty()) { // Copy from a product in the LuminosityBlock to cache for a particular luminosityBlockIndex diff --git a/IOMC/RandomEngine/plugins/RandomNumberGeneratorService.h b/IOMC/RandomEngine/plugins/RandomNumberGeneratorService.h index d0778ad3a1657..89ee4ea1167ba 100644 --- a/IOMC/RandomEngine/plugins/RandomNumberGeneratorService.h +++ b/IOMC/RandomEngine/plugins/RandomNumberGeneratorService.h @@ -11,6 +11,7 @@ (originally in FWCore/Services) */ +#include "FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h" #include "FWCore/Utilities/interface/RandomNumberGenerator.h" #include "FWCore/Utilities/interface/InputTag.h" #include "FWCore/Utilities/interface/get_underlying_safe.h" @@ -92,6 +93,11 @@ namespace edm { void setLumiCache(LuminosityBlockIndex, std::vector const& iStates) override; void setEventCache(StreamID, std::vector const& iStates) override; + void preBeginJob(PathsAndConsumesOfModulesBase const&, ProcessContext const&); + void postBeginJob(); + void preEndJob(); + void postEndJob(); + /// These next 12 functions are only used to check that random numbers are not /// being generated in these methods when enable checking is configured on. void preModuleBeginStream(StreamContext const& sc, ModuleCallingContext const& mcc); @@ -270,6 +276,7 @@ namespace edm { bool enableChecking_; std::uint32_t eventSeedOffset_; + bool beginJobEndJobActive_ = false; bool verbose_; diff --git a/Mixing/Base/interface/PileUp.h b/Mixing/Base/interface/PileUp.h index 67f0a3dfe4ddc..191f65d735468 100644 --- a/Mixing/Base/interface/PileUp.h +++ b/Mixing/Base/interface/PileUp.h @@ -13,6 +13,7 @@ #include "FWCore/Framework/interface/EventPrincipal.h" #include "FWCore/ServiceRegistry/interface/ServiceToken.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/ExceptionCollector.h" #include "TH1F.h" @@ -82,6 +83,7 @@ namespace edm { void beginJob(eventsetup::ESRecordsToProductResolverIndices const&); void beginStream(edm::StreamID); void endStream(); + void endStream(ExceptionCollector&); void beginRun(const edm::Run& run, const edm::EventSetup& setup); void beginLuminosityBlock(const edm::LuminosityBlock& lumi, const edm::EventSetup& setup); diff --git a/Mixing/Base/src/BMixingModule.cc b/Mixing/Base/src/BMixingModule.cc index 3786b58bf852b..5a9dfce8c2bf0 100644 --- a/Mixing/Base/src/BMixingModule.cc +++ b/Mixing/Base/src/BMixingModule.cc @@ -12,6 +12,7 @@ #include "FWCore/Framework/interface/EventSetup.h" #include "FWCore/Framework/interface/EventPrincipal.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/Utilities/interface/ExceptionCollector.h" #include "DataFormats/Common/interface/Handle.h" #include "TFile.h" @@ -318,17 +319,24 @@ namespace edm { } } - void BMixingModule::beginStream(edm::StreamID iID) { + void BMixingModule::beginStream(edm::StreamID streamID) { for (size_t endIdx = 0; endIdx < maxNbSources_; ++endIdx) { if (inputSources_[endIdx]) - inputSources_[endIdx]->beginStream(iID); + inputSources_[endIdx]->beginStream(streamID); } } void BMixingModule::endStream() { + ExceptionCollector exceptionCollector( + "Multiple exceptions were thrown while executing endStream and endJob for mixing modules. " + "An exception message follows for each.\n"); + for (size_t endIdx = 0; endIdx < maxNbSources_; ++endIdx) { if (inputSources_[endIdx]) - inputSources_[endIdx]->endStream(); + inputSources_[endIdx]->endStream(exceptionCollector); + } + if (exceptionCollector.hasThrown()) { + exceptionCollector.rethrow(); } } diff --git a/Mixing/Base/src/PileUp.cc b/Mixing/Base/src/PileUp.cc index 5950c64456cee..9f9778b217ce2 100644 --- a/Mixing/Base/src/PileUp.cc +++ b/Mixing/Base/src/PileUp.cc @@ -8,6 +8,7 @@ #include "FWCore/Framework/interface/SignallingProductRegistry.h" #include "FWCore/Framework/interface/ESRecordsToProductResolverIndices.h" #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h" +#include "FWCore/ServiceRegistry/interface/GlobalContext.h" #include "FWCore/ServiceRegistry/interface/ProcessContext.h" #include "FWCore/Sources/interface/VectorInputSourceDescription.h" #include "FWCore/Sources/interface/VectorInputSourceFactory.h" @@ -202,13 +203,15 @@ namespace edm { input_->doBeginJob(); if (provider_.get() != nullptr) { edm::ServiceRegistry::Operate guard(*serviceToken_); - provider_->beginJob(*productRegistry_, iES); + GlobalContext globalContext(GlobalContext::Transition::kBeginJob, processContext_.get()); + provider_->beginJob(*productRegistry_, iES, globalContext); } } void PileUp::beginStream(edm::StreamID) { auto iID = eventPrincipal_->streamID(); // each producer has its own workermanager, so use default streamid streamContext_.reset(new StreamContext(iID, processContext_.get())); + streamContext_->setTransition(StreamContext::Transition::kBeginStream); if (provider_.get() != nullptr) { edm::ServiceRegistry::Operate guard(*serviceToken_); provider_->beginStream(iID, *streamContext_); @@ -216,10 +219,26 @@ namespace edm { } void PileUp::endStream() { + ExceptionCollector exceptionCollector( + "Multiple exceptions were thrown while executing PileUp::endStream. An exception message follows for " + "each.\n"); + endStream(exceptionCollector); + + if (exceptionCollector.hasThrown()) { + exceptionCollector.rethrow(); + } + } + + void PileUp::endStream(ExceptionCollector& exceptionCollector) { if (provider_.get() != nullptr) { edm::ServiceRegistry::Operate guard(*serviceToken_); - provider_->endStream(streamContext_->streamID(), *streamContext_); - provider_->endJob(); + streamContext_->setTransition(StreamContext::Transition::kEndStream); + provider_->endStream(streamContext_->streamID(), *streamContext_, exceptionCollector); + // This is kind of strange, end of job running as part of endStream multiple times... + // For the moment, I'm leaving this as is but maybe we should think about this... + // I think nothing uses this code anymore anyway... + GlobalContext globalContext(GlobalContext::Transition::kEndJob, processContext_.get()); + provider_->endJob(exceptionCollector, globalContext); } input_->doEndJob(); } @@ -229,6 +248,7 @@ namespace edm { runPrincipal_.reset(new RunPrincipal(productRegistry_, *processConfiguration_, nullptr, 0)); runPrincipal_->setAux(run.runAuxiliary()); edm::ServiceRegistry::Operate guard(*serviceToken_); + streamContext_->setTransition(StreamContext::Transition::kBeginRun); provider_->beginRun(*runPrincipal_, setup.impl(), run.moduleCallingContext(), *streamContext_); } } @@ -239,6 +259,7 @@ namespace edm { lumiPrincipal_->setRunPrincipal(runPrincipal_); setRandomEngine(lumi); edm::ServiceRegistry::Operate guard(*serviceToken_); + streamContext_->setTransition(StreamContext::Transition::kBeginLuminosityBlock); provider_->beginLuminosityBlock(*lumiPrincipal_, setup.impl(), lumi.moduleCallingContext(), *streamContext_); } } @@ -246,12 +267,14 @@ namespace edm { void PileUp::endRun(const edm::Run& run, const edm::EventSetup& setup) { if (provider_.get() != nullptr) { edm::ServiceRegistry::Operate guard(*serviceToken_); + streamContext_->setTransition(StreamContext::Transition::kEndRun); provider_->endRun(*runPrincipal_, setup.impl(), run.moduleCallingContext(), *streamContext_); } } void PileUp::endLuminosityBlock(const edm::LuminosityBlock& lumi, const edm::EventSetup& setup) { if (provider_.get() != nullptr) { edm::ServiceRegistry::Operate guard(*serviceToken_); + streamContext_->setTransition(StreamContext::Transition::kEndLuminosityBlock); provider_->endLuminosityBlock(*lumiPrincipal_, setup.impl(), lumi.moduleCallingContext(), *streamContext_); } } @@ -262,6 +285,7 @@ namespace edm { eventPrincipal_->setLuminosityBlockPrincipal(lumiPrincipal_.get()); eventPrincipal_->setRunAndLumiNumber(lumiPrincipal_->run(), lumiPrincipal_->luminosityBlock()); edm::ServiceRegistry::Operate guard(*serviceToken_); + streamContext_->setTransition(StreamContext::Transition::kEvent); provider_->setupPileUpEvent(*eventPrincipal_, setup.impl(), *streamContext_); } } diff --git a/Mixing/Base/src/SecondaryEventProvider.cc b/Mixing/Base/src/SecondaryEventProvider.cc index de0d7ee1640b4..a551f91c3605e 100644 --- a/Mixing/Base/src/SecondaryEventProvider.cc +++ b/Mixing/Base/src/SecondaryEventProvider.cc @@ -10,6 +10,8 @@ #include "DataFormats/Provenance/interface/ProductRegistry.h" #include "oneapi/tbb/task_arena.h" +#include + namespace { template void processOneOccurrence(edm::WorkerManager& manager, @@ -69,9 +71,10 @@ namespace edm { } // SecondaryEventProvider::SecondaryEventProvider void SecondaryEventProvider::beginJob(ProductRegistry const& iRegistry, - eventsetup::ESRecordsToProductResolverIndices const& iIndices) { + eventsetup::ESRecordsToProductResolverIndices const& iIndices, + GlobalContext const& globalContext) { ProcessBlockHelper dummyProcessBlockHelper; - workerManager_.beginJob(iRegistry, iIndices, dummyProcessBlockHelper); + workerManager_.beginJob(iRegistry, iIndices, dummyProcessBlockHelper, globalContext); } //NOTE: When the Stream interfaces are propagated to the modules, this code must be updated @@ -156,11 +159,16 @@ namespace edm { } } - void SecondaryEventProvider::beginStream(edm::StreamID iID, StreamContext& sContext) { + void SecondaryEventProvider::beginStream(edm::StreamID iID, StreamContext const& sContext) { workerManager_.beginStream(iID, sContext); } - void SecondaryEventProvider::endStream(edm::StreamID iID, StreamContext& sContext) { - workerManager_.endStream(iID, sContext); + void SecondaryEventProvider::endStream(edm::StreamID iID, + StreamContext const& sContext, + ExceptionCollector& exceptionCollector) { + // In this context the mutex is not needed because these things are not + // executing concurrently but in general the WorkerManager needs one. + std::mutex exceptionCollectorMutex; + workerManager_.endStream(iID, sContext, exceptionCollector, exceptionCollectorMutex); } } // namespace edm diff --git a/Mixing/Base/src/SecondaryEventProvider.h b/Mixing/Base/src/SecondaryEventProvider.h index 3f427d9c96d31..0b8c2572227bc 100644 --- a/Mixing/Base/src/SecondaryEventProvider.h +++ b/Mixing/Base/src/SecondaryEventProvider.h @@ -3,6 +3,7 @@ #include "FWCore/Framework/interface/WorkerManager.h" #include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h" #include #include @@ -37,11 +38,15 @@ namespace edm { void setupPileUpEvent(EventPrincipal& ep, const EventSetupImpl& setup, StreamContext& sContext); - void beginJob(ProductRegistry const& iRegistry, eventsetup::ESRecordsToProductResolverIndices const&); - void endJob() { workerManager_.endJob(); } + void beginJob(ProductRegistry const& iRegistry, + eventsetup::ESRecordsToProductResolverIndices const&, + GlobalContext const&); + void endJob(ExceptionCollector& exceptionCollector, GlobalContext const& globalContext) { + workerManager_.endJob(exceptionCollector, globalContext); + } - void beginStream(edm::StreamID iID, StreamContext& sContext); - void endStream(edm::StreamID iID, StreamContext& sContext); + void beginStream(edm::StreamID, StreamContext const&); + void endStream(edm::StreamID, StreamContext const&, ExceptionCollector&); private: std::unique_ptr exceptionToActionTable_;