~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/stacktrace.cc

  • Committer: Brian Aker
  • Date: 2010-08-19 16:45:03 UTC
  • mfrom: (1711.6.11 staging)
  • Revision ID: brian@tangent.org-20100819164503-t7rhibp5s7bv3dtu
Merge of signals, plus build fix for FreeBSD. Also contains memset/constructor patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* - mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
19
 
 
20
 
#include "config.h"
21
 
#include "drizzled/stacktrace.h"
22
 
#include <cstddef>
23
 
 
24
 
#include <signal.h>
25
 
#include "drizzled/internal/my_pthread.h"
26
 
#include "drizzled/internal/m_string.h"
27
 
#ifdef HAVE_STACKTRACE
28
 
#include <unistd.h>
29
 
#include <strings.h>
30
 
 
31
 
#if HAVE_EXECINFO_H
32
 
#include <execinfo.h>
33
 
#endif
34
 
 
35
 
#include <cstring>
36
 
#include <cstdio>
37
 
#include <algorithm>
38
 
 
39
 
#if defined(BACKTRACE_DEMANGLE)
40
 
# include <cxxabi.h>
41
 
#endif
42
 
 
43
 
#include "drizzled/definitions.h"
44
 
 
45
 
using namespace std;
46
 
 
47
 
namespace drizzled
48
 
{
49
 
 
50
 
#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end)
51
 
 
52
 
char *heap_start;
53
 
 
54
 
void safe_print_str(const char* name, const char* val, int max_len)
55
 
{
56
 
  char *heap_end= (char*) sbrk(0);
57
 
  fprintf(stderr, "%s at %p ", name, val);
58
 
 
59
 
  if (!PTR_SANE(val))
60
 
  {
61
 
    fprintf(stderr, " is invalid pointer\n");
62
 
    return;
63
 
  }
64
 
 
65
 
  fprintf(stderr, "= ");
66
 
  for (; max_len && PTR_SANE(val) && *val; --max_len)
67
 
    fputc(*val++, stderr);
68
 
  fputc('\n', stderr);
69
 
}
70
 
 
71
 
#ifdef TARGET_OS_LINUX
72
 
 
73
 
#ifdef __i386__
74
 
#define SIGRETURN_FRAME_OFFSET 17
75
 
#endif
76
 
 
77
 
#ifdef __x86_64__
78
 
#define SIGRETURN_FRAME_OFFSET 23
79
 
#endif
80
 
 
81
 
#if defined(BACKTRACE_DEMANGLE)
82
 
 
83
 
static inline char *my_demangle(const char *mangled_name, int *status)
84
 
{
85
 
  return abi::__cxa_demangle(mangled_name, NULL, NULL, status);
86
 
}
87
 
 
88
 
static void my_demangle_symbols(char **addrs, int n)
89
 
{
90
 
  int status, i;
91
 
  char *begin, *end, *demangled;
92
 
 
93
 
  for (i= 0; i < n; i++)
94
 
  {
95
 
    demangled= NULL;
96
 
    begin= strchr(addrs[i], '(');
97
 
    end= begin ? strchr(begin, '+') : NULL;
98
 
 
99
 
    if (begin && end)
100
 
    {
101
 
      *begin++= *end++= '\0';
102
 
      demangled= my_demangle(begin, &status);
103
 
      if (!demangled || status)
104
 
      {
105
 
        demangled= NULL;
106
 
        begin[-1]= '(';
107
 
        end[-1]= '+';
108
 
      }
109
 
    }
110
 
 
111
 
    if (demangled)
112
 
      fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end);
113
 
    else
114
 
      fprintf(stderr, "%s\n", addrs[i]);
115
 
  }
116
 
}
117
 
#endif
118
 
 
119
 
 
120
 
#if HAVE_BACKTRACE
121
 
static void backtrace_current_thread(void)
122
 
{
123
 
  void *addrs[128];
124
 
  char **strings= NULL;
125
 
  int n = backtrace(addrs, array_elements(addrs));
126
 
#if BACKTRACE_DEMANGLE
127
 
  if ((strings= backtrace_symbols(addrs, n)))
128
 
  {
129
 
    my_demangle_symbols(strings, n);
130
 
    free(strings);
131
 
  }
132
 
#endif
133
 
#if HAVE_BACKTRACE_SYMBOLS_FD
134
 
  if (!strings)
135
 
  {
136
 
    backtrace_symbols_fd(addrs, n, fileno(stderr));
137
 
  }
138
 
#endif
139
 
}
140
 
#endif
141
 
 
142
 
 
143
 
void  print_stacktrace(unsigned char* stack_bottom, size_t thread_stack)
144
 
{
145
 
#if HAVE_BACKTRACE
146
 
  backtrace_current_thread();
147
 
  return;
148
 
#endif
149
 
  unsigned char** fp;
150
 
  uint32_t frame_count = 0, sigreturn_frame_count;
151
 
 
152
 
#ifdef __i386__
153
 
  __asm __volatile__ ("movl %%ebp,%0"
154
 
                      :"=r"(fp)
155
 
                      :"r"(fp));
156
 
#endif
157
 
#ifdef __x86_64__
158
 
  __asm __volatile__ ("movq %%rbp,%0"
159
 
                      :"=r"(fp)
160
 
                      :"r"(fp));
161
 
#endif
162
 
  if (!fp)
163
 
  {
164
 
    fprintf(stderr, "frame pointer is NULL, did you compile with\n"
165
 
                    "-fomit-frame-pointer? Aborting backtrace!\n");
166
 
    return;
167
 
  }
168
 
 
169
 
  if (!stack_bottom || (unsigned char*) stack_bottom > (unsigned char*) &fp)
170
 
  {
171
 
    ulong tmp= min((size_t)0x10000,thread_stack);
172
 
    /* Assume that the stack starts at the previous even 65K */
173
 
    stack_bottom= (unsigned char*) (((ulong) &fp + tmp) &
174
 
                          ~(ulong) 0xFFFF);
175
 
    fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", (void *)fp);
176
 
  }
177
 
  if (fp > (unsigned char**) stack_bottom ||
178
 
      fp < (unsigned char**) stack_bottom - thread_stack)
179
 
  {
180
 
    fprintf(stderr, "Bogus stack limit or frame pointer, "
181
 
                    "fp=%p, stack_bottom=%p, thread_stack=%"PRIu64", "
182
 
                    "aborting backtrace.\n",
183
 
            (void *)fp, (void *)stack_bottom, (uint64_t)thread_stack);
184
 
    return;
185
 
  }
186
 
 
187
 
  fprintf(stderr, "Stack range sanity check OK, backtrace follows:\n");
188
 
 
189
 
  /* We are 1 frame above signal frame with NPTL and 2 frames above with LT */
190
 
  sigreturn_frame_count = internal::thd_lib_detected == THD_LIB_LT ? 2 : 1;
191
 
 
192
 
  while (fp < (unsigned char**) stack_bottom)
193
 
  {
194
 
#if defined(__i386__) || defined(__x86_64__)
195
 
    unsigned char** new_fp = (unsigned char**)*fp;
196
 
    fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ?
197
 
            *(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
198
 
#endif /* defined(__386__)  || defined(__x86_64__) */
199
 
 
200
 
    if (new_fp <= fp )
201
 
    {
202
 
      fprintf(stderr, "New value of fp=%p failed sanity check, "
203
 
                      "terminating stack trace!\n", (void *)new_fp);
204
 
      goto end;
205
 
    }
206
 
    fp = new_fp;
207
 
    ++frame_count;
208
 
  }
209
 
 
210
 
  fprintf(stderr, "Stack trace seems successful - bottom reached\n");
211
 
 
212
 
end:
213
 
  fprintf(stderr,
214
 
          "Please read http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
215
 
          "and follow instructions on how to resolve the stack trace.\n"
216
 
          "Resolved stack trace is much more helpful in diagnosing the\n"
217
 
          "problem, so please do resolve it\n");
218
 
}
219
 
#endif /* TARGET_OS_LINUX */
220
 
 
221
 
} /* namespace drizzled */
222
 
 
223
 
#endif /* HAVE_STACKTRACE */
224
 
 
225
 
/* Produce a core for the thread */
226
 
 
227
 
namespace drizzled
228
 
{
229
 
 
230
 
void write_core(int sig)
231
 
{
232
 
  signal(sig, SIG_DFL);
233
 
#ifdef HAVE_gcov
234
 
  /*
235
 
    For GCOV build, crashing will prevent the writing of code coverage
236
 
    information from this process, causing gcov output to be incomplete.
237
 
    So we force the writing of coverage information here before terminating.
238
 
  */
239
 
  extern void __gcov_flush(void);
240
 
  __gcov_flush();
241
 
#endif
242
 
  pthread_kill(pthread_self(), sig);
243
 
#if defined(P_MYID) && !defined(SCO)
244
 
  /* On Solaris, the above kill is not enough */
245
 
  sigsend(P_PID,P_MYID,sig);
246
 
#endif
247
 
}
248
 
 
249
 
} /* namespace drizzled */