Adding a run_on_exit kernel debugger add-on. It installs a debugger command
"on_exit" with which you can add commands to run when exiting the debugger. With this you could for example "on_exit sync" and "on_exit shutdown -r" when your app_server crashed. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30016 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
cd03af05a4
commit
3613bfc871
@ -158,7 +158,7 @@ AddFilesToHaikuImage system add-ons kernel busses usb
|
||||
AddFilesToHaikuImage system add-ons kernel console : vga_text ;
|
||||
AddFilesToHaikuImage system add-ons kernel debugger
|
||||
: $(X86_ONLY)<kdebug>disasm <kdebug>hangman <kdebug>invalidate_on_exit
|
||||
<kdebug>usb_keyboard ;
|
||||
<kdebug>usb_keyboard <kdebug>run_on_exit ;
|
||||
AddFilesToHaikuImage system add-ons kernel file_systems
|
||||
: $(SYSTEM_ADD_ONS_FILE_SYSTEMS) ;
|
||||
AddFilesToHaikuImage system add-ons kernel generic
|
||||
|
@ -7,4 +7,5 @@ SubInclude HAIKU_TOP src add-ons kernel debugger disasm ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel debugger hangman ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel debugger invalidate_on_exit ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel debugger laplinkll ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel debugger run_on_exit ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel debugger usb_keyboard ;
|
||||
|
7
src/add-ons/kernel/debugger/run_on_exit/Jamfile
Normal file
7
src/add-ons/kernel/debugger/run_on_exit/Jamfile
Normal file
@ -0,0 +1,7 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel debugger run_on_exit ;
|
||||
|
||||
UsePrivateHeaders kernel ;
|
||||
|
||||
KernelAddon <kdebug>run_on_exit :
|
||||
run_on_exit.cpp
|
||||
;
|
142
src/add-ons/kernel/debugger/run_on_exit/run_on_exit.cpp
Normal file
142
src/add-ons/kernel/debugger/run_on_exit/run_on_exit.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2009, Michael Lotz, mmlr@mlotz.ch
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <image.h>
|
||||
|
||||
|
||||
static sem_id sRequestSem = -1;
|
||||
static char sCommandBuffer[1024];
|
||||
static uint32 sCommandOffset = 0;
|
||||
static uint32 sCommandCount = 0;
|
||||
|
||||
|
||||
static int32
|
||||
run_on_exit_loop(void *data)
|
||||
{
|
||||
while (true) {
|
||||
if (acquire_sem(sRequestSem) != B_OK)
|
||||
break;
|
||||
|
||||
char *pointer = sCommandBuffer;
|
||||
while (sCommandCount > 0) {
|
||||
uint8 argCount = (uint8)pointer[0];
|
||||
pointer++;
|
||||
|
||||
const char *args[argCount];
|
||||
for (uint8 i = 0; i < argCount; i++) {
|
||||
args[i] = pointer;
|
||||
uint32 length = strlen(pointer);
|
||||
pointer += length + 1;
|
||||
}
|
||||
|
||||
thread_id thread = load_image(argCount, args, NULL);
|
||||
if (thread >= B_OK)
|
||||
resume_thread(thread);
|
||||
sCommandCount--;
|
||||
}
|
||||
|
||||
sCommandOffset = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
add_run_on_exit_command(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2 || strcmp(argv[1], "--help") == 0) {
|
||||
print_debugger_command_usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc > 256) {
|
||||
kprintf("too many arguments\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t totalLength = 1;
|
||||
for (int32 i = 1; i < argc; i++)
|
||||
totalLength += strlen(argv[i]) + 1;
|
||||
|
||||
if (sCommandOffset + totalLength > sizeof(sCommandBuffer)) {
|
||||
kprintf("no space left in command buffer\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *pointer = sCommandBuffer + sCommandOffset;
|
||||
*pointer++ = (char)(argc - 1);
|
||||
|
||||
for (int32 i = 1; i < argc; i++) {
|
||||
strcpy(pointer, argv[i]);
|
||||
pointer += strlen(argv[i]) + 1;
|
||||
}
|
||||
|
||||
sCommandOffset += totalLength;
|
||||
sCommandCount++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
exit_debugger()
|
||||
{
|
||||
if (sCommandCount > 0)
|
||||
release_sem_etc(sRequestSem, 1, B_DO_NOT_RESCHEDULE);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
std_ops(int32 op, ...)
|
||||
{
|
||||
if (op == B_MODULE_INIT) {
|
||||
sRequestSem = create_sem(0, "run_on_exit_request");
|
||||
if (sRequestSem < B_OK)
|
||||
return sRequestSem;
|
||||
|
||||
thread_id thread = spawn_kernel_thread(&run_on_exit_loop,
|
||||
"run_on_exit_loop", B_NORMAL_PRIORITY, NULL);
|
||||
if (thread < B_OK)
|
||||
return thread;
|
||||
|
||||
send_signal_etc(thread, SIGCONT, B_DO_NOT_RESCHEDULE);
|
||||
|
||||
add_debugger_command_etc("on_exit", &add_run_on_exit_command,
|
||||
"Adds a command to be run when leaving the kernel debugger",
|
||||
"<command> [<arguments>]\n"
|
||||
"Adds a command to be run when leaving the kernel debugger.\n", 0);
|
||||
|
||||
return B_OK;
|
||||
} else if (op == B_MODULE_UNINIT) {
|
||||
remove_debugger_command("on_exit", &add_run_on_exit_command);
|
||||
// deleting the sem will also cause the thread to exit
|
||||
delete_sem(sRequestSem);
|
||||
sRequestSem = -1;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static struct debugger_module_info sModuleInfo = {
|
||||
{
|
||||
"debugger/run_on_exit/v1",
|
||||
B_KEEP_LOADED,
|
||||
&std_ops
|
||||
},
|
||||
|
||||
NULL,
|
||||
exit_debugger,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
module_info *modules[] = {
|
||||
(module_info *)&sModuleInfo,
|
||||
NULL
|
||||
};
|
Loading…
Reference in New Issue
Block a user