Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F68466677
lm_log.cc
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Thu, Jun 27, 12:58
Size
14 KB
Mime Type
text/x-c
Expires
Sat, Jun 29, 12:58 (2 d)
Engine
blob
Format
Raw Data
Handle
18482933
Attached To
rLIBMULTISCALE LibMultiScale
lm_log.cc
View Options
/**
* @file lm_log.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Mon Sep 08 23:40:22 2014
*
* @brief Log/Debug system of LibMultiScale
*
* @section LICENSE
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* LibMultiScale is free software: you can redistribute it and/or modify it
* under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* LibMultiScale is distributed in the hope that it will be useful, but
* WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "action_interface.hh"
#include "factory_multiscale.hh"
#include "lm_common.hh"
#include "lm_globals.hh"
#include <cxxabi.h>
#include <execinfo.h>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <mpi.h>
#include <unistd.h>
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
/* -------------------------------------------------------------------------- */
#define CREATE_SEGFAULT \
if (create_seg_fault) { \
UInt *a = NULL; \
*a = 1; \
}
/* -------------------------------------------------------------------------- */
void
doWait
(
bool
condition
)
{
if
(
!
condition
)
return
;
UInt
pid
=
lm_getpid
();
std
::
cerr
<<
"Proc "
<<
lm_my_proc_id
<<
" Waiting for gdb to attach: pid is "
<<
pid
<<
std
::
endl
;
UInt
a
=
1
;
while
(
a
)
{
};
}
/* -------------------------------------------------------------------------- */
void
doWaitOnFatal
()
{
doWait
(
wait_on_fatal
);
}
/* -------------------------------------------------------------------------- */
void
doWaitAtStartup
()
{
doWait
((
wait_at_startup
!=
UINT_MAX
)
&&
(
lm_my_proc_id
==
wait_at_startup
));
}
/* -------------------------------------------------------------------------- */
std
::
string
exec
(
const
std
::
string
&
cmd
)
{
FILE
*
pipe
=
popen
(
cmd
.
c_str
(),
"r"
);
if
(
!
pipe
)
return
""
;
char
buffer
[
1024
];
std
::
string
result
=
""
;
while
(
!
feof
(
pipe
))
{
if
(
fgets
(
buffer
,
128
,
pipe
)
!=
nullptr
)
result
+=
buffer
;
}
result
=
result
.
substr
(
0
,
result
.
size
()
-
1
);
pclose
(
pipe
);
return
result
;
}
/* -------------------------------------------------------------------------- */
static
inline
std
::
map
<
std
::
string
,
size_t
>
getAddressMap
()
{
std
::
string
me
=
""
;
char
buf
[
1024
];
/* The manpage says it won't null terminate. Let's zero the buffer. */
memset
(
buf
,
0
,
sizeof
(
buf
));
/* Note we use sizeof(buf)-1 since we may need an extra char for NUL. */
if
(
readlink
(
"/proc/self/exe"
,
buf
,
sizeof
(
buf
)
-
1
))
me
=
std
::
string
(
buf
);
// std::cerr << "me = " << me << std::endl;
std
::
ifstream
inmaps
;
std
::
map
<
std
::
string
,
size_t
>
addr_map
;
inmaps
.
open
(
"/proc/self/maps"
);
std
::
string
line
;
while
(
inmaps
.
good
())
{
std
::
getline
(
inmaps
,
line
);
std
::
stringstream
sstr
(
line
);
size_t
first
=
line
.
find
(
'-'
);
std
::
stringstream
sstra
(
line
.
substr
(
0
,
first
));
size_t
addr
;
sstra
>>
std
::
hex
>>
addr
;
std
::
string
lib
;
sstr
>>
lib
;
sstr
>>
lib
;
sstr
>>
lib
;
sstr
>>
lib
;
sstr
>>
lib
;
sstr
>>
lib
;
if
(
lib
!=
""
&&
addr_map
.
find
(
lib
)
==
addr_map
.
end
())
{
addr_map
[
lib
]
=
addr
;
}
}
return
addr_map
;
}
/* -------------------------------------------------------------------------- */
static
inline
LMStackTrace
get_stacktrace
()
{
UInt
max_frames
=
512
;
std
::
vector
<
void
*>
stack_addrs
(
max_frames
);
char
**
stack_strings
;
size_t
stack_depth
=
backtrace
(
stack_addrs
.
data
(),
max_frames
);
stack_strings
=
backtrace_symbols
(
stack_addrs
.
data
(),
stack_depth
);
std
::
list
<
std
::
string
>
stack_trace
;
for
(
UInt
i
=
0
;
i
<
stack_depth
-
2
;
++
i
)
{
stack_trace
.
push_back
(
stack_strings
[
i
]);
}
free
(
stack_strings
);
std
::
map
<
std
::
string
,
size_t
>
addr_map
=
getAddressMap
();
return
LMStackTrace
(
stack_trace
,
addr_map
);
}
/** Print a demangled stack backtrace of the caller function to a string */
inline
std
::
string
print_stacktrace
(
LMStackTrace
stack_trace
,
UInt
max_frames
=
10
)
{
std
::
map
<
std
::
string
,
size_t
>
addr_map
=
getAddressMap
();
auto
stack_list
=
stack_trace
.
stack
;
std
::
vector
<
std
::
string
>
stack
{
std
::
begin
(
stack_list
),
std
::
end
(
stack_list
)};
std
::
stringstream
mesg_stream
;
mesg_stream
<<
"
\n
==== C++ stack trace ====
\n
"
;
int
max
=
std
::
min
<
int
>
(
max_frames
,
stack
.
size
()
-
1
);
for
(
UInt
i
=
max
;
i
>
1
;
i
--
)
{
std
::
string
bt_line
(
stack
[
i
]);
size_t
first
,
second
;
if
((
first
=
bt_line
.
find
(
'('
))
!=
std
::
string
::
npos
&&
(
second
=
bt_line
.
find
(
'+'
))
!=
std
::
string
::
npos
)
{
std
::
string
location
=
bt_line
.
substr
(
0
,
first
);
std
::
string
location_cmd
=
std
::
string
(
"/bin/readlink"
)
+
std
::
string
(
" -f "
)
+
location
;
location
=
exec
(
location_cmd
);
std
::
string
call
=
demangle
(
bt_line
.
substr
(
first
+
1
,
second
-
first
-
1
).
c_str
());
size_t
f
=
bt_line
.
find
(
'['
);
size_t
s
=
bt_line
.
find
(
']'
);
std
::
string
address
=
bt_line
.
substr
(
f
+
1
,
s
-
f
-
1
);
std
::
stringstream
sstra
(
address
);
size_t
addr
;
sstra
>>
std
::
hex
>>
addr
;
// mesg_stream << location << " [" << call << "]";
// std::cerr << "AAAA " << sstra.str() << " " << call << std::endl;
auto
it
=
stack_trace
.
addr_map
.
find
(
location
);
if
(
it
!=
stack_trace
.
addr_map
.
end
())
{
std
::
stringstream
syscom
;
syscom
<<
"/usr/bin/addr2line"
<<
" 0x"
<<
std
::
hex
<<
(
addr
-
it
->
second
)
<<
" -i -e "
<<
location
;
// std::cerr << "AAAA " << syscom.str() << std::endl;
std
::
string
line
=
exec
(
syscom
.
str
());
// std::cerr << "AAAA " << line << std::endl;
std
::
replace
(
line
.
begin
(),
line
.
end
(),
' '
,
':'
);
mesg_stream
<<
line
<<
": "
<<
std
::
endl
;
}
else
{
mesg_stream
<<
location
<<
":0x"
<<
std
::
hex
<<
addr
<<
std
::
endl
;
}
}
else
{
mesg_stream
<<
bt_line
<<
std
::
endl
;
}
}
return
mesg_stream
.
str
();
}
/* -------------------------------------------------------------------------- */
LMStackTrace
::
LMStackTrace
(
std
::
list
<
std
::
string
>
stack
,
std
::
map
<
std
::
string
,
size_t
>
addr_map
)
:
stack
(
stack
),
addr_map
(
addr_map
)
{}
/** Print a demangled stack backtrace of the caller function to a string */
// static inline std::string print_stacktrace2(UInt max_frames = 10) {
// std::string mesg;
// mesg += "\n==== C++ stack trace ==== \n";
// // storage array for stack trace address data
// std::vector<void *> addrlist(max_frames);
// // retrieve current stack addresses
// int addrlen = backtrace(addrlist.data(), addrlist.size());
// if (addrlen == 0) {
// mesg += " <empty, possibly corrupt>\n";
// return mesg;
// }
// addrlist.resize(addrlen);
// // resolve addresses into strings containing "filename(function+address)",
// // this array must be free()-ed
// auto symbollist = backtrace_symbols(addrlist.data(), addrlist.size());
// // iterate over the returned symbol lines. skip the first, it is the
// // address of this function.
// for (UInt i = addrlist.size() - 1; i > 0; i--) {
// char *begin_name = 0, *begin_offset = 0, *end_offset = 0;
// // find parentheses and +address offset surrounding the mangled name:
// // ./module(function+0x15c) [0x8048a6d]
// for (char *p = symbollist[i]; *p; ++p) {
// if (*p == '(')
// begin_name = p;
// else if (*p == '+')
// begin_offset = p;
// else if (*p == ')' && begin_offset) {
// end_offset = p;
// break;
// }
// }
// if (begin_name && begin_offset && end_offset && begin_name <
// begin_offset) {
// *begin_name++ = '\0';
// *begin_offset++ = '\0';
// *end_offset = '\0';
// // mangled name is now in [begin_name, begin_offset) and caller
// // offset in [begin_offset, end_offset). now apply
// // __cxa_demangle():
// int status;
// decltype(auto) ret = abi::__cxa_demangle(begin_name, NULL, NULL,
// &status);
// std::string funcname;
// if (status == 0) {
// funcname = ret;
// free(ret);
// } else
// funcname = begin_name;
// mesg += symbollist[i];
// mesg += " : " + funcname + "+" + begin_offset + "\n";
// } else {
// // couldn't parse the line? print the whole line.
// mesg += symbollist[i];
// mesg += "\n";
// }
// }
// free(symbollist);
// return mesg;
// }
/* -------------------------------------------------------------------------- */
void
lmFatal
(
std
::
stringstream
&
x
,
UInt
line
,
const
std
::
string
&
file
,
const
std
::
string
&
,
const
std
::
string
&
)
{
if
(
!
fatal_loop
)
{
fatal_loop
=
true
;
try
{
auto
&
actions
=
ActionManager
::
getManager
();
current_stage
=
PRE_FATAL
;
actions
.
action
();
}
catch
(...)
{
}
}
std
::
stringstream
sstr
;
sstr
<<
file
<<
":"
<<
line
<<
":FATAL: ("
<<
current_step
<<
")"
<<
"["
<<
lm_my_proc_id
<<
"]:"
<<
x
.
str
()
<<
std
::
endl
;
// (*global_out) << sstr.str();
// (*global_out).flush();
CREATE_SEGFAULT
;
DOWAIT_ON_FATAL
;
throw
LibMultiScaleException
(
sstr
.
str
());
CREATE_SEGFAULT
;
// ::libmultiscale::lm_exit(LM_EXIT_FAILURE);
}
/* -------------------------------------------------------------------------- */
void
lmFatal_rethrow
(
LibMultiScaleException
&
e
,
std
::
stringstream
&
x
,
UInt
line
,
const
std
::
string
&
file
,
const
std
::
string
&
,
const
std
::
string
&
)
{
if
(
!
fatal_loop
)
{
fatal_loop
=
true
;
try
{
auto
&
actions
=
ActionManager
::
getManager
();
current_stage
=
PRE_FATAL
;
actions
.
action
();
}
catch
(...)
{
}
}
std
::
stringstream
sstr
;
sstr
<<
file
<<
":"
<<
line
<<
":FATAL: ("
<<
current_step
<<
")"
<<
"["
<<
lm_my_proc_id
<<
"]:"
<<
x
.
str
()
<<
std
::
endl
;
// (*global_out) << sstr.str();
// (*global_out).flush();
CREATE_SEGFAULT
;
DOWAIT_ON_FATAL
;
throw
LibMultiScaleException
(
e
,
sstr
.
str
());
CREATE_SEGFAULT
;
// ::libmultiscale::lm_exit(LM_EXIT_FAILURE);
}
/* -------------------------------------------------------------------------- */
LibMultiScaleException
::
LibMultiScaleException
(
const
std
::
string
&
mess
)
throw
()
:
message
(
mess
),
stack_trace
(
get_stacktrace
())
{
previous_exception
=
nullptr
;
}
LibMultiScaleException
::
LibMultiScaleException
(
const
LibMultiScaleException
&
e
,
const
std
::
string
&
mess
)
throw
()
:
message
(
mess
),
stack_trace
(
get_stacktrace
())
{
previous_exception
=
std
::
make_shared
<
LibMultiScaleException
>
(
e
);
}
const
char
*
LibMultiScaleException
::
what
()
const
throw
()
{
return
message
.
c_str
();
}
std
::
string
LibMultiScaleException
::
recursiveWhat
()
{
std
::
stringstream
sstr
;
sstr
<<
message
;
std
::
string
recursive_message
=
sstr
.
str
();
if
(
previous_exception
!=
nullptr
)
recursive_message
=
previous_exception
->
recursiveWhat
()
+
"
\n
"
+
"-----------------------------------------"
+
"-----------------------------------------
\n
"
+
recursive_message
;
return
recursive_message
;
}
std
::
string
LibMultiScaleException
::
messageWithTrace
()
{
std
::
stringstream
sstr
;
std
::
string
mesg
=
print_stacktrace
(
this
->
stack_trace
);
sstr
<<
mesg
<<
"
\n\n
"
<<
message
;
std
::
string
message_with_trace
=
sstr
.
str
();
if
(
previous_exception
!=
nullptr
)
message_with_trace
=
previous_exception
->
messageWithTrace
()
+
"
\n
"
+
"-----------------------------------------"
+
"-----------------------------------------
\n
"
+
message_with_trace
;
return
message_with_trace
;
}
void
openGlobal
()
{
if
(
print_crap_to_file
)
{
std
::
stringstream
sstr
;
sstr
<<
my_hostname
<<
"-"
<<
lm_my_proc_id
<<
".log"
;
file_out
.
open
(
sstr
.
str
().
c_str
(),
std
::
ios_base
::
out
);
global_out
=
&
file_out
;
}
else
{
global_out
=
&
std
::
cerr
;
}
}
/* -------------------------------------------------------------------------- */
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
stream
,
const
dbgLevel
&
_this
)
{
switch
(
_this
)
{
case
dbg_message:
;
break
;
case
dbg_warning:
stream
<<
"WARNING:"
;
break
;
case
dbg_info_startup:
stream
<<
"INFO_STARTUP:"
;
break
;
case
dbg_info:
stream
<<
"INFO:"
;
break
;
case
dbg_detail:
stream
<<
"DETAIL:"
;
break
;
case
dbg_all:
stream
<<
"ALL:"
;
break
;
}
return
stream
;
}
/* -------------------------------------------------------------------------- */
#define INFO_PROCESS \
"s=" << current_step << ":" << current_stage << ":proc=" << lm_my_proc_id \
<< ": "
#define INFO_PROCESS_FULL \
"s=" << current_step << ":" << current_stage << ":proc=" << lm_my_proc_id \
<< ":host=" << my_hostname << "," << lm_getpid() << " : "
#define INFO_SOURCE function << ":" << line << ":"
#define INFO_SOURCE_FULL file << ":" << line << ":" << pretty_function << ":"
/* ----------------- */
// no info
//#define APPEND_FILE ""
/* ------------------*/
// small info
#define APPEND_FILE INFO_SOURCE << INFO_PROCESS
/* ------------------*/
// full info
//#define APPEND_FILE INFO_SOURCE_FULL << INFO_PROCESS_FULL
/* -------------------------------------------------------------------------- */
void
lmPrintOut
(
std
::
stringstream
&
x
,
dbgLevel
level
,
UInt
line
,
const
std
::
string
&
file
[[
gnu
::
unused
]],
const
std
::
string
&
function
[[
gnu
::
unused
]],
const
std
::
string
&
pretty_function
[[
gnu
::
unused
]])
{
if
(
global_level
>=
level
)
if
((
global_proc
==
lm_uint_max
||
global_proc
==
lm_my_proc_id
||
global_proc1
==
lm_my_proc_id
||
global_proc2
==
lm_my_proc_id
)
&&
(
current_step
>=
start_dump
&&
(
end_dump
==
lm_uint_max
||
current_step
<=
end_dump
)))
{
if
(
global_out
)
(
*
global_out
)
<<
APPEND_FILE
<<
x
.
str
()
<<
std
::
endl
<<
std
::
flush
;
}
}
/* -------------------------------------------------------------------------- */
__END_LIBMULTISCALE__
Event Timeline
Log In to Comment