~ubuntu-branches/ubuntu/precise/mysql-5.5/precise-201203300109

« back to all changes in this revision

Viewing changes to mysys/stacktrace.c

  • Committer: Package Import Robot
  • Author(s): Clint Byrum
  • Date: 2012-02-14 23:59:22 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20120214235922-cux5uek1e5l0hje9
Tags: 5.5.20-0ubuntu1
* New upstream release.
* d/mysql-server-5.5.mysql.upstart: Fix stop on to make sure mysql is
  fully stopped before shutdown commences. (LP: #688541) Also simplify
  start on as it is redundant.
* d/control: Depend on upstart version which has apparmor profile load
  script to prevent failure on upgrade from lucid to precise.
  (LP: #907465)
* d/apparmor-profile: need to allow /run since that is the true path
  of /var/run files. (LP: #917542)
* d/control: mysql-server-5.5 has files in it that used to be owned
  by libmysqlclient-dev, so it must break/replace it. (LP: #912487)
* d/rules, d/control: 5.5.20 Fixes segfault on tests with gcc 4.6,
  change compiler back to system default.
* d/rules: Turn off embedded libedit/readline.(Closes: #659566)

Show diffs side-by-side

added added

removed removed

Lines of Context:
52
52
 
53
53
static void print_buffer(char *buffer, size_t count)
54
54
{
 
55
  const char s[]= " ";
55
56
  for (; count && *buffer; --count)
56
57
  {
57
 
    int c= (int) *buffer++;
58
 
    fputc(isprint(c) ? c : ' ', stderr);
 
58
    my_write_stderr(isprint(*buffer) ? buffer : s, 1);
 
59
    ++buffer;
59
60
  }
60
61
}
61
62
 
119
120
 
120
121
  /* Output a new line if something was printed. */
121
122
  if (total != (size_t) max_len)
122
 
    fputc('\n', stderr);
 
123
    my_safe_printf_stderr("%s", "\n");
123
124
 
124
125
  if (nbytes == -1)
125
 
    fprintf(stderr, "Can't read from address %p: %m.\n", addr);
 
126
    my_safe_printf_stderr("Can't read from address %p\n", addr);
126
127
 
127
128
  close(fd);
128
129
 
144
145
 
145
146
  if (!PTR_SANE(val))
146
147
  {
147
 
    fprintf(stderr, "is an invalid pointer\n");
 
148
    my_safe_printf_stderr("%s", "is an invalid pointer\n");
148
149
    return;
149
150
  }
150
151
 
151
152
  for (; max_len && PTR_SANE(val) && *val; --max_len)
152
 
    fputc(*val++, stderr);
153
 
  fputc('\n', stderr);
 
153
    my_write_stderr((val++), 1);
 
154
  my_safe_printf_stderr("%s", "\n");
154
155
}
155
156
 
156
157
#if defined(HAVE_PRINTSTACK)
162
163
                         ulong thread_stack __attribute__((unused)))
163
164
{
164
165
  if (printstack(fileno(stderr)) == -1)
165
 
    fprintf(stderr, "Error when traversing the stack, stack appears corrupt.\n");
 
166
    my_safe_printf_stderr("%s",
 
167
      "Error when traversing the stack, stack appears corrupt.\n");
166
168
  else
167
 
    fprintf(stderr,
168
 
            "Please read "
169
 
            "http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
170
 
            "and follow instructions on how to resolve the stack trace.\n"
171
 
            "Resolved stack trace is much more helpful in diagnosing the\n"
172
 
            "problem, so please do resolve it\n");
 
169
    my_safe_printf_stderr("%s"
 
170
      "Please read "
 
171
      "http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
 
172
      "and follow instructions on how to resolve the stack trace.\n"
 
173
      "Resolved stack trace is much more helpful in diagnosing the\n"
 
174
      "problem, so please do resolve it\n");
173
175
}
174
176
 
175
177
#elif HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD)
207
209
    }
208
210
 
209
211
    if (demangled)
210
 
      fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end);
 
212
      my_safe_printf_stderr("%s(%s+%s\n", addrs[i], demangled, end);
211
213
    else
212
 
      fprintf(stderr, "%s\n", addrs[i]);
 
214
      my_safe_printf_stderr("%s\n", addrs[i]);
213
215
  }
214
216
}
215
217
 
220
222
  void *addrs[128];
221
223
  char **strings= NULL;
222
224
  int n = backtrace(addrs, array_elements(addrs));
223
 
  fprintf(stderr, "stack_bottom = %p thread_stack 0x%lx\n",
224
 
          stack_bottom, thread_stack);
 
225
  my_safe_printf_stderr("stack_bottom = %p thread_stack 0x%lx\n",
 
226
                        stack_bottom, thread_stack);
225
227
#if BACKTRACE_DEMANGLE
226
228
  if ((strings= backtrace_symbols(addrs, n)))
227
229
  {
314
316
#endif
315
317
  if (!fp)
316
318
  {
317
 
    fprintf(stderr, "frame pointer is NULL, did you compile with\n\
318
 
-fomit-frame-pointer? Aborting backtrace!\n");
 
319
    my_safe_printf_stderr("%s",
 
320
      "frame pointer is NULL, did you compile with\n"
 
321
      "-fomit-frame-pointer? Aborting backtrace!\n");
319
322
    return;
320
323
  }
321
324
 
323
326
  {
324
327
    ulong tmp= min(0x10000,thread_stack);
325
328
    /* Assume that the stack starts at the previous even 65K */
326
 
    stack_bottom= (uchar*) (((ulong) &fp + tmp) &
327
 
                          ~(ulong) 0xFFFF);
328
 
    fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", fp);
 
329
    stack_bottom= (uchar*) (((ulong) &fp + tmp) & ~(ulong) 0xFFFF);
 
330
    my_safe_printf_stderr("Cannot determine thread, fp=%p, "
 
331
                          "backtrace may not be correct.\n", fp);
329
332
  }
330
333
  if (fp > (uchar**) stack_bottom ||
331
334
      fp < (uchar**) stack_bottom - thread_stack)
332
335
  {
333
 
    fprintf(stderr, "Bogus stack limit or frame pointer,\
334
 
 fp=%p, stack_bottom=%p, thread_stack=%ld, aborting backtrace.\n",
335
 
            fp, stack_bottom, thread_stack);
 
336
    my_safe_printf_stderr("Bogus stack limit or frame pointer, "
 
337
                          "fp=%p, stack_bottom=%p, thread_stack=%ld, "
 
338
                          "aborting backtrace.\n",
 
339
                          fp, stack_bottom, thread_stack);
336
340
    return;
337
341
  }
338
342
 
339
 
  fprintf(stderr, "Stack range sanity check OK, backtrace follows:\n");
 
343
  my_safe_printf_stderr("%s",
 
344
    "Stack range sanity check OK, backtrace follows:\n");
340
345
#if defined(__alpha__) && defined(__GNUC__)
341
 
  fprintf(stderr, "Warning: Alpha stacks are difficult -\
342
 
 will be taking some wild guesses, stack trace may be incorrect or \
343
 
 terminate abruptly\n");
 
346
  my_safe_printf_stderr("%s",
 
347
    "Warning: Alpha stacks are difficult -"
 
348
    "will be taking some wild guesses, stack trace may be incorrect or "
 
349
    "terminate abruptly\n");
 
350
 
344
351
  /* On Alpha, we need to get pc */
345
352
  __asm __volatile__ ("bsr %0, do_next; do_next: "
346
353
                      :"=r"(pc)
354
361
  {
355
362
#if defined(__i386__) || defined(__x86_64__)
356
363
    uchar** new_fp = (uchar**)*fp;
357
 
    fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ?
358
 
            *(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
 
364
    my_safe_printf_stderr("%p\n",
 
365
                          frame_count == sigreturn_frame_count ?
 
366
                          *(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
359
367
#endif /* defined(__386__)  || defined(__x86_64__) */
360
368
 
361
369
#if defined(__alpha__) && defined(__GNUC__)
369
377
    {
370
378
      pc = find_prev_pc(pc, fp);
371
379
      if (pc)
372
 
        fprintf(stderr, "%p\n", pc);
 
380
        my_safe_printf_stderr("%p\n", pc);
373
381
      else
374
382
      {
375
 
        fprintf(stderr, "Not smart enough to deal with the rest\
376
 
 of this stack\n");
 
383
        my_safe_printf_stderr("%s",
 
384
          "Not smart enough to deal with the rest of this stack\n");
377
385
        goto end;
378
386
      }
379
387
    }
380
388
    else
381
389
    {
382
 
      fprintf(stderr, "Not smart enough to deal with the rest of this stack\n");
 
390
      my_safe_printf_stderr("%s",
 
391
        "Not smart enough to deal with the rest of this stack\n");
383
392
      goto end;
384
393
    }
385
394
#endif /* defined(__alpha__) && defined(__GNUC__) */
386
395
    if (new_fp <= fp )
387
396
    {
388
 
      fprintf(stderr, "New value of fp=%p failed sanity check,\
389
 
 terminating stack trace!\n", new_fp);
 
397
      my_safe_printf_stderr("New value of fp=%p failed sanity check, "
 
398
                            "terminating stack trace!\n", new_fp);
390
399
      goto end;
391
400
    }
392
401
    fp = new_fp;
393
402
    ++frame_count;
394
403
  }
395
 
 
396
 
  fprintf(stderr, "Stack trace seems successful - bottom reached\n");
 
404
  my_safe_printf_stderr("%s",
 
405
                        "Stack trace seems successful - bottom reached\n");
397
406
 
398
407
end:
399
 
  fprintf(stderr,
400
 
          "Please read http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
401
 
          "and follow instructions on how to resolve the stack trace.\n"
402
 
          "Resolved stack trace is much more helpful in diagnosing the\n"
403
 
          "problem, so please do resolve it\n");
 
408
  my_safe_printf_stderr("%s",
 
409
    "Please read "
 
410
    "http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
 
411
    "and follow instructions on how to resolve the stack trace.\n"
 
412
    "Resolved stack trace is much more helpful in diagnosing the\n"
 
413
    "problem, so please do resolve it\n");
404
414
}
405
415
#endif /* TARGET_OS_LINUX */
406
416
#endif /* HAVE_STACKTRACE */
618
628
      &(package.sym));
619
629
    have_source= SymGetLineFromAddr64(hProcess, addr, &line_offset, &line);
620
630
 
621
 
    fprintf(stderr, "%p    ", addr);
 
631
    my_safe_printf_stderr("%p    ", addr);
622
632
    if(have_module)
623
633
    {
624
634
      char *base_image_name= strrchr(module.ImageName, '\\');
626
636
        base_image_name++;
627
637
      else
628
638
        base_image_name= module.ImageName;
629
 
      fprintf(stderr, "%s!", base_image_name);
 
639
      my_safe_printf_stderr("%s!", base_image_name);
630
640
    }
631
641
    if(have_symbol)
632
 
      fprintf(stderr, "%s()", package.sym.Name);
 
642
      my_safe_printf_stderr("%s()", package.sym.Name);
 
643
 
633
644
    else if(have_module)
634
 
      fprintf(stderr, "???");
 
645
      my_safe_printf_stderr("%s", "???");
635
646
 
636
647
    if(have_source)
637
648
    {
640
651
        base_file_name++;
641
652
      else
642
653
        base_file_name= line.FileName;
643
 
      fprintf(stderr,"[%s:%u]", base_file_name, line.LineNumber);
 
654
      my_safe_printf_stderr("[%s:%u]",
 
655
                            base_file_name, line.LineNumber);
644
656
    }
645
 
    fprintf(stderr, "\n");
 
657
    my_safe_printf_stderr("%s", "\n");
646
658
  }
647
 
  fflush(stderr);
648
659
}
649
660
 
650
661
 
681
692
    if(MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
682
693
      hFile, MiniDumpNormal, &info, 0, 0))
683
694
    {
684
 
      fprintf(stderr, "Minidump written to %s\n",
685
 
        _fullpath(path, dump_fname, sizeof(path)) ? path : dump_fname);
 
695
      my_safe_printf_stderr("Minidump written to %s\n",
 
696
                            _fullpath(path, dump_fname, sizeof(path)) ?
 
697
                            path : dump_fname);
686
698
    }
687
699
    else
688
700
    {
689
 
      fprintf(stderr,"MiniDumpWriteDump() failed, last error %u\n",
690
 
        GetLastError());
 
701
      my_safe_printf_stderr("MiniDumpWriteDump() failed, last error %u\n",
 
702
                            (uint) GetLastError());
691
703
    }
692
704
    CloseHandle(hFile);
693
705
  }
694
706
  else
695
707
  {
696
 
    fprintf(stderr, "CreateFile(%s) failed, last error %u\n", dump_fname,
697
 
      GetLastError());
 
708
    my_safe_printf_stderr("CreateFile(%s) failed, last error %u\n",
 
709
                          dump_fname, (uint) GetLastError());
698
710
  }
699
 
  fflush(stderr);
700
711
}
701
712
 
702
713
 
704
715
{
705
716
  __try
706
717
  {
707
 
    fprintf(stderr, "%.*s\n", len, val);
 
718
    my_write_stderr(val, len);
708
719
  }
709
720
  __except(EXCEPTION_EXECUTE_HANDLER)
710
721
  {
711
 
    fprintf(stderr, "is an invalid string pointer\n");
 
722
    my_safe_printf_stderr("%s", "is an invalid string pointer\n");
712
723
  }
713
724
}
714
725
#endif /*__WIN__*/
 
726
 
 
727
 
 
728
#ifdef __WIN__
 
729
size_t my_write_stderr(const void *buf, size_t count)
 
730
{
 
731
  DWORD bytes_written;
 
732
  SetFilePointer(GetStdHandle(STD_ERROR_HANDLE), 0, NULL, FILE_END);
 
733
  WriteFile(GetStdHandle(STD_ERROR_HANDLE), buf, count, &bytes_written, NULL);
 
734
  return bytes_written;
 
735
}
 
736
#else
 
737
size_t my_write_stderr(const void *buf, size_t count)
 
738
{
 
739
  return (size_t) write(STDERR_FILENO, buf, count);
 
740
}
 
741
#endif
 
742
 
 
743
 
 
744
static const char digits[]= "0123456789abcdef";
 
745
 
 
746
char *my_safe_utoa(int base, ulonglong val, char *buf)
 
747
{
 
748
  *buf--= 0;
 
749
  do {
 
750
    *buf--= digits[val % base];
 
751
  } while ((val /= base) != 0);
 
752
  return buf + 1;
 
753
}
 
754
 
 
755
 
 
756
char *my_safe_itoa(int base, longlong val, char *buf)
 
757
{
 
758
  char *orig_buf= buf;
 
759
  const my_bool is_neg= (val < 0);
 
760
  *buf--= 0;
 
761
 
 
762
  if (is_neg)
 
763
    val= -val;
 
764
  if (is_neg && base == 16)
 
765
  {
 
766
    int ix;
 
767
    val-= 1;
 
768
    for (ix= 0; ix < 16; ++ix)
 
769
      buf[-ix]= '0';
 
770
  }
 
771
  
 
772
  do {
 
773
    *buf--= digits[val % base];
 
774
  } while ((val /= base) != 0);
 
775
 
 
776
  if (is_neg && base == 10)
 
777
    *buf--= '-';
 
778
 
 
779
  if (is_neg && base == 16)
 
780
  {
 
781
    int ix;
 
782
    buf= orig_buf - 1;
 
783
    for (ix= 0; ix < 16; ++ix, --buf)
 
784
    {
 
785
      switch (*buf)
 
786
      {
 
787
      case '0': *buf= 'f'; break;
 
788
      case '1': *buf= 'e'; break;
 
789
      case '2': *buf= 'd'; break;
 
790
      case '3': *buf= 'c'; break;
 
791
      case '4': *buf= 'b'; break;
 
792
      case '5': *buf= 'a'; break;
 
793
      case '6': *buf= '9'; break;
 
794
      case '7': *buf= '8'; break;
 
795
      case '8': *buf= '7'; break;
 
796
      case '9': *buf= '6'; break;
 
797
      case 'a': *buf= '5'; break;
 
798
      case 'b': *buf= '4'; break;
 
799
      case 'c': *buf= '3'; break;
 
800
      case 'd': *buf= '2'; break;
 
801
      case 'e': *buf= '1'; break;
 
802
      case 'f': *buf= '0'; break;
 
803
      }
 
804
    }
 
805
  }
 
806
  return buf+1;
 
807
}
 
808
 
 
809
 
 
810
static const char *check_longlong(const char *fmt, my_bool *have_longlong)
 
811
{
 
812
  *have_longlong= FALSE;
 
813
  if (*fmt == 'l')
 
814
  {
 
815
    fmt++;
 
816
    if (*fmt != 'l')
 
817
      *have_longlong= (sizeof(long) == sizeof(longlong));
 
818
    else
 
819
    {
 
820
      fmt++;
 
821
      *have_longlong= TRUE;
 
822
    }
 
823
  }
 
824
  return fmt;
 
825
}
 
826
 
 
827
static size_t my_safe_vsnprintf(char *to, size_t size,
 
828
                                const char* format, va_list ap)
 
829
{
 
830
  char *start= to;
 
831
  char *end= start + size - 1;
 
832
  for (; *format; ++format)
 
833
  {
 
834
    my_bool have_longlong = FALSE;
 
835
    if (*format != '%')
 
836
    {
 
837
      if (to == end)                            /* end of buffer */
 
838
        break;
 
839
      *to++= *format;                           /* copy ordinary char */
 
840
      continue;
 
841
    }
 
842
    ++format;                                   /* skip '%' */
 
843
 
 
844
    format= check_longlong(format, &have_longlong);
 
845
 
 
846
    switch (*format)
 
847
    {
 
848
    case 'd':
 
849
    case 'i':
 
850
    case 'u':
 
851
    case 'x':
 
852
    case 'p':
 
853
      {
 
854
        longlong ival= 0;
 
855
        ulonglong uval = 0;
 
856
        if (*format == 'p')
 
857
          have_longlong= (sizeof(void *) == sizeof(longlong));
 
858
        if (have_longlong)
 
859
        {
 
860
          if (*format == 'u')
 
861
            uval= va_arg(ap, ulonglong);
 
862
          else
 
863
            ival= va_arg(ap, longlong);
 
864
        }
 
865
        else
 
866
        {
 
867
          if (*format == 'u')
 
868
            uval= va_arg(ap, unsigned int);
 
869
          else
 
870
            ival= va_arg(ap, int);
 
871
        }
 
872
 
 
873
        {
 
874
          char buff[22];
 
875
          const int base= (*format == 'x' || *format == 'p') ? 16 : 10;
 
876
          char *val_as_str= (*format == 'u') ?
 
877
            my_safe_utoa(base, uval, &buff[sizeof(buff)-1]) :
 
878
            my_safe_itoa(base, ival, &buff[sizeof(buff)-1]);
 
879
 
 
880
          /* Strip off "ffffffff" if we have 'x' format without 'll' */
 
881
          if (*format == 'x' && !have_longlong && ival < 0)
 
882
            val_as_str+= 8;
 
883
 
 
884
          while (*val_as_str && to < end)
 
885
            *to++= *val_as_str++;
 
886
          continue;
 
887
        }
 
888
      }
 
889
    case 's':
 
890
      {
 
891
        const char *val= va_arg(ap, char*);
 
892
        if (!val)
 
893
          val= "(null)";
 
894
        while (*val && to < end)
 
895
          *to++= *val++;
 
896
        continue;
 
897
      }
 
898
    }
 
899
  }
 
900
  *to= 0;
 
901
  return to - start;
 
902
}
 
903
 
 
904
 
 
905
size_t my_safe_snprintf(char* to, size_t n, const char* fmt, ...)
 
906
{
 
907
  size_t result;
 
908
  va_list args;
 
909
  va_start(args,fmt);
 
910
  result= my_safe_vsnprintf(to, n, fmt, args);
 
911
  va_end(args);
 
912
  return result;
 
913
}
 
914
 
 
915
 
 
916
size_t my_safe_printf_stderr(const char* fmt, ...)
 
917
{
 
918
  char to[512];
 
919
  size_t result;
 
920
  va_list args;
 
921
  va_start(args,fmt);
 
922
  result= my_safe_vsnprintf(to, sizeof(to), fmt, args);
 
923
  va_end(args);
 
924
  my_write_stderr(to, result);
 
925
  return result;
 
926
}