Problem 2082

Summary: Multiple instances of G4RunManager in the same binary cause crash
Product: Geant4 Reporter: Sergio Losilla <sergio.losilla>
Component: runAssignee: asai
Status: RESOLVED INVALID    
Severity: minor CC: sergio.losilla
Priority: P4    
Version: other   
Hardware: All   
OS: All   

Description Sergio Losilla 2018-08-31 18:04:55 CEST
The following simple program:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include "G4RunManager.hh"

int main(int argc, char *argv[])
{
    {
        G4RunManager manager;
    }
    {
        G4RunManager manager;
    }
    return 0;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

will crash when attempting to instantiate G4RunManager for the second time.

Here is the backtrace:

#0  0x00007fffeff6bcd6 in G4AllocatorPool::Grow (this=0x6611c8) at /home/sergio/src/geant4/source/global/management/src/G4AllocatorPool.cc:125
#1  0x00007ffff7142383 in G4AllocatorPool::Alloc (this=0x6611c8) at /home/sergio/src/geant4/source/global/management/include/G4AllocatorPool.hh:121
#2  0x00007ffff0db354c in G4Allocator<G4NavigationLevelRep>::MallocSingle (this=0x6611c0) at /home/sergio/src/geant4/source/global/management/include/G4Allocator.hh:204
#3  0x00007ffff0db346b in G4NavigationLevelRep::operator new () at /home/sergio/src/geant4/source/geometry/volumes/include/G4NavigationLevelRep.icc:178
#4  0x00007ffff0db2b2f in G4NavigationLevel::G4NavigationLevel (this=0x841b00) at /home/sergio/src/geant4/source/geometry/volumes/src/G4NavigationLevel.cc:64
#5  0x00007ffff33c3220 in std::_Construct<G4NavigationLevel> (__p=0x841b00) at /usr/include/c++/8/bits/stl_construct.h:75
#6  0x00007ffff33c30d9 in std::__uninitialized_default_n_1<false>::__uninit_default_n<G4NavigationLevel*, unsigned long> (__first=0x841b00, __n=15) at /usr/include/c++/8/bits/stl_uninitialized.h:527
#7  0x00007ffff33c2fc8 in std::__uninitialized_default_n<G4NavigationLevel*, unsigned long> (__first=0x841b00, __n=15) at /usr/include/c++/8/bits/stl_uninitialized.h:583
#8  0x00007ffff33c2dd3 in std::__uninitialized_default_n_a<G4NavigationLevel*, unsigned long, G4NavigationLevel> (__first=0x841b00, __n=15) at /usr/include/c++/8/bits/stl_uninitialized.h:645
#9  0x00007ffff0db1a41 in std::vector<G4NavigationLevel, std::allocator<G4NavigationLevel> >::_M_default_initialize (this=0x6940f0, __n=15) at /usr/include/c++/8/bits/stl_vector.h:1490
#10 0x00007ffff0db15b7 in std::vector<G4NavigationLevel, std::allocator<G4NavigationLevel> >::vector (this=0x6940f0, __n=15, __a=...) at /usr/include/c++/8/bits/stl_vector.h:417
#11 0x00007ffff0db12c8 in G4NavigationHistoryPool::GetNewLevels (this=0x8380b0) at /home/sergio/src/geant4/source/geometry/volumes/include/G4NavigationHistoryPool.hh:119
#12 0x00007ffff0db1387 in G4NavigationHistoryPool::GetLevels (this=0x8380b0) at /home/sergio/src/geant4/source/geometry/volumes/include/G4NavigationHistoryPool.hh:141
#13 0x00007ffff0db0dc4 in G4NavigationHistory::G4NavigationHistory (this=0x681b90) at /home/sergio/src/geant4/source/geometry/volumes/src/G4NavigationHistory.cc:48
#14 0x00007ffff0c54da7 in G4Navigator::G4Navigator (this=0x681b70) at /home/sergio/src/geant4/source/geometry/navigation/src/G4Navigator.cc:60
#15 0x00007ffff0c72fc5 in G4TransportationManager::G4TransportationManager (this=0x830680) at /home/sergio/src/geant4/source/geometry/navigation/src/G4TransportationManager.cc:67
#16 0x00007ffff0c73250 in G4TransportationManager::GetTransportationManager () at /home/sergio/src/geant4/source/geometry/navigation/src/G4TransportationManager.cc:100
#17 0x00007ffff4fdfb0a in G4SteppingManager::G4SteppingManager (this=0x6815c0) at /home/sergio/src/geant4/source/tracking/src/G4SteppingManager.cc:79
#18 0x00007ffff4febc14 in G4TrackingManager::G4TrackingManager (this=0x660930) at /home/sergio/src/geant4/source/tracking/src/G4TrackingManager.cc:53
#19 0x00007ffff526c130 in G4EventManager::G4EventManager (this=0x681520) at /home/sergio/src/geant4/source/event/src/G4EventManager.cc:62
#20 0x00007ffff5585b76 in G4RunManagerKernel::G4RunManagerKernel (this=0x840cb0, rmkType=G4RunManagerKernel::masterRMK) at /home/sergio/src/geant4/source/run/src/G4RunManagerKernel.cc:182
#21 0x00007ffff558a3ea in G4MTRunManagerKernel::G4MTRunManagerKernel (this=0x840cb0) at /home/sergio/src/geant4/source/run/src/G4MTRunManagerKernel.cc:38
#22 0x00007ffff55772b5 in G4RunManager::G4RunManager (this=0x7fffffffd4d0, rmType=G4RunManager::masterRM) at /home/sergio/src/geant4/source/run/src/G4RunManager.cc:158
#23 0x00007ffff557c261 in G4MTRunManager::G4MTRunManager (this=0x7fffffffd4d0) at /home/sergio/src/geant4/source/run/src/G4MTRunManager.cc:84
#24 0x0000000000400c0b in main (argc=1, argv=0x7fffffffda28) at main.cpp:9

Version found: v10.5.0.beta. Both Release and Debug builds crash.
Comment 1 asai 2018-09-03 08:52:34 CEST
G4RunManager has to be a singleton. It must not be instantiated more than once in an application, and we have protections against multiple instantiation. If multithreading is what you want to achieve, instantiate G4MTRunManager just once.
Hope this helps,
Makoto
Comment 2 Sergio Losilla 2018-09-03 10:05:13 CEST
Thanks for your reply.

Well, in this case the protection failed, didn't it? The call to G4Exception would have been triggered if I would have instantiated G4RunManager twice within the same scope, but because the singleton had been deleted, the process did not detect this and failed down the line. 

It seems to me that the G4(MT)RunManager tries to clean after itself, so my guess was that it should be possible to get the system to a clean state and instantiate G4(MT)RunManager again. Maybe some additional cleanup needs to be made in the pool allocator? I could roll up my sleeves and have a look at this, but first it would be nice to know if this is a futile effort :-D

If G4RunManager cannot be reinstantiated, can it be reset? That would also work for me.

What I am trying to achieve is writing a test suite with different setups, so I would need to do the Initialize/BeamOn/analysis sequence multiple times. I tried resetting the run manager, but I did not find an easy way to do this: G4RunManager::DeleteUserInitializations is a protected method called only from the G4RunManager destructor, which lead me to believe it should be possible to reset it by destroying it... And that's how I ended up here.
Comment 3 asai 2018-09-03 11:10:44 CEST
We have several kernel classes that are supposed to be instantiated only once. So, please restart your program application instead of re-instantiating G4RunManager.
Comment 4 Sergio Losilla 2018-09-03 12:15:16 CEST
What I was asking in my last comment is if it is possible to reset G4RunManager so I can call Initialize again with a different setup, so that my program would look like:

main()
{
    G4RunManager manager;
    ...
    manager.SetUserInitialization(physics1);
    manager.SetUserInitialization(geometry1);
    manager.SetUserInitialization(actions1);
    manager.Initialize
    manager.BeamOn(1);
    ...
    ??? Reset manager without re-instantiating ???
    ...
    manager.SetUserInitialization(physics2);
    manager.SetUserInitialization(geometry2);
    manager.SetUserInitialization(actions2);
    manager.Initialize
    manager.BeamOn(1);
    ...
    return 0;
}
Comment 5 asai 2018-09-03 12:19:57 CEST
Sorry but we do not have clean reset.
Comment 6 Sergio Losilla 2018-09-03 12:31:51 CEST
I suspected that :-/ Thanks for your time. I'll try to take a stab at the pool allocator issue in case something can be done.
Comment 7 asai 2018-09-03 12:51:15 CEST
I'm afraid allocator is not the only issue that prevents from resetting. Several manager classes and table classes behind the scene presume to be singleton without any convenient reset.
Makoto
Comment 8 Sergio Losilla 2018-09-03 13:39:22 CEST
Being the natural optimist I am, I think there is hope that the destructors of those classes are cleaning everything up :-D But yes, I do not expect this to be simple, or even possible. The worst that can happen if that I learn something about the inner workings of Geant4.

Thanks again!