Added "--signal" option that performs the crash in a signal handler.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27934 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,7 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005-2008, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
#undef NDEBUG
|
#undef NDEBUG
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -18,6 +23,7 @@ static const char *kUsage =
|
|||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -d - call disable_debugger() first\n"
|
" -d - call disable_debugger() first\n"
|
||||||
" -h, --help - print this info text\n"
|
" -h, --help - print this info text\n"
|
||||||
|
" --signal - crash in a signal handler\n"
|
||||||
" --thread - crash in a separate thread\n"
|
" --thread - crash in a separate thread\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Modes:\n"
|
"Modes:\n"
|
||||||
@@ -26,7 +32,7 @@ static const char *kUsage =
|
|||||||
" segv2 - strcmp() using a 0x1 pointer\n"
|
" segv2 - strcmp() using a 0x1 pointer\n"
|
||||||
" div - executes a division by zero\n"
|
" div - executes a division by zero\n"
|
||||||
" debugger - invokes debugger()\n"
|
" debugger - invokes debugger()\n"
|
||||||
" assert - failed assert(), which should invoke the "
|
" assert - failed assert(), which should invoke the\n"
|
||||||
" debugger\n"
|
" debugger\n"
|
||||||
"\n"
|
"\n"
|
||||||
"[x86 specific]\n"
|
"[x86 specific]\n"
|
||||||
@@ -113,6 +119,24 @@ crash_protection()
|
|||||||
typedef int crash_function_t();
|
typedef int crash_function_t();
|
||||||
|
|
||||||
|
|
||||||
|
struct Options {
|
||||||
|
Options()
|
||||||
|
:
|
||||||
|
inThread(false),
|
||||||
|
inSignalHandler(false),
|
||||||
|
disableDebugger(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
crash_function_t* function;
|
||||||
|
bool inThread;
|
||||||
|
bool inSignalHandler;
|
||||||
|
bool disableDebugger;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Options sOptions;
|
||||||
|
|
||||||
|
|
||||||
static crash_function_t*
|
static crash_function_t*
|
||||||
get_crash_function(const char* mode)
|
get_crash_function(const char* mode)
|
||||||
{
|
{
|
||||||
@@ -138,12 +162,29 @@ get_crash_function(const char* mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
signal_handler(int signal)
|
||||||
|
{
|
||||||
|
sOptions.function();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_crash()
|
||||||
|
{
|
||||||
|
if (sOptions.inSignalHandler) {
|
||||||
|
signal(SIGUSR1, &signal_handler);
|
||||||
|
send_signal(find_thread(NULL), SIGUSR1);
|
||||||
|
} else
|
||||||
|
sOptions.function();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
crashing_thread(void* data)
|
crashing_thread(void* data)
|
||||||
{
|
{
|
||||||
crash_function_t* doCrash = (crash_function_t*)data;
|
|
||||||
snooze(100000);
|
snooze(100000);
|
||||||
doCrash();
|
do_crash();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,8 +192,6 @@ crashing_thread(void* data)
|
|||||||
int
|
int
|
||||||
main(int argc, const char* const* argv)
|
main(int argc, const char* const* argv)
|
||||||
{
|
{
|
||||||
bool inThread = false;
|
|
||||||
bool disableDebugger = false;
|
|
||||||
const char* mode = "segv";
|
const char* mode = "segv";
|
||||||
|
|
||||||
// parse args
|
// parse args
|
||||||
@@ -164,9 +203,11 @@ main(int argc, const char* const* argv)
|
|||||||
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
|
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
|
||||||
print_usage_and_exit(false);
|
print_usage_and_exit(false);
|
||||||
} else if (strcmp(arg, "-d") == 0) {
|
} else if (strcmp(arg, "-d") == 0) {
|
||||||
disableDebugger = true;
|
sOptions.disableDebugger = true;
|
||||||
|
} else if (strcmp(arg, "--signal") == 0) {
|
||||||
|
sOptions.inSignalHandler = true;
|
||||||
} else if (strcmp(arg, "--thread") == 0) {
|
} else if (strcmp(arg, "--thread") == 0) {
|
||||||
inThread = true;
|
sOptions.inThread = true;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Invalid option \"%s\"\n", arg);
|
fprintf(stderr, "Invalid option \"%s\"\n", arg);
|
||||||
print_usage_and_exit(true);
|
print_usage_and_exit(true);
|
||||||
@@ -176,18 +217,18 @@ main(int argc, const char* const* argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crash_function_t* doCrash = get_crash_function(mode);
|
sOptions.function = get_crash_function(mode);
|
||||||
if (doCrash == NULL) {
|
if (sOptions.function == NULL) {
|
||||||
fprintf(stderr, "Invalid mode \"%s\"\n", mode);
|
fprintf(stderr, "Invalid mode \"%s\"\n", mode);
|
||||||
print_usage_and_exit(true);
|
print_usage_and_exit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disableDebugger)
|
if (sOptions.disableDebugger)
|
||||||
disable_debugger(true);
|
disable_debugger(true);
|
||||||
|
|
||||||
if (inThread) {
|
if (sOptions.inThread) {
|
||||||
thread_id thread = spawn_thread(crashing_thread, "crashing thread",
|
thread_id thread = spawn_thread(crashing_thread, "crashing thread",
|
||||||
B_NORMAL_PRIORITY, (void*)doCrash);
|
B_NORMAL_PRIORITY, NULL);
|
||||||
if (thread < 0) {
|
if (thread < 0) {
|
||||||
fprintf(stderr, "Error: Failed to spawn thread: %s\n",
|
fprintf(stderr, "Error: Failed to spawn thread: %s\n",
|
||||||
strerror(thread));
|
strerror(thread));
|
||||||
@@ -199,7 +240,7 @@ main(int argc, const char* const* argv)
|
|||||||
while (wait_for_thread(thread, &result) == B_INTERRUPTED) {
|
while (wait_for_thread(thread, &result) == B_INTERRUPTED) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
doCrash();
|
do_crash();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user