From f1cac1f9a0f21d9bb27cec97dc0e77fdd3fa4c0f Mon Sep 17 00:00:00 2001 From: aszostak Date: Thu, 25 Mar 2010 21:18:11 +0000 Subject: [PATCH] Fixing bug in generated trigger logic code for checking class inheritance. Fixing bug due to possible missing dictionaries when loading the global decision. Had to put back explicit checks for NULL pointers since the custom streamer is not guaranteed to be called if the object was written to a TTree with split-mode > 0. --- HLT/BASE/AliHLTGlobalTriggerDecision.cxx | 108 +++++++++++++++---- HLT/trigger/AliHLTGlobalTriggerComponent.cxx | 2 +- 2 files changed, 90 insertions(+), 20 deletions(-) diff --git a/HLT/BASE/AliHLTGlobalTriggerDecision.cxx b/HLT/BASE/AliHLTGlobalTriggerDecision.cxx index 1e5f8c46a8b..2e5e31f4e2f 100644 --- a/HLT/BASE/AliHLTGlobalTriggerDecision.cxx +++ b/HLT/BASE/AliHLTGlobalTriggerDecision.cxx @@ -26,11 +26,20 @@ #include "Riostream.h" #include "TClass.h" #include "AliHLTMisc.h" -#include +#include "AliHLTLogging.h" ClassImp(AliHLTGlobalTriggerDecision) +namespace { +const char* kgSplitModeMessage = + "The global decision object contains NULL pointers in the fInputObjects array." + " This means that it was written to a TTree branch with the split-mode > 0." + " This causes the custom streamer to be skipped and prevents the" + " fInputObjects array to be setup properly. In addition this can cause memory leaks."; +}; + + AliHLTGlobalTriggerDecision::AliHLTGlobalTriggerDecision() : AliHLTTriggerDecision(0, "HLTGlobalTrigger"), fContributingTriggers(AliHLTTriggerDecision::Class()), @@ -87,8 +96,15 @@ void AliHLTGlobalTriggerDecision::Print(Option_t* option) const cout << "#################### Input trigger decisions ####################" << endl; for (Int_t i = 0; i < NumberOfTriggerInputs(); i++) { - assert(TriggerInput(i) != NULL); - TriggerInput(i)->Print(option); + if (TriggerInput(i) != NULL) + { + TriggerInput(i)->Print(option); + } + else + { + AliHLTLogging log; + log.LoggingVarargs(kHLTLogError, this->ClassName(), FUNCTIONNAME(), __FILE__, __LINE__, kgSplitModeMessage); + } } if (NumberOfTriggerInputs() == 0) { @@ -115,8 +131,15 @@ void AliHLTGlobalTriggerDecision::Print(Option_t* option) const for (Int_t i = 0; i < NumberOfTriggerInputs(); i++) { cout << "-------------------- Input trigger decision " << i << " --------------------" << endl; - assert(TriggerInput(i) != NULL); - TriggerInput(i)->Print(option); + if (TriggerInput(i) != NULL) + { + TriggerInput(i)->Print(option); + } + else + { + AliHLTLogging log; + log.LoggingVarargs(kHLTLogError, this->ClassName(), FUNCTIONNAME(), __FILE__, __LINE__, kgSplitModeMessage); + } } if (NumberOfTriggerInputs() == 0) { @@ -126,8 +149,15 @@ void AliHLTGlobalTriggerDecision::Print(Option_t* option) const for (Int_t i = 0; i < NumberOfInputObjects(); i++) { cout << "------------------------ Input object " << i << " ------------------------" << endl; - assert(InputObject(i) != NULL); - InputObject(i)->Print(option); + if (InputObject(i) != NULL) + { + InputObject(i)->Print(option); + } + else + { + AliHLTLogging log; + log.LoggingVarargs(kHLTLogError, this->ClassName(), FUNCTIONNAME(), __FILE__, __LINE__, kgSplitModeMessage); + } } if (NumberOfInputObjects() == 0) { @@ -194,19 +224,33 @@ AliHLTGlobalTriggerDecision& AliHLTGlobalTriggerDecision::operator=(const AliHLT fContributingTriggers.Delete(); for (int triggerInput=0; triggerInputClassName(), FUNCTIONNAME(), __FILE__, __LINE__, kgSplitModeMessage); + } } DeleteInputObjects(); for (int inputObject=0; inputObjectClassName(), FUNCTIONNAME(), __FILE__, __LINE__, kgSplitModeMessage); + } } SetCounters(src.Counters()); @@ -274,7 +318,12 @@ void AliHLTGlobalTriggerDecision::DeleteInputObjects() for (Int_t i = 0; i < NumberOfInputObjects(); i++) { TObject* obj = fInputObjects.UncheckedAt(i); - assert(obj != NULL); + if (obj == NULL) + { + AliHLTLogging log; + log.LoggingVarargs(kHLTLogError, this->ClassName(), FUNCTIONNAME(), __FILE__, __LINE__, kgSplitModeMessage); + continue; + } if (obj->TestBit(kCanDelete)) delete obj; } fInputObjects.Clear(); @@ -290,12 +339,33 @@ void AliHLTGlobalTriggerDecision::Streamer(TBuffer &b) b.ReadClassBuffer(AliHLTGlobalTriggerDecision::Class(), this); // We must mark all the objects that were read into fInputObjects as owned. // Otherwise we will have a memory leak in DeleteInputObjects. - for (Int_t i = 0; i < fInputObjects.GetEntriesFast(); i++) + bool loggedWarning = false; + for (Int_t i = 0; i < fInputObjects.GetEntriesFast(); ++i) { TObject* obj = fInputObjects.UncheckedAt(i); - assert(obj != NULL); - obj->SetBit(kCanDelete); + // We must check if the object pointer is NULL. This could happen because the + // class dictionary has not been loaded, so the ReadClassBuffer streamer just + // silently skips the object but fills the fInputObjects array with a NULL pointer. + if (obj == NULL) + { + fInputObjects.RemoveAt(i); + if (not loggedWarning) + { + AliHLTLogging log; + log.LoggingVarargs(kHLTLogWarning, this->ClassName(), FUNCTIONNAME(), __FILE__, __LINE__, + "The global trigger decision contains NULL pointers in the input object array." + " This is probably due to the fact that some class dictionaries have not been loaded." + " Will just remove the NULL pointer and continue." + ); + loggedWarning = true; // Prevent multiple warnings, one is enough. + } + } + else + { + obj->SetBit(kCanDelete); + } } + fInputObjects.Compress(); } else { diff --git a/HLT/trigger/AliHLTGlobalTriggerComponent.cxx b/HLT/trigger/AliHLTGlobalTriggerComponent.cxx index 41c2c7560a9..fe9e0b7f897 100644 --- a/HLT/trigger/AliHLTGlobalTriggerComponent.cxx +++ b/HLT/trigger/AliHLTGlobalTriggerComponent.cxx @@ -966,7 +966,7 @@ int AliHLTGlobalTriggerComponent::GenerateTrigger( // 30 Oct 2009 - CINT sometimes evaluates the dynamic_cast incorrectly. // Have to use the TClass system for extra protection. code << " const " << symbol->ObjectClass() << "* " << symbol->Name() << "_object_ = NULL;" << endl; - code << " if (_object_->IsA()->GetBaseClass(\"" << symbol->ObjectClass() << "\") != NULL) " << symbol->Name() + code << " if (_object_->InheritsFrom(" << symbol->ObjectClass() << "::Class())) " << symbol->Name() << "_object_ = dynamic_castObjectClass() << "*>(_object_);" << endl; code << " if (" << symbol->Name() << "_object_ != NULL && "; -- 2.43.0