Qt 4.8
Functions | Variables
qcrashhandler.cpp File Reference
#include "qplatformdefs.h"
#include "private/qcrashhandler_p.h"
#include "qbytearray.h"
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>

Go to the source code of this file.

Functions

static bool backtrace_command (FILE *outb, const char *format,...)
 
static void init_backtrace (char **argv, int argc)
 
static void print_backtrace (FILE *outb)
 
void qt_signal_handler (int sig)
 

Variables

static char * globalProgName = NULL
 

Function Documentation

◆ backtrace_command()

static bool backtrace_command ( FILE *  outb,
const char *  format,
  ... 
)
static

Definition at line 114 of file qcrashhandler.cpp.

Referenced by print_backtrace().

115 {
116 
117  bool ret = false;
118  char buffer[50];
119 
120  /*
121  * Please note that vsnprintf() is not ASync safe (ie. cannot safely
122  * be used from a signal handler.) If this proves to be a problem
123  * then the cmd string can be built by more basic functions such as
124  * strcpy, strcat, and a home-made integer-to-ascii function.
125  */
126  va_list args;
127  char cmd[512];
128  va_start(args, format);
129  qvsnprintf(cmd, 512, format, args);
130  va_end(args);
131 
132  char *foo = cmd;
133 #if 0
134  foo = "echo hi";
135 #endif
136  if(FILE *inb = popen(foo, "r")) {
137  while(!feof(inb)) {
138  int len = fread(buffer, 1, sizeof(buffer), inb);
139  if(!len)
140  break;
141  if(!ret) {
142  fwrite("Output from ", 1, strlen("Output from "), outb);
143  strtok(cmd, " ");
144  fwrite(cmd, 1, strlen(cmd), outb);
145  fwrite("\n", 1, 1, outb);
146  ret = true;
147  }
148  fwrite(buffer, 1, len, outb);
149  }
150  fclose(inb);
151  }
152  return ret;
153 }
int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap)
A portable vsnprintf() function.
Definition: qvsnprintf.cpp:78

◆ init_backtrace()

static void init_backtrace ( char **  argv,
int  argc 
)
static

Definition at line 155 of file qcrashhandler.cpp.

Referenced by QSegfaultHandler::initialize().

156 {
157  if(argc >= 1)
158  globalProgName = argv[0];
159 }
static char * globalProgName

◆ print_backtrace()

static void print_backtrace ( FILE *  outb)
static

Definition at line 161 of file qcrashhandler.cpp.

Referenced by qt_signal_handler().

162 {
163  /*
164  * In general dbx seems to do a better job than gdb.
165  *
166  * Different dbx implementations require different flags/commands.
167  */
168 #if defined(Q_OS_AIX)
169  if(backtrace_command(outb, "dbx -a %d 2>/dev/null <<EOF\n"
170  "where\n"
171  "detach\n"
172  "EOF\n",
173  (int)getpid()))
174  return;
175  if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
176  "set prompt\n"
177  "where\n"
178  "detach\n"
179  "quit\n"
180  "EOF\n",
181  globalProgName, (int)getpid()))
182  return;
183 #elif defined(Q_OS_FREEBSD)
184  /*
185  * FreeBSD insists on sending a SIGSTOP to the process we
186  * attach to, so we let the debugger send a SIGCONT to that
187  * process after we have detached.
188  */
189  if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
190  "set prompt\n"
191  "where\n"
192  "detach\n"
193  "shell kill -CONT %d\n"
194  "quit\n"
195  "EOF\n",
196  globalProgName, (int)getpid(), (int)getpid()))
197  return;
198 #elif defined(Q_OS_HPUX)
199  /*
200  * HP decided to call their debugger xdb.
201  *
202  * This does not seem to work properly yet. The debugger says
203  * "Note: Stack traces may not be possible until you are
204  * stopped in user code." on HP-UX 09.01
205  *
206  * -L = line-oriented interface.
207  * "T [depth]" gives a stacktrace with local variables.
208  * The final "y" is confirmation to the quit command.
209  */
210  if(backtrace_command(outb, "xdb -P %d -L %s 2>&1 <<EOF\n"
211  "T 50\n"
212  "q\ny\n"
213  "EOF\n",
214  (int)getpid(), globalProgName))
215  return;
216  if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
217  "set prompt\n"
218  "where\n"
219  "detach\n"
220  "quit\n"
221  "EOF\n",
222  globalProgName, (int)getpid()))
223  return;
224 #elif defined(Q_OS_IRIX)
225  /*
226  * "set $page=0" drops hold mode
227  * "dump ." displays the contents of the variables
228  */
229  if(backtrace_command(outb, "dbx -p %d 2>/dev/null <<EOF\n"
230  "set \\$page=0\n"
231  "where\n"
232 # if !defined(__GNUC__)
233  /* gcc does not generate this information */
234  "dump .\n"
235 # endif
236  "detach\n"
237  "EOF\n",
238  (int)getpid()))
239  return;
240 
241 # if defined(USE_LIBEXC)
242  if(trace_back_stack_and_print())
243  return;
244 # endif
245  if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
246  "set prompt\n"
247  "where\n"
248  "echo ---\\n\n"
249  "frame 5\n" /* Skip signal handler frames */
250  "set \\$x = 50\n"
251  "while (\\$x)\n" /* Print local variables for each frame */
252  "info locals\n"
253  "up\n"
254  "set \\$x--\n"
255  "end\n"
256  "echo ---\\n\n"
257  "detach\n"
258  "quit\n"
259  "EOF\n",
260  globalProgName, (int)getpid()))
261  return;
262 #elif defined(Q_OS_OSF)
263  if(backtrace_command(outb, "dbx -pid %d %s 2>/dev/null <<EOF\n"
264  "where\n"
265  "detach\n"
266  "quit\n"
267  "EOF\n",
268  (int)getpid(), globalProgName))
269  return;
270  if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
271  "set prompt\n"
272  "where\n"
273  "detach\n"
274  "quit\n"
275  "EOF\n",
276  globalProgName, (int)getpid()))
277  return;
278 #elif defined(Q_OS_SCO)
279  /*
280  * SCO OpenServer dbx is like a catch-22. The 'detach' command
281  * depends on whether ptrace(S) support detaching or not. If it
282  * is supported then 'detach' must be used, otherwise the process
283  * will be killed upon dbx exit. If it isn't supported then 'detach'
284  * will cause the process to be killed. We do not want it to be
285  * killed.
286  *
287  * Out of two evils, the omission of 'detach' was chosen because
288  * it worked on our system.
289  */
290  if(backtrace_command(outb, "dbx %s %d 2>/dev/null <<EOF\n"
291  "where\n"
292  "quit\nEOF\n",
293  globalProgName, (int)getpid()))
294  return;
295  if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
296  "set prompt\n"
297  "where\n"
298  "detach\n"
299  "quit\n"
300  "EOF\n",
301  globalProgName, (int)getpid()))
302  return;
303 #elif defined(Q_OS_SOLARIS)
304  if(backtrace_command(outb, "dbx %s %d 2>/dev/null <<EOF\n"
305  "where\n"
306  "detach\n"
307  "EOF\n",
308  globalProgName, (int)getpid()))
309  return;
310  if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
311  "set prompt\n"
312  "where\n"
313  "echo ---\\n\n"
314  "frame 5\n" /* Skip signal handler frames */
315  "set \\$x = 50\n"
316  "while (\\$x)\n" /* Print local variables for each frame */
317  "info locals\n"
318  "up\n"
319  "set \\$x--\n"
320  "end\n"
321  "echo ---\\n\n"
322  "detach\n"
323  "quit\n"
324  "EOF\n",
325  globalProgName, (int)getpid()))
326  return;
327  if(backtrace_command(outb, "/usr/proc/bin/pstack %d",
328  (int)getpid()))
329  return;
330  /*
331  * Other Unices (AIX, HPUX, SCO) also have adb, but
332  * they seem unable to attach to a running process.)
333  */
334  if(backtrace_command(outb, "adb %s 2>&1 <<EOF\n"
335  "0t%d:A\n" /* Attach to pid */
336  "\\$c\n" /* print stacktrace */
337  ":R\n" /* Detach */
338  "\\$q\n" /* Quit */
339  "EOF\n",
340  globalProgName, (int)getpid()))
341  return;
342 #elif defined(Q_OS_INTEGRITY)
343  /* abort */
344  CheckSuccess(Failure);
345 #else /* All other platforms */
346  /*
347  * TODO: SCO/UnixWare 7 must be something like (not tested)
348  * debug -i c <pid> <<EOF\nstack -f 4\nquit\nEOF\n
349  */
350 # if !defined(__GNUC__)
351  if(backtrace_command(outb, "dbx %s %d 2>/dev/null <<EOF\n"
352  "where\n"
353  "detach\n"
354  "EOF\n",
355  globalProgName, (int)getpid()))
356  return;
357 # endif
358  if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
359  "set prompt\n"
360  "where\n"
361 #if 0
362  "echo ---\\n\n"
363  "frame 4\n"
364  "set \\$x = 50\n"
365  "while (\\$x)\n"
366  "info locals\n"
367  "up\n"
368  "set \\$x--\n"
369  "end\n"
370  "echo ---\\n\n"
371 #endif
372  "detach\n"
373  "quit\n"
374  "EOF\n",
375  globalProgName, (int)getpid()))
376  return;
377 #endif
378  const char debug_err[] = "No debugger found\n";
379  fwrite(debug_err, strlen(debug_err), 1, outb);
380 }
static char * globalProgName
static bool backtrace_command(FILE *outb, const char *format,...)

◆ qt_signal_handler()

void qt_signal_handler ( int  sig)

Definition at line 385 of file qcrashhandler.cpp.

386 {
387  signal(sig, SIG_DFL);
389  (*QSegfaultHandler::callback)();
390  _exit(1);
391  }
392  FILE *outb = stderr;
393  if(char *crash_loc = ::getenv("QT_CRASH_OUTPUT")) {
394  if(FILE *new_outb = fopen(crash_loc, "w")) {
395  fprintf(stderr, "Crash (backtrace written to %s)!!!\n", crash_loc);
396  outb = new_outb;
397  }
398  } else {
399  fprintf(outb, "Crash!!!\n");
400  }
401  print_backtrace(outb);
402  if(outb != stderr)
403  fclose(outb);
404  _exit(1);
405 }
static QtCrashHandler callback
static void print_backtrace(FILE *outb)

Variable Documentation

◆ globalProgName

char* globalProgName = NULL
static

Definition at line 113 of file qcrashhandler.cpp.