LCOV - code coverage report
Current view: top level - tools - DLLoader.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 22 35 62.9 %
Date: 2024-10-18 14:00:25 Functions: 5 8 62.5 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #include "DLLoader.h"
      23             : 
      24             : #include "Exception.h"
      25             : #include <cstdlib>
      26             : #include <iostream>
      27             : #include "core/ActionRegister.h"
      28             : #include "core/CLToolRegister.h"
      29             : 
      30             : #ifdef __PLUMED_HAS_DLOPEN
      31             : #include <dlfcn.h>
      32             : #endif
      33             : 
      34             : namespace PLMD {
      35             : 
      36          42 : bool DLLoader::installed() {
      37             : #ifdef __PLUMED_HAS_DLOPEN
      38          42 :   return true;
      39             : #else
      40             :   return false;
      41             : #endif
      42             : }
      43             : 
      44             : 
      45          51 : void* DLLoader::load(const std::string&s) {
      46             : #ifdef __PLUMED_HAS_DLOPEN
      47          51 :   auto lockerAction=Register::registrationLock(s);
      48          51 :   void* p=dlopen(s.c_str(),RTLD_NOW|RTLD_LOCAL);
      49          51 :   if(!p) plumed_error()<<"Could not load library "<<s<<"\n"<<dlerror();
      50          51 :   handles.push_back(p);
      51          51 :   Register::completeAllRegistrations(p);
      52          51 :   return p;
      53             : #else
      54             :   plumed_error()<<"you are trying to use dlopen but it's not configured on your system";
      55             : #endif
      56          51 : }
      57             : 
      58      812061 : DLLoader::~DLLoader() {
      59      812061 :   auto debug=std::getenv("PLUMED_LOAD_DEBUG");
      60             : #ifdef __PLUMED_HAS_DLOPEN
      61      812061 :   if(debug) std::fprintf(stderr,"delete dlloader\n");
      62      812112 :   while(!handles.empty()) {
      63          51 :     int ret=dlclose(handles.back());
      64          51 :     if(ret) {
      65           0 :       std::fprintf(stderr,"+++ error reported by dlclose: %s\n",dlerror());
      66             :     }
      67             :     handles.pop_back();
      68             :   }
      69      812061 :   if(debug) std::fprintf(stderr,"end delete dlloader\n");
      70             : #endif
      71      812061 : }
      72             : 
      73      812061 : DLLoader::DLLoader() {
      74             :   // do nothing
      75      812061 : }
      76             : 
      77       55164 : const std::vector<void*> & DLLoader::getHandles() const noexcept {
      78       55164 :   return handles;
      79             : }
      80             : 
      81           0 : DLLoader::EnsureGlobalDLOpen::EnsureGlobalDLOpen(const void *symbol) noexcept {
      82             : #ifdef __PLUMED_HAS_DLOPEN
      83             : #ifdef __PLUMED_HAS_DLADDR
      84             :   Dl_info info;
      85             :   // from the manual:
      86             :   // If the address specified in addr could not be matched to a shared
      87             :   //      object, then these functions return 0.  In this case, an error
      88             :   //      message is not available via dlerror(3).
      89           0 :   int zeroIsError=dladdr(symbol, &info);
      90           0 :   if(zeroIsError!=0) {
      91             :     //This "promotes" to GLOBAL the object with the symbol pointed by ptr
      92           0 :     handle_ = dlopen(info.dli_fname, RTLD_GLOBAL | RTLD_NOW);
      93             :   } else {
      94           0 :     std::fprintf(stderr,
      95             :                  "+++WARNING+++"
      96             :                  "Failure in finding any object that contains the symbol %p.\n",
      97             :                  symbol);
      98             :   }
      99             : #else
     100             :   std::fprintf(stderr,
     101             :                "+++WARNING+++"
     102             :                "I can't use dladdr for promoting the library containing the symbol %p.\n"
     103             :                "This system seems not to support dladdr",
     104             :                symbol);
     105             : #endif //__PLUMED_HAS_DLADDR
     106             : #endif //__PLUMED_HAS_DLOPEN
     107           0 : }
     108             : 
     109           0 : DLLoader::EnsureGlobalDLOpen::~EnsureGlobalDLOpen() {
     110             : #ifdef __PLUMED_HAS_DLOPEN
     111           0 :   if (handle_) {
     112           0 :     dlclose(handle_);
     113             :   }
     114             : #endif //__PLUMED_HAS_DLOPEN
     115           0 : }
     116             : 
     117           0 : bool DLLoader::isPlumedGlobal() {
     118             : #if defined(__APPLE__)
     119             :   bool result;
     120             : #ifdef __PLUMED_HAS_DLOPEN
     121             :   void* handle;
     122             : #if defined(__PLUMED_HAS_RTLD_DEFAULT)
     123             :   handle=RTLD_DEFAULT;
     124             : #else
     125             :   handle=dlopen(NULL,RTLD_LOCAL);
     126             : #endif
     127             :   // we check for two variants, see wrapper/Plumed.h for an explanation:
     128             :   result=dlsym(handle,"plumed_plumedmain_create") || dlsym(handle,"plumedmain_create");
     129             :   if(handle) dlclose(handle);
     130             : #else
     131             :   // if a system cannot use dlopen, we assume plumed is globally available
     132             :   result=true;
     133             : #endif //__PLUMED_HAS_DLOPEN
     134             :   return result;
     135             : #else
     136           0 :   plumed_error()<<"DLLoader::isPlumedGlobal() is only functional with APPLE dlsym";
     137             : #endif
     138             : }
     139             : 
     140             : } // namespace PLMD

Generated by: LCOV version 1.16