Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
69850c1e
Commit
69850c1e
authored
Mar 30, 2015
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Print stack trace on signal for all processes using KJ_MAIN.
parent
ab775828
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
83 additions
and
69 deletions
+83
-69
exception.c++
c++/src/kj/exception.c++
+68
-0
exception.h
c++/src/kj/exception.h
+5
-0
main.c++
c++/src/kj/main.c++
+3
-1
test.c++
c++/src/kj/test.c++
+6
-68
thread.h
c++/src/kj/thread.h
+1
-0
No files found.
c++/src/kj/exception.c++
View file @
69850c1e
...
...
@@ -27,6 +27,9 @@
#include <stdlib.h>
#include <exception>
#include <new>
#include <signal.h>
#include <sys/mman.h>
#include "io.h"
#if (__linux__ && !__ANDROID__) || __APPLE__
#define KJ_HAS_BACKTRACE 1
...
...
@@ -139,6 +142,71 @@ String stringifyStackTrace(ArrayPtr<void* const> trace) {
#endif
}
namespace
{
void
crashHandler
(
int
signo
,
siginfo_t
*
info
,
void
*
context
)
{
void
*
traceSpace
[
32
];
auto
trace
=
getStackTrace
(
traceSpace
);
if
(
trace
.
size
()
>=
3
)
{
// Remove getStackTrace(), crashHandler() and signal trampoline from trace.
trace
=
trace
.
slice
(
3
,
trace
.
size
());
}
auto
message
=
kj
::
str
(
"*** Received signal #"
,
signo
,
": "
,
strsignal
(
signo
),
"
\n
stack: "
,
strArray
(
trace
,
" "
),
stringifyStackTrace
(
trace
),
'\n'
);
FdOutputStream
(
STDERR_FILENO
).
write
(
message
.
begin
(),
message
.
size
());
_exit
(
1
);
}
}
// namespace
void
printStackTraceOnCrash
()
{
#if KJ_HAS_BACKTRACE
// Set up alternate signal stack so that stack overflows can be handled.
stack_t
stack
;
memset
(
&
stack
,
0
,
sizeof
(
stack
));
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
#ifndef MAP_GROWSDOWN
#define MAP_GROWSDOWN 0
#endif
stack
.
ss_size
=
65536
;
// Note: ss_sp is char* on FreeBSD, void* on Linux and OSX.
stack
.
ss_sp
=
reinterpret_cast
<
char
*>
(
mmap
(
nullptr
,
stack
.
ss_size
,
PROT_READ
|
PROT_WRITE
,
MAP_ANONYMOUS
|
MAP_PRIVATE
|
MAP_GROWSDOWN
,
-
1
,
0
));
KJ_SYSCALL
(
sigaltstack
(
&
stack
,
nullptr
));
// Catch all relevant signals.
struct
sigaction
action
;
memset
(
&
action
,
0
,
sizeof
(
action
));
action
.
sa_flags
=
SA_SIGINFO
|
SA_ONSTACK
|
SA_NODEFER
|
SA_RESETHAND
;
action
.
sa_sigaction
=
&
crashHandler
;
// Dump stack on common "crash" signals.
KJ_SYSCALL
(
sigaction
(
SIGSEGV
,
&
action
,
nullptr
));
KJ_SYSCALL
(
sigaction
(
SIGBUS
,
&
action
,
nullptr
));
KJ_SYSCALL
(
sigaction
(
SIGFPE
,
&
action
,
nullptr
));
KJ_SYSCALL
(
sigaction
(
SIGABRT
,
&
action
,
nullptr
));
// Dump stack on unimplemented syscalls -- useful in seccomp sandboxes.
KJ_SYSCALL
(
sigaction
(
SIGSYS
,
&
action
,
nullptr
));
#ifdef KJ_DEBUG
// Dump stack on keyboard interrupt -- useful for infinite loops. Only in debug mode, though,
// because stack traces on ctrl+c can be obnoxious for, say, command-line tools.
KJ_SYSCALL
(
sigaction
(
SIGINT
,
&
action
,
nullptr
));
#endif
#endif
}
StringPtr
KJ_STRINGIFY
(
Exception
::
Type
type
)
{
static
const
char
*
TYPE_STRINGS
[]
=
{
"failed"
,
...
...
c++/src/kj/exception.h
View file @
69850c1e
...
...
@@ -302,6 +302,11 @@ String stringifyStackTrace(ArrayPtr<void* const>);
// Convert the stack trace to a string with file names and line numbers. This may involve executing
// suprocesses.
void
printStackTraceOnCrash
();
// Registers signal handlers on common "crash" signals like SIGSEGV that will (attempt to) print
// a stack trace. You should call this as early as possible on program startup. Programs using
// KJ_MAIN get this automatically.
}
// namespace kj
#endif // KJ_EXCEPTION_H_
c++/src/kj/main.c++
View file @
69850c1e
...
...
@@ -43,7 +43,9 @@ namespace kj {
TopLevelProcessContext
::
TopLevelProcessContext
(
StringPtr
programName
)
:
programName
(
programName
),
cleanShutdown
(
getenv
(
"KJ_CLEAN_SHUTDOWN"
)
!=
nullptr
)
{}
cleanShutdown
(
getenv
(
"KJ_CLEAN_SHUTDOWN"
)
!=
nullptr
)
{
printStackTraceOnCrash
();
}
StringPtr
TopLevelProcessContext
::
getProgramName
()
{
return
programName
;
...
...
c++/src/kj/test.c++
View file @
69850c1e
...
...
@@ -59,9 +59,11 @@ namespace _ { // private
bool
hasSubstring
(
kj
::
StringPtr
haystack
,
kj
::
StringPtr
needle
)
{
// TODO(perf): This is not the best algorithm for substring matching.
for
(
size_t
i
=
0
;
i
<=
haystack
.
size
()
-
needle
.
size
();
i
++
)
{
if
(
haystack
.
slice
(
i
).
startsWith
(
needle
))
{
return
true
;
if
(
needle
.
size
()
<=
haystack
.
size
())
{
for
(
size_t
i
=
0
;
i
<=
haystack
.
size
()
-
needle
.
size
();
i
++
)
{
if
(
haystack
.
slice
(
i
).
startsWith
(
needle
))
{
return
true
;
}
}
}
return
false
;
...
...
@@ -181,68 +183,6 @@ void GlobFilter::applyState(char c, int state) {
namespace
{
void
crashHandler
(
int
signo
,
siginfo_t
*
info
,
void
*
context
)
{
void
*
traceSpace
[
32
];
auto
trace
=
getStackTrace
(
traceSpace
);
if
(
trace
.
size
()
>=
3
)
{
// Remove getStackTrace(), crashHandler() and signal trampoline from trace.
trace
=
trace
.
slice
(
3
,
trace
.
size
());
}
auto
message
=
kj
::
str
(
"*** Received signal #"
,
signo
,
": "
,
strsignal
(
signo
),
"
\n
stack: "
,
strArray
(
trace
,
" "
),
stringifyStackTrace
(
trace
),
'\n'
);
FdOutputStream
(
STDERR_FILENO
).
write
(
message
.
begin
(),
message
.
size
());
_exit
(
1
);
}
void
registerCrashHandler
()
{
// Set up alternate signal stack so that stack overflows can be handled.
stack_t
stack
;
memset
(
&
stack
,
0
,
sizeof
(
stack
));
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
#ifndef MAP_GROWSDOWN
#define MAP_GROWSDOWN 0
#endif
stack
.
ss_size
=
65536
;
// Note: ss_sp is char* on FreeBSD, void* on Linux and OSX.
stack
.
ss_sp
=
reinterpret_cast
<
char
*>
(
mmap
(
nullptr
,
stack
.
ss_size
,
PROT_READ
|
PROT_WRITE
,
MAP_ANONYMOUS
|
MAP_PRIVATE
|
MAP_GROWSDOWN
,
-
1
,
0
));
KJ_SYSCALL
(
sigaltstack
(
&
stack
,
nullptr
));
// Catch all relevant signals.
struct
sigaction
action
;
memset
(
&
action
,
0
,
sizeof
(
action
));
action
.
sa_flags
=
SA_SIGINFO
|
SA_ONSTACK
|
SA_NODEFER
|
SA_RESETHAND
;
action
.
sa_sigaction
=
&
crashHandler
;
// Dump stack on common "crash" signals.
KJ_SYSCALL
(
sigaction
(
SIGSEGV
,
&
action
,
nullptr
));
KJ_SYSCALL
(
sigaction
(
SIGBUS
,
&
action
,
nullptr
));
KJ_SYSCALL
(
sigaction
(
SIGFPE
,
&
action
,
nullptr
));
KJ_SYSCALL
(
sigaction
(
SIGABRT
,
&
action
,
nullptr
));
// Dump stack on unimplemented syscalls -- useful in seccomp sandboxes.
KJ_SYSCALL
(
sigaction
(
SIGSYS
,
&
action
,
nullptr
));
// Dump stack on keyboard interrupt -- useful for infinite loops.
KJ_SYSCALL
(
sigaction
(
SIGINT
,
&
action
,
nullptr
));
}
}
// namespace
// =======================================================================================
namespace
{
class
TestExceptionCallback
:
public
ExceptionCallback
{
public
:
TestExceptionCallback
(
ProcessContext
&
context
)
:
context
(
context
)
{}
...
...
@@ -278,9 +218,7 @@ private:
class
TestRunner
{
public
:
explicit
TestRunner
(
ProcessContext
&
context
)
:
context
(
context
),
useColor
(
isatty
(
STDOUT_FILENO
))
{
registerCrashHandler
();
}
:
context
(
context
),
useColor
(
isatty
(
STDOUT_FILENO
))
{}
MainFunc
getMain
()
{
return
MainBuilder
(
context
,
"KJ Test Runner (version not applicable)"
,
...
...
c++/src/kj/thread.h
View file @
69850c1e
...
...
@@ -39,6 +39,7 @@ class Thread {
public
:
explicit
Thread
(
Function
<
void
()
>
func
);
KJ_DISALLOW_COPY
(
Thread
);
~
Thread
()
noexcept
(
false
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment