Hello all,
I am coming across a multithreading segmentation error and crash. Previously attempting a separate analysis class, I decided to keep my variables and data storage in my UserRunAction.hh file, as that’s where I book my AnalysisManager Ntuples. My crash is coming from my BeginOfEventAction anytime I try to access the variables from my UserRunAction class. For example,
runAction->nScintPhotons = 0;
gives me a segmentation error. runAction is defined in my EventAction constructor like so:
if(!runAction)
runAction = (MyRunAction*)G4RunManager::GetRunManager()->GetUserRunAction();
In MyEventAction.hh, I declare the MyRunAction object like so:
private:
MyRunAction* runAction;
From my understanding and all the presentations online, each thread gets its own MyRunAction instance. To me, that means I should be able to change MyRunAction variables for each thread without any race conditions.
Please let me know where my misconception lays and if there are any silly mistakes I may have made.
Thanks so much,
Shivom
Geant4 Version: 11.3
Operating System: Linux
Hi Shivom
Your RunAction should be defined your ActionInitialization. This is something that has changed in going from 10 → 11. Have a look at a simple example. Is this the problem?
John
Hey John,
I don’t think this is the problem. I have SetUserAction(new MyRunAction()) in both Build() and BuildFromMaster().
Thanks,
Shivom
Edit: Have I overlooked the G4Run class? Would it be better I store my variables in an extended G4Run class and access them using something like
void MyEventAction::BeginOfEventAction(const G4Event* evt)
{
if(!aRun)
MyRun* aRun = G4RunManager()::GetCurrentRun();
aRun->nScintPhotons = 0;
aRun->CalorimeterHitsCollID= -1;
aRun->etc;
But if each thread gets its own instance of MyRunAction, what’s the difference between having the variables in MyRunAction or in MyRun?
Hello,
Through lots of confusion, I found the solution to my problem.
G4RunManager::GetRunManager()->GetUserRunAction();
did not return the same MyRunAction instance that was being used in the run itself.
I changed my UserActionInitialization Build() method from
SetUserAction(new MyRunAction);
SetUserAction(new MyEventAction);
to
auto threadLocalRunAction = new MyRunAction();
SetUserAction(threadLocalRunAction);
SetUserAction(new MyEventAction(threadLocalRunAction) );
...
Passing in threadLocalRunAction
as a parameter to a new MyEventAction
constructor allowed me to correctly ‘connect’ my MyRunAction instance to my runAction variable.
I suppose this is because I extended the G4UserRunAction class, but I would’ve expected the GetUserRunAction()
method to return the correct MyRunAction.
Regardless, thank you John
Shivom