xref: /4.0.0/forestdb/utils/debug.cc (revision bda6f426)
1#include "debug.h"
2#include <stdio.h>
3#include <stdlib.h>
4#include <stdint.h>
5#include "time_utils.h"
6#if !defined(WIN32) && !defined(_WIN32)
7#include <sys/wait.h>
8#include <unistd.h>
9#include <execinfo.h>
10#endif // !defined(WIN32) && !defined(_WIN32)
11
12#define N_DBG_SWITCH (256)
13
14static uint8_t _global_dbg_switch[N_DBG_SWITCH];
15static void* _global_dbg_addr[N_DBG_SWITCH];
16static uint64_t _global_dbg_uint64_t[N_DBG_SWITCH];
17
18// LCOV_EXCL_START
19void _dbg_sw_set(int n)
20{
21    _global_dbg_switch[n] = 1;
22}
23
24void _dbg_sw_clear(int n)
25{
26    _global_dbg_switch[n] = 0;
27}
28
29void _dbg_set_addr(int n, void *addr)
30{
31    _global_dbg_addr[n] = addr;
32}
33
34void * _dbg_get_addr(int n)
35{
36    return _global_dbg_addr[n];
37}
38
39void _dbg_set_uint64_t(int n, uint64_t val)
40{
41    _global_dbg_uint64_t[n] = val;
42}
43
44uint64_t _dbg_get_uint64_t(int n)
45{
46    return _global_dbg_uint64_t[n];
47}
48
49int _dbg_is_sw_set(int n)
50{
51    return _global_dbg_switch[n];
52}
53
54void dump_backtraces() {
55#ifdef __linux__
56    char my_pid[16];
57    char proc_name[512];
58    sprintf(my_pid, "--pid=%d", getpid());
59    proc_name[readlink("/proc/self/exe", proc_name, 511)] = '\0';
60    printf("Dumping backtrace for %s pid=%s..\n", proc_name, my_pid);
61    int gdb_pid = fork();
62    if (!gdb_pid) { // child process...
63        printf("Running gdb backtrace for %s pid=%s\n", proc_name, my_pid);
64        execlp("gdb", "gdb", "--batch", "-n",
65               "-ex", "thread apply all bt 8",
66               proc_name, my_pid, NULL);
67        abort(); /* If gdb failed to start */
68    } else {
69        int ret_stat;
70        waitpid(gdb_pid, &ret_stat, 0);
71        if (!ret_stat) {
72            fprintf(stderr, "\ngdb dumping successful\n");
73        } else {
74            fprintf(stderr, "\ngdb backtracing incomplete\n");
75        }
76    }
77#elif !defined(WIN32) && !defined(_WIN32)
78    void *callstack[10];
79    char **backtrace_buf;
80    int frames = backtrace(callstack, 10);
81    backtrace_buf = backtrace_symbols(callstack, frames);
82    if (backtrace_buf) {
83        for (int i = 0; i < frames; ++i) {
84            fprintf(stderr, "%d : %s\n", i, backtrace_buf[i]);
85        } // (no need to free memory as process is crashing)
86    }
87#endif // __linux__ or WIN32 || _WIN32
88}
89
90void _dbg_assert(int line, const char *file, uint64_t val, uint64_t expected) {
91    char *hang_process;
92     fprintf(stderr, "Assertion in %p != %p in %s:%d\n",
93            (void *)val, (void *)expected, file, line);
94
95     dump_backtraces(); // try to dump backtraces, for linux use gdb
96
97     hang_process = getenv("HANG_ON_ASSERTION");
98     if (hang_process) {
99         fprintf(stderr, "Hanging process...");
100         fprintf(stderr, "\n");
101         while (1) {
102             usleep(1000);
103         }
104     }
105}
106// LCOV_EXCL_STOP
107
108