Skip to content

Commit 174077f

Browse files
authored
Merge pull request #339 from bazsi/debugger-interrupt-handling
Debugger interrupt handling
2 parents b916003 + 7cbb51d commit 174077f

File tree

4 files changed

+100
-30
lines changed

4 files changed

+100
-30
lines changed

lib/debugger/debugger.c

+76-22
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@
3131
#include "compat/time.h"
3232
#include "scratch-buffers.h"
3333

34+
#include <iv_signal.h>
3435
#include <stdio.h>
3536
#include <unistd.h>
3637

3738
struct _Debugger
3839
{
3940
Tracer *tracer;
41+
struct iv_signal sigint;
4042
MainLoop *main_loop;
4143
GlobalConfig *cfg;
4244
gchar *command_buffer;
@@ -138,15 +140,31 @@ _display_source_line(LogExprNode *expr_node)
138140
static gboolean
139141
_cmd_help(Debugger *self, gint argc, gchar *argv[])
140142
{
141-
printf("syslog-ng interactive console, the following commands are available\n\n"
142-
" help, h, or ? Display this help\n"
143-
" info Display information about the current execution state\n"
144-
" continue or c Continue until the next breakpoint\n"
145-
" trace Display timing information as the message traverses the config\n"
146-
" print, p Print the current log message\n"
147-
" drop, d Drop the current message\n"
148-
" quit, q Tell syslog-ng to exit\n"
149-
);
143+
if (self->breakpoint_site)
144+
{
145+
printf("syslog-ng interactive console\n"
146+
"Stopped on a breakpoint.\n"
147+
"The following commands are available:\n\n"
148+
" help, h, ? Display this help\n"
149+
" info, i Display information about the current execution state\n"
150+
" continue, c Continue until the next breakpoint\n"
151+
" display Set the displayed message template\n"
152+
" trace, t Display timing information as the message traverses the config\n"
153+
" print, p Print the current log message\n"
154+
" drop, d Drop the current message\n"
155+
" quit, q Tell syslog-ng to exit\n"
156+
);
157+
}
158+
else
159+
{
160+
printf("syslog-ng interactive console\n"
161+
"Stopped on an interrupt.\n"
162+
"The following commands are available:\n\n"
163+
" help, h, ? Display this help\n"
164+
" continue, c Continue until the next breakpoint\n"
165+
" quit, q Tell syslog-ng to exit\n"
166+
);
167+
}
150168
return TRUE;
151169
}
152170

@@ -210,7 +228,8 @@ static gboolean
210228
_cmd_quit(Debugger *self, gint argc, gchar *argv[])
211229
{
212230
main_loop_exit(self->main_loop);
213-
self->breakpoint_site->drop = TRUE;
231+
if (self->breakpoint_site)
232+
self->breakpoint_site->drop = TRUE;
214233
return FALSE;
215234
}
216235

@@ -245,22 +264,25 @@ struct
245264
{
246265
const gchar *name;
247266
DebuggerCommandFunc command;
267+
gboolean requires_breakpoint_site;
248268
} command_table[] =
249269
{
250270
{ "help", _cmd_help },
251271
{ "h", _cmd_help },
252272
{ "?", _cmd_help },
253273
{ "continue", _cmd_continue },
254274
{ "c", _cmd_continue },
255-
{ "print", _cmd_print },
256-
{ "p", _cmd_print },
275+
{ "print", _cmd_print, .requires_breakpoint_site = TRUE },
276+
{ "p", _cmd_print, .requires_breakpoint_site = TRUE },
257277
{ "display", _cmd_display },
258-
{ "drop", _cmd_drop },
278+
{ "drop", _cmd_drop, .requires_breakpoint_site = TRUE },
279+
{ "d", _cmd_drop, .requires_breakpoint_site = TRUE },
259280
{ "quit", _cmd_quit },
260281
{ "q", _cmd_quit },
261-
{ "trace", _cmd_trace },
262-
{ "info", _cmd_info },
263-
{ "i", _cmd_info },
282+
{ "trace", _cmd_trace, .requires_breakpoint_site = TRUE },
283+
{ "t", _cmd_trace, .requires_breakpoint_site = TRUE },
284+
{ "info", _cmd_info, .requires_breakpoint_site = TRUE },
285+
{ "i", _cmd_info, .requires_breakpoint_site = TRUE },
264286
{ NULL, NULL }
265287
};
266288

@@ -319,6 +341,7 @@ _handle_command(Debugger *self)
319341
gint argc;
320342
gchar **argv;
321343
GError *error = NULL;
344+
gboolean requires_breakpoint_site = TRUE;
322345
DebuggerCommandFunc command = NULL;
323346

324347
if (!g_shell_parse_argv(self->command_buffer ? : "", &argc, &argv, &error))
@@ -333,6 +356,7 @@ _handle_command(Debugger *self)
333356
if (strcmp(command_table[i].name, argv[0]) == 0)
334357
{
335358
command = command_table[i].command;
359+
requires_breakpoint_site = command_table[i].requires_breakpoint_site;
336360
break;
337361
}
338362
}
@@ -341,6 +365,11 @@ _handle_command(Debugger *self)
341365
printf("Undefined command %s, try \"help\"\n", argv[0]);
342366
return TRUE;
343367
}
368+
else if (requires_breakpoint_site && self->breakpoint_site == NULL)
369+
{
370+
printf("Running in interrupt context, command %s requires pipeline context\n", argv[0]);
371+
return TRUE;
372+
}
344373
gboolean result = command(self, argc, argv);
345374
g_strfreev(argv);
346375
return result;
@@ -350,11 +379,20 @@ static void
350379
_handle_interactive_prompt(Debugger *self)
351380
{
352381
gchar buf[1024];
353-
LogPipe *current_pipe = self->breakpoint_site->pipe;
382+
LogPipe *current_pipe;
383+
384+
if (self->breakpoint_site)
385+
{
386+
current_pipe = self->breakpoint_site->pipe;
354387

355-
printf("Breakpoint hit %s\n", log_expr_node_format_location(current_pipe->expr_node, buf, sizeof(buf)));
356-
_display_source_line(current_pipe->expr_node);
357-
_display_msg_with_template(self, self->breakpoint_site->msg, self->display_template);
388+
printf("Breakpoint hit %s\n", log_expr_node_format_location(current_pipe->expr_node, buf, sizeof(buf)));
389+
_display_source_line(current_pipe->expr_node);
390+
_display_msg_with_template(self, self->breakpoint_site->msg, self->display_template);
391+
}
392+
else
393+
{
394+
printf("Stopping on interrupt, message related commands are unavailable...\n");
395+
}
358396
while (1)
359397
{
360398
_fetch_command(self);
@@ -374,22 +412,37 @@ _debugger_thread_func(Debugger *self)
374412
while (1)
375413
{
376414
self->breakpoint_site = NULL;
377-
if (!tracer_wait_for_breakpoint(self->tracer, &self->breakpoint_site))
415+
if (!tracer_wait_for_event(self->tracer, &self->breakpoint_site))
378416
break;
379417

380418
_handle_interactive_prompt(self);
381-
tracer_resume_after_breakpoint(self->tracer, self->breakpoint_site);
419+
tracer_resume_after_event(self->tracer, self->breakpoint_site);
382420
}
383421
scratch_buffers_explicit_gc();
384422
app_thread_stop();
385423
return NULL;
386424
}
387425

426+
static void
427+
_interrupt(gpointer user_data)
428+
{
429+
Debugger *self = (Debugger *) user_data;
430+
431+
tracer_stop_on_interrupt(self->tracer);
432+
}
433+
388434
void
389435
debugger_start_console(Debugger *self)
390436
{
391437
main_loop_assert_main_thread();
392438

439+
IV_SIGNAL_INIT(&self->sigint);
440+
self->sigint.signum = SIGINT;
441+
self->sigint.flags = IV_SIGNAL_FLAG_EXCLUSIVE;
442+
self->sigint.cookie = self;
443+
self->sigint.handler = _interrupt;
444+
iv_signal_register(&self->sigint);
445+
393446
self->debugger_thread = g_thread_new(NULL, (GThreadFunc) _debugger_thread_func, self);
394447
}
395448

@@ -429,6 +482,7 @@ debugger_exit(Debugger *self)
429482
{
430483
main_loop_assert_main_thread();
431484

485+
iv_signal_unregister(&self->sigint);
432486
tracer_cancel(self->tracer);
433487
g_thread_join(self->debugger_thread);
434488
}

lib/debugger/tracer.c

+21-5
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,20 @@ tracer_stop_on_breakpoint(Tracer *self, BreakpointSite *breakpoint_site)
6262
g_mutex_unlock(&self->breakpoint_mutex);
6363
}
6464

65+
void
66+
tracer_stop_on_interrupt(Tracer *self)
67+
{
68+
g_mutex_lock(&self->breakpoint_mutex);
69+
/* send interrupt signal as a NULL */
70+
g_queue_push_tail(self->waiting_breakpoints, NULL);
71+
g_cond_signal(&self->breakpoint_cond);
72+
g_mutex_unlock(&self->breakpoint_mutex);
73+
}
74+
6575
/* NOTE: called by the interactive debugger to wait for a breakpoint to
6676
* trigger, a return of FALSE indicates that the tracing was cancelled */
6777
gboolean
68-
tracer_wait_for_breakpoint(Tracer *self, BreakpointSite **breakpoint_site)
78+
tracer_wait_for_event(Tracer *self, BreakpointSite **breakpoint_site)
6979
{
7080
gboolean cancelled = FALSE;
7181
g_mutex_lock(&self->breakpoint_mutex);
@@ -92,13 +102,19 @@ tracer_wait_for_breakpoint(Tracer *self, BreakpointSite **breakpoint_site)
92102

93103
/* NOTE: called by the interactive debugger to resume the worker after a breakpoint */
94104
void
95-
tracer_resume_after_breakpoint(Tracer *self, BreakpointSite *breakpoint_site)
105+
tracer_resume_after_event(Tracer *self, BreakpointSite *breakpoint_site)
96106
{
97107
g_mutex_lock(&self->breakpoint_mutex);
98108
g_assert(self->pending_breakpoint == breakpoint_site);
99-
self->pending_breakpoint->resume_requested = TRUE;
100-
self->pending_breakpoint = NULL;
101-
g_cond_broadcast(&self->resume_cond);
109+
if (self->pending_breakpoint)
110+
{
111+
/* we might be returning from an interrupt in which case
112+
* pending_breakpoint is NULL, nothing to resume */
113+
114+
self->pending_breakpoint->resume_requested = TRUE;
115+
self->pending_breakpoint = NULL;
116+
g_cond_broadcast(&self->resume_cond);
117+
}
102118
g_mutex_unlock(&self->breakpoint_mutex);
103119
}
104120

lib/debugger/tracer.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ typedef struct _BreakpointSite
3838
} BreakpointSite;
3939

4040

41+
void tracer_stop_on_interrupt(Tracer *self);
4142
void tracer_stop_on_breakpoint(Tracer *self, BreakpointSite *breakpoint_site);
42-
gboolean tracer_wait_for_breakpoint(Tracer *self, BreakpointSite **breakpoint_site);
43-
void tracer_resume_after_breakpoint(Tracer *self, BreakpointSite *breakpoint_site);
43+
gboolean tracer_wait_for_event(Tracer *self, BreakpointSite **breakpoint_site);
44+
void tracer_resume_after_event(Tracer *self, BreakpointSite *breakpoint_site);
4445
void tracer_cancel(Tracer *self);
4546

4647
Tracer *tracer_new(GlobalConfig *cfg);

lib/mainloop.c

-1
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,6 @@ _register_signal_handler(struct iv_signal *signal_poll, gint signum, void (*hand
550550
{
551551
IV_SIGNAL_INIT(signal_poll);
552552
signal_poll->signum = signum;
553-
signal_poll->flags = IV_SIGNAL_FLAG_EXCLUSIVE;
554553
signal_poll->cookie = user_data;
555554
signal_poll->handler = handler;
556555
iv_signal_register(signal_poll);

0 commit comments

Comments
 (0)