AIDASoft / DD4hep

Detector Description Toolkit for High Energy Physics
http://dd4hep.cern.ch
GNU Lesser General Public License v3.0
53 stars 100 forks source link

listcomponents fails to load libG4processes.so with a TLS violation #411

Closed gordonwatts closed 6 years ago

gordonwatts commented 6 years ago

I'm using the rel 1.07.1 with a few small patches to cmake files (as described in now closed issues).

I'm trying to add a new sensitive detector action (Geant4SensitiveAction). This requires, among other lines in the source,

#include "DDG4/Factories.h"
using namespace dd4hep::sim;
DECLARE_GEANT4SENSITIVE(SimpleDetectorAction)

For the time being, I've just included it in the same .so that I've included the detector element creation code. However, when I run cmake, I get an error:

/usr/bin/cmake -Dlibname=libdd4Experiments.so -Drootmapfile=libdd4Experiments.components -Dgenmap_install_dir=/home/example/lib -DROOT_VERSION=6.12.06 -DDD4hep_DIR=/usr/local -P /usr/local/cmake/MakeGaudiMap.cmake
--  *** Gaudi listcomponents: Generate map for libdd4Experiments.so ...
--  *** MakeGaudiMap.cmake run command : /usr/local/bin/listcomponents -o libdd4Experiments.components libdd4Experiments.so
             WORKING_DIRECTORY /home/example/lib
ERROR: failed to load libdd4Experiments.so
/usr/local/lib/libG4processes.so: cannot allocate memory in static TLS block
make[2]: Leaving directory '/home/example'

My guess is there is some incompatibility between how DD4 compiles listcomponents and how libG4processes was built (the flags to cmake for G4 say that libG4processes.so was built with tls global-dynamic).

But it could be that I should not be trying to put these two things in the same library. I couldn't find any documentation about this in the HTML (or didn't know where to look), so perhaps I should have split these into two libraries.

What I am trying to do: I would like to dump custom data values for a "tracking"-like detector, rather than all the energy deposits as the track progresses through the detector. So a little like a calorimeter. Plus want to add some extra data about the detector itself. It looked like creating a new sensitive detector action was the right way to accomplish this.

Here is the cmake file:

cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
include ( "${DD4hep_DIR}/cmake/DD4hep.cmake" )

# Setup this package as a basic build with detector.
dd4hep_configure_output()
dd4hep_package (dd4Experiments MAJOR 0 MINOR 0 PATCH 1
  USES         [ROOT   REQUIRED COMPONENTS Geom GenVector] 
               [DD4hep REQUIRED COMPONENTS DDCore DDRec DDG4]
               [Geant4 COMPONENTS multithreaded]
    OPTIONAL     XERCESC
  INCLUDE_DIRS include )
dd4hep_set_compiler_flags()

# We have to build the detector plug-in. We will put it in the "bin" directory when it is built.
dd4hep_add_plugin(dd4Experiments SOURCES src/*.cpp)
dd4hep_install_dir(compact DESTINATION bin)

Note the DDG4 and Geant4 dependencies - they cause this problem (of course, code doesn't compile without them). Here is the C++ file I'm trying to build right now (currently does nothing till I can get the build to work!). It is located in the src directory.

#include "DDG4/Geant4SensDetAction.inl"
#include "DDG4/Geant4EventAction.h"

namespace dd4hep {
    namespace sim {

class SimpleDetector
{
};

template <>
void Geant4SensitiveAction<SimpleDetector>::defineCollections()
{
    m_collectionID = -1; //declareReadoutFilteredCollection<Geant4Tracker::Hit>();
}

template <>
bool Geant4SensitiveAction<SimpleDetector>::process(G4Step *step, G4TouchableHistory * /*hist*/)
{
#endif
    return true;
}
typedef Geant4SensitiveAction<Geant4Tracker> SimpleDetectorAction;
    }
}

// Define entry points for G4
#include "DDG4/Factories.h"
using namespace dd4hep::sim;
DECLARE_GEANT4SENSITIVE(SimpleDetectorAction)
andresailer commented 6 years ago

Is your docker file with the Geant4 build on dockerhub? That would make it most easy to reproduce.

MarkusFrankATcernch commented 6 years ago

1) In the past this error was always related with inconsistencies in the compile option: -ftls-model=global-dynamic Both, Geant4 and DD4hep need this option. Otherwise this behaviour appears. Here it might be different, because there is no code for the factory:

2) There is a typo in the code: typedef Geant4SensitiveAction<Geant4Tracker> SimpleDetectorAction; Should probably be: typedef Geant4SensitiveAction<SimpleDetector> SimpleDetectorAction;

I know that the macro is ugly. Any backwards compatible modification is highly welcome. But, you may instead of the using declaration be able to live with with a typedef at global scope: typedef dd4hep::sim::Geant4SensitiveAction<dd4hep::sim::SimpleDetector> SimpleDetectorAction;

3) There should be no factories in the src directory -- no factories entries will be generated. Instead it shows up in every component library linking to libDDG4.so .... Please move it to the "plugin" directory.

gordonwatts commented 6 years ago

I am using the docker G4 image I talked about - here is the link to it on the hub: https://hub.docker.com/r/gordonwatts/geant4/.

Ok, I'll create a plug-in directory. I'm sure there is an example in your example tree that does something with plug-ins, so I can find the build instructions there.

If I continue to have trouble I'll look into duplicating the git repo to github so you can see everything.

I'll update this bug report later this evening.

MarkusFrankATcernch commented 6 years ago

Ok. Here an example, which I built a minute ago:

//==========================================================================
//  AIDA Detector description implementation 
//--------------------------------------------------------------------------
// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
// All rights reserved.
//
// For the licensing terms see $DD4hepINSTALL/LICENSE.
// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
//
// Author     : M.Frank
//
//==========================================================================

// Framework include files
#include "DDG4/Geant4SensDetAction.inl"
#include "DDG4/Factories.h"

using namespace CLHEP;

namespace {
  struct MySimpleSD {};
}

/// Namespace for the AIDA detector description toolkit
namespace dd4hep {

  /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
  namespace sim   {

    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //               Geant4SensitiveAction<MySimpleSD>
    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    /** \addtogroup Geant4SDActionPlugin
     *
     * @{
     * \package MySimpleSDAction
     * \brief Sensitive detector meant for tracking detectors, will produce one hit per step
     *
     * @}
     */

    /// Define collections created by this sensitivie action object
    template <> void Geant4SensitiveAction<MySimpleSD>::defineCollections()    {
      m_collectionID = declareReadoutFilteredCollection<Geant4Tracker::Hit>();
    }

    /// Method for generating hit(s) using the information of G4Step object.
    template <> bool Geant4SensitiveAction<MySimpleSD>::process(G4Step* step,G4TouchableHistory* /*hist*/ ) {
      typedef Geant4Tracker::Hit Hit;
      Geant4StepHandler h(step);
      Position prePos    = h.prePos();
      Position postPos   = h.postPos();
      Position direction = postPos - prePos;
      Position position  = mean_direction(prePos,postPos);
      double   hit_len   = direction.R();

      // if (hit_len > 0) {
      //   double new_len = mean_length(h.preMom(),h.postMom())/hit_len;
      //   direction *= new_len/hit_len;
      // }

      Hit* hit = new Hit(h.trkID(), h.trkPdgID(), h.deposit(), h.track->GetGlobalTime());
      HitContribution contrib = Hit::extractContribution(step);
      hit->cellID        = cellID(step);
      hit->energyDeposit = contrib.deposit;
      hit->position      = position;
      hit->momentum      = 0.5*( h. preMom() + h.postMom() ) ;
      hit->length        = hit_len;
      collection(m_collectionID)->add(hit);
      mark(h.track);
      if ( 0 == hit->cellID )  {
        hit->cellID        = volumeID( step ) ;
        except("+++ Invalid CELL ID for hit!");
      }
      print("Hit with deposit:%f  Pos:%f %f %f ID=%016X",
            step->GetTotalEnergyDeposit(),position.X(),position.Y(),position.Z(),
            (void*)hit->cellID);
      Geant4TouchableHandler handler(step);
      print("    Geant4 path:%s",handler.path().c_str());
      return true;
    }

  }
}

//--- Factory declaration
namespace dd4hep { namespace sim {
    typedef Geant4SensitiveAction<MySimpleSD> MySimpleSDAction;
  }}
DECLARE_GEANT4SENSITIVE(MySimpleSDAction)
//----------------------------------------------------------------------------------------------------------------

The file is placed as DDG4/plugins/MySimpleSDAction.cpp in the source tree, but could also be a new plugin library. Then: $> make install $> cat lib/libDDG4Plugins.components | grep MySimpleSDAction libDDG4Plugins.so:MySimpleSDAction

All build and factory entry is created. Your problem MUST BE THE TYPO, as I mentioned earlier.

MarkusFrankATcernch commented 6 years ago

Addendum: 1) I assume the standard examples of DD4hep using Geant4 work. 2) For a check: after build, the following entries do appear in the library for my specialization MySimpleSD:

19:57:56-frankm~/SW/DD4hep_head_dbg.root_v6.12.06.g4_10.04.p01_MT/build/tmp/DD4hep_build$ nm -C lib/libDDG4Plugins.so | grep MySimpleSD
000000000004fd00 t _GLOBAL__sub_I_MySimpleSDAction.cpp
000000000007a1e0 t (anonymous namespace)::Factory<dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>, dd4hep::sim::Geant4Sensitive* (dd4hep::sim::Geant4Context*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, dd4hep::DetElement*, dd4hep::Detector*)>::call(dd4hep::sim::Geant4Context*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, dd4hep::DetElement*, dd4hep::Detector*)
000000000007a0a0 t dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>::initialize()
000000000007a350 t dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>::defineCollections()
000000000007ac60 t dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>::end(G4HCofThisEvent*)
000000000007ac70 t dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>::begin(G4HCofThisEvent*)
000000000007ac50 t dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>::clear(G4HCofThisEvent*)
000000000007a6e0 t dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>::process(G4Step*, G4TouchableHistory*)
000000000007a0a0 t dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>::finalize()
000000000007a0f0 t dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>::~Geant4SensitiveAction()
000000000007a0b0 t dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>::~Geant4SensitiveAction()
000000000007a0b0 t dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>::~Geant4SensitiveAction()
00000000002c2368 d typeinfo for dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>
000000000009a640 r typeinfo name for dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>
00000000002c2380 d vtable for dd4hep::sim::Geant4SensitiveAction<(anonymous namespace)::MySimpleSD>
MarkusFrankATcernch commented 6 years ago

@gordonwatts since I failed to add a tar file here, please see PM.

gordonwatts commented 6 years ago

I got the email, I will take a look. Sorry - at a conference this week so my work time has been reduced.

andresailer commented 6 years ago

After face-to-face discussions it turns out that Gordon wants the already existing functionality from https://dd4hep.web.cern.ch/dd4hep/reference/namespaceGeant4TrackerWeightedAction.html where steps are accumulated.

This doesn't solve the problem of building a plugin, but should we close this issue?

MarkusFrankATcernch commented 6 years ago

Yes. I think we can close then the issue. I added an example last week (or 2 weeks ago) showing how to add a personalized sensitive detector action. This should answer the question...