UserRunAction Segmentation Error with Multithreading

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