YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/port/stack_trace.cc
Line
Count
Source (jump to first uncovered line)
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under the BSD-style license found in the
3
//  LICENSE file in the root directory of this source tree. An additional grant
4
//  of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// The following only applies to changes made to this file as part of YugaByte development.
7
//
8
// Portions Copyright (c) YugaByte, Inc.
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
11
// in compliance with the License.  You may obtain a copy of the License at
12
//
13
// http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software distributed under the License
16
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17
// or implied.  See the License for the specific language governing permissions and limitations
18
// under the License.
19
//
20
#include "yb/rocksdb/port/stack_trace.h"
21
22
#if defined(ROCKSDB_LITE) || !(defined(__linux__) || defined(OS_MACOSX)) || \
23
    defined(CYGWIN)
24
25
// noop
26
27
namespace rocksdb {
28
namespace port {
29
void InstallStackTraceHandler() {}
30
void PrintStack(int first_frames_to_skip) {}
31
}  // namespace port
32
}  // namespace rocksdb
33
34
#else
35
36
#include <execinfo.h>
37
#include <signal.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <string.h>
41
#include <unistd.h>
42
#include <cxxabi.h>
43
44
namespace rocksdb {
45
namespace port {
46
47
namespace {
48
49
#ifdef __linux__
50
const char* GetExecutableName() {
51
  static char name[1024];
52
53
  char link[1024];
54
  snprintf(link, sizeof(link), "/proc/%d/exe", getpid());
55
  auto read = readlink(link, name, sizeof(name) - 1);
56
  if (-1 == read) {
57
    return nullptr;
58
  } else {
59
    name[read] = 0;
60
    return name;
61
  }
62
}
63
64
void PrintStackTraceLine(const char* symbol, void* frame) {
65
  static const char* executable = GetExecutableName();
66
  if (symbol) {
67
    fprintf(stderr, "%s ", symbol);
68
  }
69
  if (executable) {
70
    // out source to addr2line, for the address translation
71
    const int kLineMax = 256;
72
    char cmd[kLineMax];
73
    snprintf(cmd, kLineMax, "addr2line %p -e %s -f -C 2>&1", frame, executable);
74
    auto f = popen(cmd, "r");
75
    if (f) {
76
      char line[kLineMax];
77
      while (fgets(line, sizeof(line), f)) {
78
        line[strlen(line) - 1] = 0;  // remove newline
79
        fprintf(stderr, "%s\t", line);
80
      }
81
      pclose(f);
82
    }
83
  } else {
84
    fprintf(stderr, " %p", frame);
85
  }
86
87
  fprintf(stderr, "\n");
88
}
89
#elif defined(OS_MACOSX)
90
91
47
void PrintStackTraceLine(const char* symbol, void* frame) {
92
47
  static int pid = getpid();
93
  // out source to atos, for the address translation
94
47
  const int kLineMax = 256;
95
47
  char cmd[kLineMax];
96
47
  snprintf(cmd, kLineMax, "xcrun atos %p -p %d  2>&1", frame, pid);
97
47
  auto f = popen(cmd, "r");
98
47
  if (f) {
99
23
    char line[kLineMax];
100
46
    while (fgets(line, sizeof(line), f)) {
101
23
      line[strlen(line) - 1] = 0;  // remove newline
102
23
      fprintf(stderr, "%s\t", line);
103
23
    }
104
23
    pclose(f);
105
24
  } else if (symbol) {
106
24
    fprintf(stderr, "%s ", symbol);
107
24
  }
108
109
47
  fprintf(stderr, "\n");
110
47
}
111
112
#endif
113
114
}  // namespace
115
116
2
void PrintStack(int first_frames_to_skip) {
117
2
  const int kMaxFrames = 100;
118
2
  void* frames[kMaxFrames];
119
120
2
  auto num_frames = backtrace(frames, kMaxFrames);
121
2
  auto symbols = backtrace_symbols(frames, num_frames);
122
123
49
  for (int i = first_frames_to_skip; i < num_frames; ++i) {
124
47
    fprintf(stderr, "#%-2d  ", i - first_frames_to_skip);
125
47
    PrintStackTraceLine((symbols != nullptr) ? symbols[i] : nullptr, frames[i]);
126
47
  }
127
2
}
128
129
2
static void StackTraceHandler(int sig) {
130
  // reset to default handler
131
2
  signal(sig, SIG_DFL);
132
2
  fprintf(stderr, "Received signal %d (%s)\n", sig, strsignal(sig));
133
  // skip the top three signal handler related frames
134
2
  PrintStack(3);
135
  // re-signal to default handler (so we still get core dump if needed...)
136
2
  raise(sig);
137
2
}
138
139
563
void InstallStackTraceHandler() {
140
  // just use the plain old signal as it's simple and sufficient
141
  // for this use case
142
563
  signal(SIGILL, StackTraceHandler);
143
563
  signal(SIGSEGV, StackTraceHandler);
144
563
  signal(SIGBUS, StackTraceHandler);
145
563
  signal(SIGABRT, StackTraceHandler);
146
563
}
147
148
}  // namespace port
149
}  // namespace rocksdb
150
151
#endif