]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/assert.cc
update sources to v12.1.0
[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 "common/debug.h"
16
17 namespace ceph {
18 static CephContext *g_assert_context = NULL;
19
20 /* If you register an assert context, assert() will try to lock the dout
21 * stream of that context before starting an assert. This is nice because the
22 * output looks better. Your assert will not be interleaved with other dout
23 * statements.
24 *
25 * However, this is strictly optional and library code currently does not
26 * register an assert context. The extra complexity of supporting this
27 * wouldn't really be worth it.
28 */
29 void register_assert_context(CephContext *cct)
30 {
31 assert(!g_assert_context);
32 g_assert_context = cct;
33 }
34
35 void __ceph_assert_fail(const char *assertion, const char *file, int line,
36 const char *func)
37 {
38 ostringstream tss;
39 tss << ceph_clock_now();
40
41 char buf[8096];
42 snprintf(buf, sizeof(buf),
43 "%s: In function '%s' thread %llx time %s\n"
44 "%s: %d: FAILED assert(%s)\n",
45 file, func, (unsigned long long)pthread_self(), tss.str().c_str(),
46 file, line, assertion);
47 dout_emergency(buf);
48
49 // TODO: get rid of this memory allocation.
50 ostringstream oss;
51 oss << BackTrace(1);
52 dout_emergency(oss.str());
53
54 dout_emergency(" NOTE: a copy of the executable, or `objdump -rdS <executable>` "
55 "is needed to interpret this.\n");
56
57 if (g_assert_context) {
58 lderr(g_assert_context) << buf << std::endl;
59 *_dout << oss.str();
60 *_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
61 << "is needed to interpret this.\n" << dendl;
62
63 g_assert_context->_log->dump_recent();
64 }
65
66 abort();
67 }
68
69 void __ceph_assertf_fail(const char *assertion, const char *file, int line,
70 const char *func, const char* msg, ...)
71 {
72 ostringstream tss;
73 tss << ceph_clock_now();
74
75 class BufAppender {
76 public:
77 BufAppender(char* buf, int size) : bufptr(buf), remaining(size) {
78 }
79
80 void printf(const char * format, ...) {
81 va_list args;
82 va_start(args, format);
83 this->vprintf(format, args);
84 va_end(args);
85 }
86
87 void vprintf(const char * format, va_list args) {
88 int n = vsnprintf(bufptr, remaining, format, args);
89 if (n >= 0) {
90 if (n < remaining) {
91 remaining -= n;
92 bufptr += n;
93 } else {
94 remaining = 0;
95 }
96 }
97 }
98
99 private:
100 char* bufptr;
101 int remaining;
102 };
103
104 char buf[8096];
105 BufAppender ba(buf, sizeof(buf));
106 BackTrace *bt = new BackTrace(1);
107 ba.printf("%s: In function '%s' thread %llx time %s\n"
108 "%s: %d: FAILED assert(%s)\n",
109 file, func, (unsigned long long)pthread_self(), tss.str().c_str(),
110 file, line, assertion);
111 ba.printf("Assertion details: ");
112 va_list args;
113 va_start(args, msg);
114 ba.vprintf(msg, args);
115 va_end(args);
116 ba.printf("\n");
117 dout_emergency(buf);
118
119 // TODO: get rid of this memory allocation.
120 ostringstream oss;
121 oss << *bt;
122 dout_emergency(oss.str());
123
124 dout_emergency(" NOTE: a copy of the executable, or `objdump -rdS <executable>` "
125 "is needed to interpret this.\n");
126
127 if (g_assert_context) {
128 lderr(g_assert_context) << buf << std::endl;
129 *_dout << oss.str();
130 *_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
131 << "is needed to interpret this.\n" << dendl;
132
133 g_assert_context->_log->dump_recent();
134 }
135
136 abort();
137 }
138
139 void __ceph_assert_warn(const char *assertion, const char *file,
140 int line, const char *func)
141 {
142 char buf[8096];
143 snprintf(buf, sizeof(buf),
144 "WARNING: assert(%s) at: %s: %d: %s()\n",
145 assertion, file, line, func);
146 dout_emergency(buf);
147 }
148 }