The Gaudi Framework  v36r1 (3e2fb5a8)
StatusCodeSvc.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #include "StatusCodeSvc.h"
12 #include "GaudiKernel/StatusCode.h"
13 
14 //
16 //
17 inline void toupper( std::string& s ) { std::transform( s.begin(), s.end(), s.begin(), (int ( * )( int ))toupper ); }
18 
19 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20 
22 
24  if ( !sc.isSuccess() ) return sc;
25 
26  info() << "initialize" << endmsg;
27 
28  for ( const auto& itr : m_pFilter.value() ) {
29  std::string fnc, lib;
30  parseFilter( itr, fnc, lib );
31  if ( !fnc.empty() ) m_filterfnc.insert( fnc );
32  if ( !lib.empty() ) m_filterlib.insert( lib );
33  }
34 
35  return StatusCode::SUCCESS;
36 }
37 
38 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
39 
41 
42  info() << "reinitialize" << endmsg;
43 
44  return StatusCode::SUCCESS;
45 }
46 
47 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
49 
50  list();
51  return StatusCode::SUCCESS;
52 }
53 
54 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
55 
56 void StatusCodeSvc::regFnc( const std::string& fnc, const std::string& lib ) {
57 
59 
60  // A StatusCode instance may be create internally by ROOT dictionaries and,
61  // of course, it's not checked, so here we whitelist a few library names
62  // that are known to produce spurious reports.
63  if ( m_dict ) {
64  // ROOT's library names can end with either ".so" or ".so.x.y" with x.y the ROOT version in use
65  const auto len = lib.length();
66  if ( len >= 3 && lib.compare( len - 3, 3, ".so" ) == 0 ) {
67  if ( ( len >= 7 && ( lib.compare( len - 7, 4, "Dict" ) == 0 || lib.compare( len - 7, 4, "Core" ) == 0 ) ) ||
68  ( len >= 8 && lib.compare( len - 8, 5, "Cling" ) == 0 ) ) {
69  return;
70  }
71  } else if ( lib.rfind( "Dict.so" ) != std::string::npos || lib.rfind( "Cling.so" ) != std::string::npos ||
72  lib.rfind( "Core.so" ) != std::string::npos ) {
73  return;
74  }
75  }
76  // this appears only with gcc 4.9...
77  if ( fnc == "_PyObject_GC_Malloc" ) return;
78  // GAUDI-1036
79  if ( fnc == "PyThread_get_thread_ident" ) return;
80  if ( fnc == "local" ) return;
81 
82  const std::string rlib = lib.substr( lib.rfind( "/" ) + 1 );
83  if ( failsFilter( fnc, rlib ) ) return;
84 
85  if ( m_abort ) {
86  fatal() << "Unchecked StatusCode in " << fnc << " from lib " << lib << endmsg;
87  msgStream().flush();
88  abort();
89  }
90 
91  const std::string key = fnc + lib;
92 
93  decltype( m_dat )::const_iterator itr = m_dat.find( key );
94  if ( itr != m_dat.end() ) {
95  ++( itr->second.count );
96  } else {
97  m_dat.emplace( key, StatCodeDat{fnc, rlib} );
98  }
99 }
100 
101 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
102 
103 bool StatusCodeSvc::failsFilter( const std::string& fnc, const std::string& lib ) const {
104  return m_filterfnc.find( fnc ) != m_filterfnc.end() || m_filterlib.find( lib ) != m_filterlib.end();
105 }
106 
107 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
108 
109 void StatusCodeSvc::list() const {
110 
112  unsigned int N = 0;
113 
114  // Created a sorted map of the results
115  std::map<std::string, StatCodeDat> dat_sorted( m_dat.begin(), m_dat.end() );
116  for ( const auto& itr : dat_sorted ) {
117  const auto& dat = itr.second;
118 
119  // we need to do this in case someone has gotten to regFnc before filters were setup in initialize
120  if ( failsFilter( dat.fnc, dat.lib ) ) continue;
121 
122  N++;
123  os.width( 3 );
124  os.setf( std::ios_base::right, std::ios_base::adjustfield );
125  os << dat.count;
126 
127  os << " | ";
128  os.width( 30 );
129  os.setf( std::ios_base::left, std::ios_base::adjustfield );
130  os << dat.fnc;
131 
132  os << " | ";
133  os.setf( std::ios_base::left, std::ios_base::adjustfield );
134  os << dat.lib;
135 
136  os << std::endl;
137  }
138  if ( N > 0 ) {
139  info() << "listing all unchecked return codes:" << endmsg;
140  info() << std::endl
141  << "Num | Function | Source Library" << std::endl
142  << "----+--------------------------------+------------------------------------------" << std::endl
143  << os.str() << endmsg;
144  } else {
145  if ( msgLevel( MSG::DEBUG ) ) debug() << "all StatusCode instances where checked" << endmsg;
146  }
147 }
148 
149 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
150 
151 void StatusCodeSvc::parseFilter( const std::string& str, std::string& fnc, std::string& lib ) const {
152 
153  auto loc = str.find( "=" );
154  if ( loc == std::string::npos ) {
155  fnc = str;
156  lib = "";
157  } else {
158  std::string key = str.substr( 0, loc );
159  std::string val = str.substr( loc + 1 );
160 
161  toupper( key );
162 
163  if ( key == "FCN" || key == "FNC" ) {
164  fnc = val;
165  lib.clear();
166  } else if ( key == "LIB" ) {
167  fnc.clear();
168  lib = val;
169  } else {
170  fnc.clear();
171  lib.clear();
172 
173  warning() << "ignoring unknown token in Filter: " << str << endmsg;
174  }
175  }
176 }
177 
178 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
179 
MSG::DEBUG
@ DEBUG
Definition: IMessageSvc.h:25
std::ostringstream::width
T width(T... args)
Service::initialize
StatusCode initialize() override
Definition: Service.cpp:118
std::string
STL class.
IOTest.N
N
Definition: IOTest.py:110
Service::m_state
Gaudi::StateMachine::State m_state
Service state
Definition: Service.h:206
StatusCode::isSuccess
bool isSuccess() const
Definition: StatusCode.h:355
gaudirun.s
string s
Definition: gaudirun.py:328
std::set::find
T find(T... args)
StatusCodeSvc::m_abort
Gaudi::Property< bool > m_abort
Definition: StatusCodeSvc.h:48
std::string::length
T length(T... args)
StatusCodeSvc::m_filterfnc
std::set< std::string > m_filterfnc
Definition: StatusCodeSvc.h:53
StatusCodeSvc::regFnc
void regFnc(const std::string &func, const std::string &lib) override
Definition: StatusCodeSvc.cpp:56
StatusCode.h
CommonMessaging< implements< IService, IProperty, IStateful > >::msgLevel
MSG::Level msgLevel() const
get the cached level (originally extracted from the embedded MsgStream)
Definition: CommonMessaging.h:148
StatusCodeSvc::parseFilter
void parseFilter(const std::string &str, std::string &fnc, std::string &lib) const
Definition: StatusCodeSvc.cpp:151
std::string::clear
T clear(T... args)
StatusCodeSvc::StatCodeDat
Definition: StatusCodeSvc.h:34
StatusCodeSvc::m_filterlib
std::set< std::string > m_filterlib
Definition: StatusCodeSvc.h:53
Gaudi::StateMachine::CONFIGURED
@ CONFIGURED
Definition: StateMachine.h:24
StatusCode
Definition: StatusCode.h:65
StatusCodeSvc::finalize
StatusCode finalize() override
Definition: StatusCodeSvc.cpp:48
MsgStream::flush
MsgStream & flush()
Definition: MsgStream.h:123
toupper
void toupper(std::string &s)
Definition: StatusCodeSvc.cpp:17
Gaudi::StateMachine::OFFLINE
@ OFFLINE
Definition: StateMachine.h:23
std::string::compare
T compare(T... args)
Gaudi::Property::value
const ValueType & value() const
Backward compatibility (.
Definition: Property.h:240
StatusCodeSvc::m_dict
Gaudi::Property< bool > m_dict
Definition: StatusCodeSvc.h:50
std::ostringstream::setf
T setf(T... args)
StatusCodeSvc::reinitialize
StatusCode reinitialize() override
Definition: StatusCodeSvc.cpp:40
StatusCodeSvc::failsFilter
bool failsFilter(const std::string &fnc, const std::string &lib) const
Definition: StatusCodeSvc.cpp:103
StatusCodeSvc::m_pFilter
Gaudi::Property< std::vector< std::string > > m_pFilter
Definition: StatusCodeSvc.h:47
StatusCodeSvc
Definition: StatusCodeSvc.h:22
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:203
std::map
STL class.
std::transform
T transform(T... args)
std::string::substr
T substr(T... args)
std::ostringstream
STL class.
StatusCodeSvc.h
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
std::endl
T endl(T... args)
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
std::set::insert
T insert(T... args)
StatusCodeSvc::list
void list() const override
Definition: StatusCodeSvc.cpp:109
StatusCodeSvc::initialize
StatusCode initialize() override
Definition: StatusCodeSvc.cpp:21
std::string::empty
T empty(T... args)
std::ostringstream::str
T str(T... args)
std::set::end
T end(T... args)
ProduceConsume.key
key
Definition: ProduceConsume.py:52
std::string::rfind
T rfind(T... args)
StatusCodeSvc::m_dat
tbb::concurrent_unordered_map< std::string, StatCodeDat > m_dat
Definition: StatusCodeSvc.h:52