Exception.cpp 3.64 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/******************************************************************************
 *                      Exception.cpp
 *
 * This file is part of the Castor project.
 * See http://castor.web.cern.ch/castor
 *
 * Copyright (C) 2003  CERN
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * 
 *
 * @author Castor Dev team, castor-dev@cern.ch
 *****************************************************************************/
Eric Cano's avatar
Eric Cano committed
24

25
#define _XOPEN_SOURCE 600
26
#include "Exception.hpp"
27
#include <stdlib.h>
Eric Cano's avatar
Eric Cano committed
28
29
30
31
32
33
#include <errno.h>
/* We want the thread safe (and portable) version of strerror */
#include <string.h>
#include <sstream>
#include <iosfwd>
#include <sstream>
34
35
36
#include <execinfo.h>
#include <cxxabi.h>

37
38
39
40

/* TODO remove me: it should be temporary */
#include <iostream>

41
42
43
using namespace castor::tape;

const char * Exception::what() const throw () {
44
45
46
  return m_what.c_str();
}

47
const char * Exception::shortWhat() const throw () {
48
49
50
  return m_shortWhat.c_str();
}

51
void Exception::setWhat(const std::string& what) {
52
  std::stringstream w;
53
54
  w << what << std::endl << std::string(backtrace);
  m_what = w.str();
55
  m_shortWhat = what;
56
}
Eric Cano's avatar
Eric Cano committed
57

58
Exceptions::Errnum::Errnum(std::string what):Exception("") {
Eric Cano's avatar
Eric Cano committed
59
60
  m_errnum = errno;
  char s[1000];
61
62
63
  /* _XOPEN_SOURCE seems not to work.  */
  char * errorStr = ::strerror_r(m_errnum, s, sizeof(s));
  if (!errorStr) {
Eric Cano's avatar
Eric Cano committed
64
65
    int new_errno = errno;
    std::stringstream w;
66
    w << "Errno=" << m_errnum << ". In addition, failed to read the corresponding error string (strerror gave errno="
Eric Cano's avatar
Eric Cano committed
67
68
69
            << new_errno << ")";
    m_strerror = w.str();
  } else {
70
    m_strerror = errorStr;
Eric Cano's avatar
Eric Cano committed
71
72
  }
  std::stringstream w2;
73
74
  if (what.size())
    w2 << what << " ";
Eric Cano's avatar
Eric Cano committed
75
  w2 << "Errno=" << m_errnum << ": " << m_strerror;
76
  setWhat(w2.str());
Eric Cano's avatar
Eric Cano committed
77
}
78

79
Exceptions::Backtrace::Backtrace() {
80
81
82
83
84
85
86
  void * array[200];
  size_t depth = ::backtrace(array, sizeof(array)/sizeof(void*));
  char ** strings = ::backtrace_symbols(array, depth);
  if (!strings)
    m_trace = "";
  else {
    std::stringstream trc;
87
    for (size_t i=0; i<depth; i++) {
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
      std::string line(strings[i]);
      /* Demangle the c++, if possible. We expect the c++ function name's to live
       * between a '(' and a +
       * line format: /usr/lib/somelib.so.1(_Mangle2Mangle3Ev+0x123) [0x12345] */
      if ((std::string::npos != line.find("(")) && (std::string::npos != line.find("+"))) {
        std::string before, theFunc, after;
        before = line.substr(0, line.find("(")+1);
        theFunc = line.substr(line.find("(")+1, line.find("+") - (line.find("(") + 1));
        after = line.substr(line.find("+"), std::string::npos);
        int status(-1);
        char demangled[200];
        size_t length(sizeof(demangled));
        abi::__cxa_demangle(theFunc.c_str(), demangled, &length, &status);
        if (0 == status)
          trc << before << demangled << after << " (C++ demangled)" << std::endl;
        else
          trc << strings[i] << std::endl;
      } else {
        trc << strings[i] << std::endl;
      }  
    }
    free (strings);
    m_trace = trc.str();
  }
}