1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
* Ceph - scalable distributed file system
*
* Copyright (C) 2008-2011 New Dream Network
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software
* Foundation. See file COPYING.
*
*/
#include <errno.h>
#include <iostream>
#include <pthread.h>
#include <sstream>
#include <time.h>
#include "include/assert.h"
#include "common/ceph_context.h"
#include "common/config.h"
#include "common/debug.h"
#include "common/Clock.h"
#include "common/BackTrace.h"
namespace ceph {
static CephContext *g_assert_context = NULL;
/* If you register an assert context, assert() will try to lock the dout
* stream of that context before starting an assert. This is nice because the
* output looks better. Your assert will not be interleaved with other dout
* statements.
*
* However, this is strictly optional and library code currently does not
* register an assert context. The extra complexity of supporting this
* wouldn't really be worth it.
*/
void register_assert_context(CephContext *cct)
{
assert(!g_assert_context);
g_assert_context = cct;
}
void __ceph_assert_fail(const char *assertion, const char *file, int line, const char *func)
{
ostringstream tss;
tss << ceph_clock_now(g_assert_context);
char buf[8096];
BackTrace *bt = new BackTrace(1);
snprintf(buf, sizeof(buf),
"%s: In function '%s' thread %llx time %s\n"
"%s: %d: FAILED assert(%s)\n",
file, func, (unsigned long long)pthread_self(), tss.str().c_str(),
file, line, assertion);
dout_emergency(buf);
// TODO: get rid of this memory allocation.
ostringstream oss;
bt->print(oss);
dout_emergency(oss.str());
dout_emergency(" NOTE: a copy of the executable, or `objdump -rdS <executable>` "
"is needed to interpret this.\n");
if (g_assert_context) {
lderr(g_assert_context) << buf << std::endl;
bt->print(*_dout);
*_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
<< "is needed to interpret this.\n" << dendl;
g_assert_context->_log->dump_recent();
}
throw FailedAssertion(bt);
}
void __ceph_assert_warn(const char *assertion, const char *file,
int line, const char *func)
{
char buf[8096];
snprintf(buf, sizeof(buf),
"WARNING: assert(%s) at: %s: %d: %s()\n",
assertion, file, line, func);
dout_emergency(buf);
}
}
|