Skip to content

Commit 0ae04eb

Browse files
committed
Use ev_async for signal-safe flight recorder dump
Defer flight recorder dump from SIGUSR2 handler to main loop via ev_async to ensure fprintf() is called outside signal context.
1 parent 95fe77c commit 0ae04eb

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

src/logging.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ static FILE *logfile = NULL; // NOLINT(cppcoreguidelines
1818
static int loglevel = LOG_ERROR; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
1919
static ev_timer logging_timer; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
2020
static ev_signal sigusr2; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
21+
static ev_async flight_recorder_async; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
22+
static struct ev_loop *logging_loop = NULL; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
2123
static struct ring_buffer * flight_recorder = NULL; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
2224

2325
static const char * const SeverityStr[] = {
@@ -46,13 +48,23 @@ void logging_flight_recorder_dump(void) {
4648
}
4749
}
4850

51+
static void logging_flight_recorder_dump_async_cb(struct ev_loop __attribute__((unused)) *loop,
52+
ev_async __attribute__((__unused__)) *w,
53+
int __attribute__((__unused__)) revents) {
54+
logging_flight_recorder_dump();
55+
}
56+
4957
static void logging_flight_recorder_dump_cb(struct ev_loop __attribute__((unused)) *loop,
5058
ev_signal __attribute__((__unused__)) *w,
5159
int __attribute__((__unused__)) revents) {
52-
logging_flight_recorder_dump();
60+
// Signal handler: just trigger async watcher to defer to main loop
61+
// This ensures fprintf() is called outside of signal context
62+
ev_async_send(logging_loop, &flight_recorder_async);
5363
}
5464

5565
void logging_events_init(struct ev_loop *loop) {
66+
logging_loop = loop;
67+
5668
/* don't start timer if we will never write messages that are not flushed */
5769
if (loglevel < LOG_FLUSH_LEVEL) {
5870
DLOG("starting periodic log flush timer");
@@ -61,13 +73,16 @@ void logging_events_init(struct ev_loop *loop) {
6173
}
6274

6375
DLOG("starting SIGUSR2 handler");
76+
ev_async_init(&flight_recorder_async, logging_flight_recorder_dump_async_cb);
77+
ev_async_start(loop, &flight_recorder_async);
6478
ev_signal_init(&sigusr2, logging_flight_recorder_dump_cb, SIGUSR2);
6579
ev_signal_start(loop, &sigusr2);
6680
}
6781

6882
void logging_events_cleanup(struct ev_loop *loop) {
6983
ev_timer_stop(loop, &logging_timer);
7084
ev_signal_stop(loop, &sigusr2);
85+
ev_async_stop(loop, &flight_recorder_async);
7186
}
7287

7388
void logging_init(int fd, int level, uint32_t flight_recorder_size) {

0 commit comments

Comments
 (0)