]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/assert.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / common / assert.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2008-2011 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #include "BackTrace.h"
16 #include "common/ceph_context.h"
17 #include "common/config.h"
18 #include "common/debug.h"
19 #include "common/Clock.h"
20 #include "include/assert.h"
21
22 #include <errno.h>
23 #include <iostream>
24 #include <pthread.h>
25 #include <sstream>
26 #include <time.h>
27
28 namespace ceph {
29 static CephContext *g_assert_context = NULL;
30
31 /* If you register an assert context, assert() will try to lock the dout
32 * stream of that context before starting an assert. This is nice because the
33 * output looks better. Your assert will not be interleaved with other dout
34 * statements.
35 *
36 * However, this is strictly optional and library code currently does not
37 * register an assert context. The extra complexity of supporting this
38 * wouldn't really be worth it.
39 */
40 void register_assert_context(CephContext *cct)
41 {
42 assert(!g_assert_context);
43 g_assert_context = cct;
44 }
45
46 void __ceph_assert_fail(const char *assertion, const char *file, int line,
47 const char *func)
48 {
49 ostringstream tss;
50 tss << ceph_clock_now();
51
52 char buf[8096];
53 snprintf(buf, sizeof(buf),
54 "%s: In function '%s' thread %llx time %s\n"
55 "%s: %d: FAILED assert(%s)\n",
56 file, func, (unsigned long long)pthread_self(), tss.str().c_str(),
57 file, line, assertion);
58 dout_emergency(buf);
59
60 // TODO: get rid of this memory allocation.
61 ostringstream oss;
62 oss << BackTrace(1);
63 dout_emergency(oss.str());
64
65 dout_emergency(" NOTE: a copy of the executable, or `objdump -rdS <executable>` "
66 "is needed to interpret this.\n");
67
68 if (g_assert_context) {
69 lderr(g_assert_context) << buf << std::endl;
70 *_dout << oss.str();
71 *_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
72 << "is needed to interpret this.\n" << dendl;
73
74 g_assert_context->_log->dump_recent();
75 }
76
77 abort();
78 }
79
80 void __ceph_assertf_fail(const char *assertion, const char *file, int line,
81 const char *func, const char* msg, ...)
82 {
83 ostringstream tss;
84 tss << ceph_clock_now();
85
86 class BufAppender {
87 public:
88 BufAppender(char* buf, int size) : bufptr(buf), remaining(size) {
89 }
90
91 void printf(const char * format, ...) {
92 va_list args;
93 va_start(args, format);
94 this->vprintf(format, args);
95 va_end(args);
96 }
97
98 void vprintf(const char * format, va_list args) {
99 int n = vsnprintf(bufptr, remaining, format, args);
100 if (n >= 0) {
101 if (n < remaining) {
102 remaining -= n;
103 bufptr += n;
104 } else {
105 remaining = 0;
106 }
107 }
108 }
109
110 private:
111 char* bufptr;
112 int remaining;
113 };
114
115 char buf[8096];
116 BufAppender ba(buf, sizeof(buf));
117 BackTrace *bt = new BackTrace(1);
118 ba.printf("%s: In function '%s' thread %llx time %s\n"
119 "%s: %d: FAILED assert(%s)\n",
120 file, func, (unsigned long long)pthread_self(), tss.str().c_str(),
121 file, line, assertion);
122 ba.printf("Assertion details: ");
123 va_list args;
124 va_start(args, msg);
125 ba.vprintf(msg, args);
126 va_end(args);
127 ba.printf("\n");
128 dout_emergency(buf);
129
130 // TODO: get rid of this memory allocation.
131 ostringstream oss;
132 oss << *bt;
133 dout_emergency(oss.str());
134
135 dout_emergency(" NOTE: a copy of the executable, or `objdump -rdS <executable>` "
136 "is needed to interpret this.\n");
137
138 if (g_assert_context) {
139 lderr(g_assert_context) << buf << std::endl;
140 *_dout << oss.str();
141 *_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
142 << "is needed to interpret this.\n" << dendl;
143
144 g_assert_context->_log->dump_recent();
145 }
146
147 abort();
148 }
149
150 void __ceph_assert_warn(const char *assertion, const char *file,
151 int line, const char *func)
152 {
153 char buf[8096];
154 snprintf(buf, sizeof(buf),
155 "WARNING: assert(%s) at: %s: %d: %s()\n",
156 assertion, file, line, func);
157 dout_emergency(buf);
158 }
159 }