Skip to content

Commit

Permalink
Merge pull request #339 from bazsi/debugger-interrupt-handling
Browse files Browse the repository at this point in the history
Debugger interrupt handling
  • Loading branch information
alltilla authored Nov 13, 2024
2 parents b916003 + 7cbb51d commit 174077f
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 30 deletions.
98 changes: 76 additions & 22 deletions lib/debugger/debugger.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@
#include "compat/time.h"
#include "scratch-buffers.h"

#include <iv_signal.h>
#include <stdio.h>
#include <unistd.h>

struct _Debugger
{
Tracer *tracer;
struct iv_signal sigint;
MainLoop *main_loop;
GlobalConfig *cfg;
gchar *command_buffer;
Expand Down Expand Up @@ -138,15 +140,31 @@ _display_source_line(LogExprNode *expr_node)
static gboolean
_cmd_help(Debugger *self, gint argc, gchar *argv[])
{
printf("syslog-ng interactive console, the following commands are available\n\n"
" help, h, or ? Display this help\n"
" info Display information about the current execution state\n"
" continue or c Continue until the next breakpoint\n"
" trace Display timing information as the message traverses the config\n"
" print, p Print the current log message\n"
" drop, d Drop the current message\n"
" quit, q Tell syslog-ng to exit\n"
);
if (self->breakpoint_site)
{
printf("syslog-ng interactive console\n"
"Stopped on a breakpoint.\n"
"The following commands are available:\n\n"
" help, h, ? Display this help\n"
" info, i Display information about the current execution state\n"
" continue, c Continue until the next breakpoint\n"
" display Set the displayed message template\n"
" trace, t Display timing information as the message traverses the config\n"
" print, p Print the current log message\n"
" drop, d Drop the current message\n"
" quit, q Tell syslog-ng to exit\n"
);
}
else
{
printf("syslog-ng interactive console\n"
"Stopped on an interrupt.\n"
"The following commands are available:\n\n"
" help, h, ? Display this help\n"
" continue, c Continue until the next breakpoint\n"
" quit, q Tell syslog-ng to exit\n"
);
}
return TRUE;
}

Expand Down Expand Up @@ -210,7 +228,8 @@ static gboolean
_cmd_quit(Debugger *self, gint argc, gchar *argv[])
{
main_loop_exit(self->main_loop);
self->breakpoint_site->drop = TRUE;
if (self->breakpoint_site)
self->breakpoint_site->drop = TRUE;
return FALSE;
}

Expand Down Expand Up @@ -245,22 +264,25 @@ struct
{
const gchar *name;
DebuggerCommandFunc command;
gboolean requires_breakpoint_site;
} command_table[] =
{
{ "help", _cmd_help },
{ "h", _cmd_help },
{ "?", _cmd_help },
{ "continue", _cmd_continue },
{ "c", _cmd_continue },
{ "print", _cmd_print },
{ "p", _cmd_print },
{ "print", _cmd_print, .requires_breakpoint_site = TRUE },
{ "p", _cmd_print, .requires_breakpoint_site = TRUE },
{ "display", _cmd_display },
{ "drop", _cmd_drop },
{ "drop", _cmd_drop, .requires_breakpoint_site = TRUE },
{ "d", _cmd_drop, .requires_breakpoint_site = TRUE },
{ "quit", _cmd_quit },
{ "q", _cmd_quit },
{ "trace", _cmd_trace },
{ "info", _cmd_info },
{ "i", _cmd_info },
{ "trace", _cmd_trace, .requires_breakpoint_site = TRUE },
{ "t", _cmd_trace, .requires_breakpoint_site = TRUE },
{ "info", _cmd_info, .requires_breakpoint_site = TRUE },
{ "i", _cmd_info, .requires_breakpoint_site = TRUE },
{ NULL, NULL }
};

Expand Down Expand Up @@ -319,6 +341,7 @@ _handle_command(Debugger *self)
gint argc;
gchar **argv;
GError *error = NULL;
gboolean requires_breakpoint_site = TRUE;
DebuggerCommandFunc command = NULL;

if (!g_shell_parse_argv(self->command_buffer ? : "", &argc, &argv, &error))
Expand All @@ -333,6 +356,7 @@ _handle_command(Debugger *self)
if (strcmp(command_table[i].name, argv[0]) == 0)
{
command = command_table[i].command;
requires_breakpoint_site = command_table[i].requires_breakpoint_site;
break;
}
}
Expand All @@ -341,6 +365,11 @@ _handle_command(Debugger *self)
printf("Undefined command %s, try \"help\"\n", argv[0]);
return TRUE;
}
else if (requires_breakpoint_site && self->breakpoint_site == NULL)
{
printf("Running in interrupt context, command %s requires pipeline context\n", argv[0]);
return TRUE;
}
gboolean result = command(self, argc, argv);
g_strfreev(argv);
return result;
Expand All @@ -350,11 +379,20 @@ static void
_handle_interactive_prompt(Debugger *self)
{
gchar buf[1024];
LogPipe *current_pipe = self->breakpoint_site->pipe;
LogPipe *current_pipe;

if (self->breakpoint_site)
{
current_pipe = self->breakpoint_site->pipe;

printf("Breakpoint hit %s\n", log_expr_node_format_location(current_pipe->expr_node, buf, sizeof(buf)));
_display_source_line(current_pipe->expr_node);
_display_msg_with_template(self, self->breakpoint_site->msg, self->display_template);
printf("Breakpoint hit %s\n", log_expr_node_format_location(current_pipe->expr_node, buf, sizeof(buf)));
_display_source_line(current_pipe->expr_node);
_display_msg_with_template(self, self->breakpoint_site->msg, self->display_template);
}
else
{
printf("Stopping on interrupt, message related commands are unavailable...\n");
}
while (1)
{
_fetch_command(self);
Expand All @@ -374,22 +412,37 @@ _debugger_thread_func(Debugger *self)
while (1)
{
self->breakpoint_site = NULL;
if (!tracer_wait_for_breakpoint(self->tracer, &self->breakpoint_site))
if (!tracer_wait_for_event(self->tracer, &self->breakpoint_site))
break;

_handle_interactive_prompt(self);
tracer_resume_after_breakpoint(self->tracer, self->breakpoint_site);
tracer_resume_after_event(self->tracer, self->breakpoint_site);
}
scratch_buffers_explicit_gc();
app_thread_stop();
return NULL;
}

static void
_interrupt(gpointer user_data)
{
Debugger *self = (Debugger *) user_data;

tracer_stop_on_interrupt(self->tracer);
}

void
debugger_start_console(Debugger *self)
{
main_loop_assert_main_thread();

IV_SIGNAL_INIT(&self->sigint);
self->sigint.signum = SIGINT;
self->sigint.flags = IV_SIGNAL_FLAG_EXCLUSIVE;
self->sigint.cookie = self;
self->sigint.handler = _interrupt;
iv_signal_register(&self->sigint);

self->debugger_thread = g_thread_new(NULL, (GThreadFunc) _debugger_thread_func, self);
}

Expand Down Expand Up @@ -429,6 +482,7 @@ debugger_exit(Debugger *self)
{
main_loop_assert_main_thread();

iv_signal_unregister(&self->sigint);
tracer_cancel(self->tracer);
g_thread_join(self->debugger_thread);
}
Expand Down
26 changes: 21 additions & 5 deletions lib/debugger/tracer.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,20 @@ tracer_stop_on_breakpoint(Tracer *self, BreakpointSite *breakpoint_site)
g_mutex_unlock(&self->breakpoint_mutex);
}

void
tracer_stop_on_interrupt(Tracer *self)
{
g_mutex_lock(&self->breakpoint_mutex);
/* send interrupt signal as a NULL */
g_queue_push_tail(self->waiting_breakpoints, NULL);
g_cond_signal(&self->breakpoint_cond);
g_mutex_unlock(&self->breakpoint_mutex);
}

/* NOTE: called by the interactive debugger to wait for a breakpoint to
* trigger, a return of FALSE indicates that the tracing was cancelled */
gboolean
tracer_wait_for_breakpoint(Tracer *self, BreakpointSite **breakpoint_site)
tracer_wait_for_event(Tracer *self, BreakpointSite **breakpoint_site)
{
gboolean cancelled = FALSE;
g_mutex_lock(&self->breakpoint_mutex);
Expand All @@ -92,13 +102,19 @@ tracer_wait_for_breakpoint(Tracer *self, BreakpointSite **breakpoint_site)

/* NOTE: called by the interactive debugger to resume the worker after a breakpoint */
void
tracer_resume_after_breakpoint(Tracer *self, BreakpointSite *breakpoint_site)
tracer_resume_after_event(Tracer *self, BreakpointSite *breakpoint_site)
{
g_mutex_lock(&self->breakpoint_mutex);
g_assert(self->pending_breakpoint == breakpoint_site);
self->pending_breakpoint->resume_requested = TRUE;
self->pending_breakpoint = NULL;
g_cond_broadcast(&self->resume_cond);
if (self->pending_breakpoint)
{
/* we might be returning from an interrupt in which case
* pending_breakpoint is NULL, nothing to resume */

self->pending_breakpoint->resume_requested = TRUE;
self->pending_breakpoint = NULL;
g_cond_broadcast(&self->resume_cond);
}
g_mutex_unlock(&self->breakpoint_mutex);
}

Expand Down
5 changes: 3 additions & 2 deletions lib/debugger/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ typedef struct _BreakpointSite
} BreakpointSite;


void tracer_stop_on_interrupt(Tracer *self);
void tracer_stop_on_breakpoint(Tracer *self, BreakpointSite *breakpoint_site);
gboolean tracer_wait_for_breakpoint(Tracer *self, BreakpointSite **breakpoint_site);
void tracer_resume_after_breakpoint(Tracer *self, BreakpointSite *breakpoint_site);
gboolean tracer_wait_for_event(Tracer *self, BreakpointSite **breakpoint_site);
void tracer_resume_after_event(Tracer *self, BreakpointSite *breakpoint_site);
void tracer_cancel(Tracer *self);

Tracer *tracer_new(GlobalConfig *cfg);
Expand Down
1 change: 0 additions & 1 deletion lib/mainloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,6 @@ _register_signal_handler(struct iv_signal *signal_poll, gint signum, void (*hand
{
IV_SIGNAL_INIT(signal_poll);
signal_poll->signum = signum;
signal_poll->flags = IV_SIGNAL_FLAG_EXCLUSIVE;
signal_poll->cookie = user_data;
signal_poll->handler = handler;
iv_signal_register(signal_poll);
Expand Down

0 comments on commit 174077f

Please sign in to comment.