~drizzle-trunk/drizzle/development

467 by Monty Taylor
Made sql_state and stacktrace compile as C++. drizzled/ is pure c++ now.
1
/* - mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
398.1.6 by Monty Taylor
Removed __alpha__ references.
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
 */
1 by brian
clean slate
19
960.2.20 by Monty Taylor
Removed global.h from a header.
20
#include "drizzled/global.h"
1 by brian
clean slate
21
#include "stacktrace.h"
22
23
#include <signal.h>
212.5.13 by Monty Taylor
Moved my_sys/my_pthread/my_nosys and mysys_err to mysys.
24
#include <mysys/my_pthread.h>
212.5.45 by Monty Taylor
Removed excess AM_CPPFLAGS from the tree. Now the only thing that should be in the include path should be -I${top_srcdir} and -I${top_builddir}w
25
#include <mystrings/m_string.h>
1 by brian
clean slate
26
#ifdef HAVE_STACKTRACE
27
#include <unistd.h>
28
#include <strings.h>
29
30
#if HAVE_EXECINFO_H
31
#include <execinfo.h>
32
#endif
33
1067.4.11 by Nathan Williams
Converted last usage of cmin to std::min.
34
#include <algorithm>
35
36
using namespace std;
37
1 by brian
clean slate
38
#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end)
39
40
char *heap_start;
41
42
void safe_print_str(const char* name, const char* val, int max_len)
43
{
44
  char *heap_end= (char*) sbrk(0);
45
  fprintf(stderr, "%s at %p ", name, val);
46
47
  if (!PTR_SANE(val))
48
  {
49
    fprintf(stderr, " is invalid pointer\n");
50
    return;
51
  }
52
53
  fprintf(stderr, "= ");
54
  for (; max_len && PTR_SANE(val) && *val; --max_len)
55
    fputc(*val++, stderr);
56
  fputc('\n', stderr);
57
}
58
59
#ifdef TARGET_OS_LINUX
60
61
#ifdef __i386__
62
#define SIGRETURN_FRAME_OFFSET 17
63
#endif
64
65
#ifdef __x86_64__
66
#define SIGRETURN_FRAME_OFFSET 23
67
#endif
68
69
70
#if BACKTRACE_DEMANGLE
71
static void my_demangle_symbols(char **addrs, int n)
72
{
73
  int status, i;
74
  char *begin, *end, *demangled;
75
76
  for (i= 0; i < n; i++)
77
  {
78
    demangled= NULL;
79
    begin= strchr(addrs[i], '(');
80
    end= begin ? strchr(begin, '+') : NULL;
81
82
    if (begin && end)
83
    {
84
      *begin++= *end++= '\0';
85
      demangled= my_demangle(begin, &status);
86
      if (!demangled || status)
87
      {
88
        demangled= NULL;
89
        begin[-1]= '(';
90
        end[-1]= '+';
91
      }
92
    }
93
94
    if (demangled)
95
      fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end);
96
    else
97
      fprintf(stderr, "%s\n", addrs[i]);
98
  }
99
}
100
#endif
101
102
103
#if HAVE_BACKTRACE
104
static void backtrace_current_thread(void)
105
{
106
  void *addrs[128];
107
  char **strings= NULL;
108
  int n = backtrace(addrs, array_elements(addrs));
109
#if BACKTRACE_DEMANGLE
110
  if ((strings= backtrace_symbols(addrs, n)))
111
  {
112
    my_demangle_symbols(strings, n);
113
    free(strings);
114
  }
115
#endif
116
#if HAVE_BACKTRACE_SYMBOLS_FD
117
  if (!strings)
118
  {
119
    backtrace_symbols_fd(addrs, n, fileno(stderr));
120
  }
121
#endif
122
}
123
#endif
124
125
629.2.7 by Monty Taylor
Fixed a couple of memory buffer size issues.
126
void  print_stacktrace(unsigned char* stack_bottom, size_t thread_stack)
1 by brian
clean slate
127
{
128
#if HAVE_BACKTRACE
129
  backtrace_current_thread();
130
  return;
131
#endif
481 by Brian Aker
Remove all of uchar.
132
  unsigned char** fp;
482 by Brian Aker
Remove uint.
133
  uint32_t frame_count = 0, sigreturn_frame_count;
1 by brian
clean slate
134
135
#ifdef __i386__
136
  __asm __volatile__ ("movl %%ebp,%0"
398.1.6 by Monty Taylor
Removed __alpha__ references.
137
                      :"=r"(fp)
138
                      :"r"(fp));
1 by brian
clean slate
139
#endif
140
#ifdef __x86_64__
141
  __asm __volatile__ ("movq %%rbp,%0"
398.1.6 by Monty Taylor
Removed __alpha__ references.
142
                      :"=r"(fp)
143
                      :"r"(fp));
1 by brian
clean slate
144
#endif
145
  if (!fp)
146
  {
147
    fprintf(stderr, "frame pointer is NULL, did you compile with\n\
148
-fomit-frame-pointer? Aborting backtrace!\n");
149
    return;
150
  }
151
481 by Brian Aker
Remove all of uchar.
152
  if (!stack_bottom || (unsigned char*) stack_bottom > (unsigned char*) &fp)
1 by brian
clean slate
153
  {
1067.4.11 by Nathan Williams
Converted last usage of cmin to std::min.
154
    ulong tmp= min((size_t)0x10000,thread_stack);
1 by brian
clean slate
155
    /* Assume that the stack starts at the previous even 65K */
481 by Brian Aker
Remove all of uchar.
156
    stack_bottom= (unsigned char*) (((ulong) &fp + tmp) &
1 by brian
clean slate
157
			  ~(ulong) 0xFFFF);
77.1.54 by Monty Taylor
More warnings cleanups.
158
    fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", (void *)fp);
1 by brian
clean slate
159
  }
481 by Brian Aker
Remove all of uchar.
160
  if (fp > (unsigned char**) stack_bottom ||
161
      fp < (unsigned char**) stack_bottom - thread_stack)
1 by brian
clean slate
162
  {
163
    fprintf(stderr, "Bogus stack limit or frame pointer,\
632.1.9 by Monty
Cast size_t up to uint64_t to print. Man I really want to fix all of this...
164
 fp=%p, stack_bottom=%p, thread_stack=%"PRIu64", aborting backtrace.\n",
165
	    (void *)fp, (void *)stack_bottom, (uint64_t)thread_stack);
1 by brian
clean slate
166
    return;
167
  }
168
169
  fprintf(stderr, "Stack range sanity check OK, backtrace follows:\n");
170
171
  /* We are 1 frame above signal frame with NPTL and 2 frames above with LT */
172
  sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1;
173
481 by Brian Aker
Remove all of uchar.
174
  while (fp < (unsigned char**) stack_bottom)
1 by brian
clean slate
175
  {
176
#if defined(__i386__) || defined(__x86_64__)
481 by Brian Aker
Remove all of uchar.
177
    unsigned char** new_fp = (unsigned char**)*fp;
1 by brian
clean slate
178
    fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ?
398.1.6 by Monty Taylor
Removed __alpha__ references.
179
            *(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
1 by brian
clean slate
180
#endif /* defined(__386__)  || defined(__x86_64__) */
181
182
    if (new_fp <= fp )
183
    {
184
      fprintf(stderr, "New value of fp=%p failed sanity check,\
77.1.54 by Monty Taylor
More warnings cleanups.
185
 terminating stack trace!\n", (void *)new_fp);
1 by brian
clean slate
186
      goto end;
187
    }
188
    fp = new_fp;
189
    ++frame_count;
190
  }
191
192
  fprintf(stderr, "Stack trace seems successful - bottom reached\n");
193
194
end:
195
  fprintf(stderr,
196
          "Please read http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
197
          "and follow instructions on how to resolve the stack trace.\n"
198
          "Resolved stack trace is much more helpful in diagnosing the\n"
199
          "problem, so please do resolve it\n");
200
}
201
#endif /* TARGET_OS_LINUX */
202
#endif /* HAVE_STACKTRACE */
203
204
/* Produce a core for the thread */
205
206
void write_core(int sig)
207
{
208
  signal(sig, SIG_DFL);
209
#ifdef HAVE_gcov
210
  /*
211
    For GCOV build, crashing will prevent the writing of code coverage
212
    information from this process, causing gcov output to be incomplete.
213
    So we force the writing of coverage information here before terminating.
214
  */
215
  extern void __gcov_flush(void);
216
  __gcov_flush();
217
#endif
218
  pthread_kill(pthread_self(), sig);
219
#if defined(P_MYID) && !defined(SCO)
220
  /* On Solaris, the above kill is not enough */
221
  sigsend(P_PID,P_MYID,sig);
222
#endif
223
}