"syslog" debugger command: By default it now ignores the output added to the

syslog in the current KDL session. Added option "-k" for the former behavior.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35976 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2010-03-27 18:13:11 +00:00
parent b5489c54b0
commit c81e68b2b2
+69 -33
View File
@@ -99,7 +99,11 @@ static sem_id sSyslogNotify = -1;
static struct syslog_message* sSyslogMessage; static struct syslog_message* sSyslogMessage;
static struct ring_buffer* sSyslogBuffer; static struct ring_buffer* sSyslogBuffer;
static size_t sSyslogBufferOffset = 0; static size_t sSyslogBufferOffset = 0;
// (relative) buffer offset of the yet unsent syslog messages
static bool sSyslogDropped = false; static bool sSyslogDropped = false;
static size_t sSyslogDebuggerOffset = 0;
// (relative) buffer offset of the kernel debugger messages of the current
// KDL session
static const char* sCurrentKernelDebuggerMessagePrefix; static const char* sCurrentKernelDebuggerMessagePrefix;
static const char* sCurrentKernelDebuggerMessage; static const char* sCurrentKernelDebuggerMessage;
@@ -801,6 +805,8 @@ kernel_debugger_loop(const char* messagePrefix, const char* message,
if (sCurrentKernelDebuggerMessage != NULL) if (sCurrentKernelDebuggerMessage != NULL)
va_copy(sCurrentKernelDebuggerMessageArgs, args); va_copy(sCurrentKernelDebuggerMessageArgs, args);
sSyslogDebuggerOffset = ring_buffer_readable(sSyslogBuffer);
print_kernel_debugger_message(); print_kernel_debugger_message();
kprintf("Welcome to Kernel Debugging Land...\n"); kprintf("Welcome to Kernel Debugging Land...\n");
@@ -1051,50 +1057,77 @@ cmd_dump_syslog(int argc, char** argv)
return 0; return 0;
} }
bool currentOnly = false; bool unsentOnly = false;
if (argc > 1) { bool ignoreKDLOutput = true;
if (!strcmp(argv[1], "-n"))
currentOnly = true; int argi = 1;
else { for (; argi < argc; argi++) {
print_debugger_command_usage(argv[0]); if (strcmp(argv[argi], "-n") == 0)
return 0; unsentOnly = true;
} else if (strcmp(argv[argi], "-k") == 0)
ignoreKDLOutput = false;
else
break;
} }
uint32 start = sSyslogBuffer->first; if (argi < argc) {
size_t end = start + sSyslogBuffer->in; print_debugger_command_usage(argv[0]);
if (!currentOnly) {
// Start the buffer after the current end (we don't really know if
// this part has been written to already).
start = (start + sSyslogBuffer->in) % sSyslogBuffer->size;
end = start + sSyslogBuffer->size;
} else if (!ring_buffer_readable(sSyslogBuffer)) {
kprintf("Syslog is empty.\n");
return 0; return 0;
} }
// break it down to lines to make it grep'able size_t debuggerOffset = sSyslogDebuggerOffset;
size_t start = unsentOnly ? sSyslogBufferOffset : 0;
size_t end = ignoreKDLOutput
? debuggerOffset : ring_buffer_readable(sSyslogBuffer);
// allocate a buffer for processing the syslog output
size_t bufferSize = 1024;
char* buffer = (char*)debug_malloc(bufferSize);
char stackBuffer[64];
if (buffer == NULL) {
buffer = stackBuffer;
bufferSize = sizeof(stackBuffer);
}
// filter the output
bool newLine = false; bool newLine = false;
char line[256]; while (start < end) {
size_t linePos = 0; size_t bytesRead = ring_buffer_peek(sSyslogBuffer, start, buffer,
for (uint32 i = start; i < end; i++) { std::min(end - start, bufferSize - 1));
char c = sSyslogBuffer->buffer[i % sSyslogBuffer->size]; if (bytesRead == 0)
if (c == '\0' || (uint8)c == 0xcc) break;
continue; start += bytesRead;
line[linePos++] = c; // remove '\0' and 0xcc
newLine = false; size_t toPrint = 0;
for (size_t i = 0; i < bytesRead; i++) {
if (buffer[i] != '\0' && buffer[i] != 0xcc)
buffer[toPrint++] = buffer[i];
}
if (c == '\n' || linePos == sizeof(line) - 1) { if (toPrint > 0) {
newLine = c == '\n'; newLine = buffer[toPrint - 1] == '\n';
line[linePos] = '\0'; buffer[toPrint] = '\0';
linePos = 0; kputs(buffer);
kprintf(line); }
if (debuggerOffset > sSyslogDebuggerOffset) {
// Our output caused older syslog output to be evicted from the
// syslog buffer. We need to adjust our offsets accordingly. Note,
// this can still go wrong, if the buffer was already full and more
// was written to it than we have processed, but we can't help that.
size_t diff = debuggerOffset - sSyslogDebuggerOffset;
start -= std::min(start, diff);
end -= std::min(end, diff);
debuggerOffset = sSyslogDebuggerOffset;
} }
} }
if (!newLine) if (!newLine)
kprintf("\n"); kputs("\n");
if (buffer != stackBuffer)
debug_free(buffer);
return 0; return 0;
} }
@@ -1237,6 +1270,8 @@ syslog_write(const char* text, int32 length, bool notify)
sSyslogDropped = true; sSyslogDropped = true;
} else } else
sSyslogBufferOffset -= toDrop; sSyslogBufferOffset -= toDrop;
sSyslogDebuggerOffset -= std::min(toDrop, sSyslogDebuggerOffset);
} }
ring_buffer_write(sSyslogBuffer, (uint8*)text, length); ring_buffer_write(sSyslogBuffer, (uint8*)text, length);
@@ -1336,7 +1371,8 @@ syslog_init_post_vm(struct kernel_args* args)
add_debugger_command_etc("syslog", &cmd_dump_syslog, add_debugger_command_etc("syslog", &cmd_dump_syslog,
"Dumps the syslog buffer.", "Dumps the syslog buffer.",
"[-n]\nDumps the whole syslog buffer, or, if -n is specified, only " "[ \"-n\" ] [ \"-k\" ]\n"
"Dumps the whole syslog buffer, or, if -k is specified, only "
"the part that hasn't been sent yet.\n", 0); "the part that hasn't been sent yet.\n", 0);
add_debugger_command("serial_input", &cmd_serial_input, add_debugger_command("serial_input", &cmd_serial_input,