LCOV - code coverage report
Current view: top level - tools - PlumedHandle.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 12 57 21.1 %
Date: 2021-11-18 15:22:58 Functions: 4 11 36.4 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2018-2020 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 "PlumedHandle.h"
      23             : #include "core/PlumedMain.h"
      24             : #include "Tools.h"
      25             : #include <cstring>
      26             : #ifdef __PLUMED_HAS_DLOPEN
      27             : #include <dlfcn.h>
      28             : #endif
      29             : 
      30             : namespace PLMD
      31             : {
      32             : 
      33          22 : PlumedHandle::DlHandle::~DlHandle() {
      34             : #ifdef __PLUMED_HAS_DLOPEN
      35          11 :   if(handle) dlclose(handle);
      36             : #endif
      37          11 : }
      38             : 
      39          11 : PlumedHandle::PlumedHandle():
      40          22 :   local(new PlumedMain)
      41             : {
      42          11 : }
      43             : 
      44           0 : PlumedHandle::PlumedHandle(const char* kernel)
      45             : #ifdef __PLUMED_HAS_DLOPEN
      46             :   :
      47           0 :   handle([&]() {
      48           0 :   dlerror();
      49             :   int mode = RTLD_LOCAL | RTLD_NOW;
      50             : #ifdef RTLD_DEEPBIND
      51             : // Needed on Linux to avoid namespace clashes
      52             :   mode |= RTLD_DEEPBIND;
      53             : #endif
      54           0 :   void* h=::dlopen(kernel,mode);
      55             : // try to remove the "Kernel" string.
      56             : // needed to load old versions
      57           0 :   if(!h) {
      58           0 :     std::string k(kernel);
      59             :     auto i=k.rfind("Kernel");
      60           0 :     if(i!=std::string::npos) {
      61           0 :       k=k.substr(0,i) + k.substr(i+6);
      62           0 :       h=::dlopen(k.c_str(),mode);
      63             :     }
      64             :   }
      65           0 :   plumed_assert(h) << "there was a problem loading kernel "<<kernel <<"\n"<<dlerror();
      66           0 :   return DlHandle(h);
      67             : // once the DlHandle has been constructed we know that later exceptions will also call dlclose().
      68             : }()),
      69           0 : symbol_((plumed_symbol_table_type*) dlsym(handle,"plumed_symbol_table")),
      70           0 : create_([&]() {
      71           0 :   if(symbol_) {
      72           0 :     plumed_assert(symbol_->functions.create);
      73             :     return symbol_->functions.create;
      74             :   }
      75             :   void* c=nullptr;
      76           0 :   if(!c) c=dlsym(handle,"plumedmain_create");
      77           0 :   if(!c) c=dlsym(handle,"plumed_plumedmain_create");
      78           0 :   plumed_assert(c) << "in kernel "<<kernel<<" I could not find (plumed_)plumedmain_create";
      79             :   plumed_create_pointer cc;
      80           0 :   *(void **)(&cc)=c;
      81           0 :   return cc;
      82           0 : }()),
      83           0 : cmd_([&]() {
      84           0 :   if(symbol_) {
      85           0 :     plumed_assert(symbol_->functions.cmd);
      86             :     return symbol_->functions.cmd;
      87             :   }
      88             :   void* c=nullptr;
      89           0 :   if(!c) c=dlsym(handle,"plumedmain_cmd");
      90           0 :   if(!c) c=dlsym(handle,"plumed_plumedmain_cmd");
      91           0 :   plumed_assert(c) << "in kernel "<<kernel<<" I could not find (plumed_)plumedmain_cmd";
      92             :   plumed_cmd_pointer cc;
      93           0 :   *(void **)(&cc)=c;
      94           0 :   return cc;
      95           0 : }()),
      96           0 : finalize_([&]() {
      97           0 :   if(symbol_) {
      98           0 :     plumed_assert(symbol_->functions.finalize);
      99             :     return symbol_->functions.finalize;
     100             :   }
     101             :   void* f=nullptr;
     102           0 :   if(!f) f=dlsym(handle,"plumedmain_finalize");
     103           0 :   if(!f) f=dlsym(handle,"plumed_plumedmain_finalize");
     104           0 :   plumed_assert(f) << "in kernel "<<kernel<<" I could not find (plumed_)plumedmain_finalize";
     105             :   plumed_finalize_pointer ff;
     106           0 :   *(void **)(&ff)=f;
     107           0 :   return ff;
     108           0 : }()),
     109           0 : p(create_())
     110             : // No exceptions thrown past this point.
     111             : // Thus, destructor PlumedHandle::~PlumedHandle() will always be called and p will always be finalized.
     112           0 : {}
     113             : #else
     114             : {
     115             :   plumed_error() << "You are trying to dynamically load a kernel, but PLUMED was compiled without dlopen";
     116             : }
     117             : #endif
     118             : 
     119          33 : PlumedHandle::~PlumedHandle() {
     120             : #ifdef __PLUMED_HAS_DLOPEN
     121          11 :   if(p) finalize_(p);
     122             : #endif
     123          11 : }
     124             : 
     125           0 : PlumedHandle PlumedHandle::dlopen(const char* path) {
     126           0 :   return PlumedHandle(path);
     127             : }
     128             : 
     129        1254 : void PlumedHandle::cmd(const char*key,const void*ptr) {
     130        2508 :   if(local) local->cmd(key,ptr);
     131           0 :   else if(p && cmd_) cmd_(p,key,ptr);
     132           0 :   else plumed_error() << "should never arrive here (either one or the other should work)";
     133        1254 : }
     134             : 
     135             : }

Generated by: LCOV version 1.14