From 03625d7c928be02258f8c963846a4b9926415c9d Mon Sep 17 00:00:00 2001 From: Yuichiro NAITO Date: Wed, 12 Nov 2025 17:22:50 +0900 Subject: [PATCH] lib: Re-create the event loop after daemonizing on BSD platforms. Because kqueue(2) is not inherited by the child process. Signed-off-by: Yuichiro NAITO --- include/fluent-bit/flb_error.h | 1 + include/fluent-bit/flb_lib.h | 2 + src/flb_lib.c | 105 +++++++++++++++++++++++++-------- src/flb_utils.c | 3 + src/fluent-bit.c | 11 ++++ 5 files changed, 96 insertions(+), 26 deletions(-) diff --git a/include/fluent-bit/flb_error.h b/include/fluent-bit/flb_error.h index 17c9e07eaeb..545a296d039 100644 --- a/include/fluent-bit/flb_error.h +++ b/include/fluent-bit/flb_error.h @@ -26,6 +26,7 @@ #define FLB_ERR_CFG_FLUSH 20 #define FLB_ERR_CFG_FLUSH_CREATE 21 #define FLB_ERR_CFG_FLUSH_REGISTER 22 +#define FLB_ERR_EVENT_LOOP_CREATE 30 #define FLB_ERR_CUSTOM_INVALID 49 #define FLB_ERR_INPUT_INVALID 50 #define FLB_ERR_INPUT_UNDEF 51 diff --git a/include/fluent-bit/flb_lib.h b/include/fluent-bit/flb_lib.h index 88ff8cb0af3..33dc3ab4481 100644 --- a/include/fluent-bit/flb_lib.h +++ b/include/fluent-bit/flb_lib.h @@ -49,6 +49,8 @@ typedef struct flb_lib_ctx flb_ctx_t; struct flb_processor; FLB_EXPORT void flb_init_env(); +FLB_EXPORT int flb_create_event_loop(flb_ctx_t *ctx); +FLB_EXPORT int flb_destroy_event_loop(flb_ctx_t *ctx); FLB_EXPORT flb_ctx_t *flb_create(); FLB_EXPORT void flb_destroy(flb_ctx_t *ctx); FLB_EXPORT int flb_input(flb_ctx_t *ctx, const char *input, void *data); diff --git a/src/flb_lib.c b/src/flb_lib.c index 29bc200630a..882bc59e501 100644 --- a/src/flb_lib.c +++ b/src/flb_lib.c @@ -140,6 +140,83 @@ void flb_init_env() cmt_initialize(); } +int flb_create_event_loop(flb_ctx_t *ctx) +{ + int ret; + struct flb_config *config; + + if (ctx == NULL) + return FLB_LIB_ERROR; + + config = ctx->config; + + /* Create the event loop to receive notifications */ + ctx->event_loop = mk_event_loop_create(256); + if (!ctx->event_loop) + return FLB_LIB_ERROR; + + config->ch_evl = ctx->event_loop; + + /* Prepare the notification channels */ + ctx->event_channel = flb_calloc(1, sizeof(struct mk_event)); + if (!ctx->event_channel) { + perror("calloc"); + goto error_1; + } + + MK_EVENT_ZERO(ctx->event_channel); + + ret = mk_event_channel_create(config->ch_evl, + &config->ch_notif[0], + &config->ch_notif[1], + ctx->event_channel); + if (ret != 0) { + flb_error("[lib] could not create notification channels"); + goto error_2; + } + + return 0; + +error_2: + flb_free(ctx->event_channel); + ctx->event_channel = NULL; +error_1: + mk_event_loop_destroy(ctx->event_loop); + ctx->event_loop = NULL; + return FLB_LIB_ERROR; +} + +int flb_destroy_event_loop(flb_ctx_t *ctx) +{ + int ret; + struct flb_config *config; + + if (ctx == NULL || ctx->config == NULL) + return 0; + + config = ctx->config; + if (ctx->event_channel != NULL) { + ret = mk_event_channel_destroy(config->ch_evl, + config->ch_notif[0], + config->ch_notif[1], + ctx->event_channel); + if (ret != 0) { + /* make sure to close file descriptors */ + close(config->ch_notif[0]); + close(config->ch_notif[1]); + } + flb_free(ctx->event_channel); + ctx->event_channel = NULL; + } + + if (ctx->event_loop != NULL) { + mk_event_loop_destroy(ctx->event_loop); + ctx->event_loop = NULL; + } + + return 0; +} + flb_ctx_t *flb_create() { int ret; @@ -184,37 +261,13 @@ flb_ctx_t *flb_create() return NULL; } - /* Create the event loop to receive notifications */ - ctx->event_loop = mk_event_loop_create(256); - if (!ctx->event_loop) { - flb_config_exit(ctx->config); - flb_free(ctx); - return NULL; - } - config->ch_evl = ctx->event_loop; - - /* Prepare the notification channels */ - ctx->event_channel = flb_calloc(1, sizeof(struct mk_event)); - if (!ctx->event_channel) { - perror("calloc"); + ret = flb_create_event_loop(ctx); + if (ret != 0) { flb_config_exit(ctx->config); flb_free(ctx); return NULL; } - MK_EVENT_ZERO(ctx->event_channel); - - ret = mk_event_channel_create(config->ch_evl, - &config->ch_notif[0], - &config->ch_notif[1], - ctx->event_channel); - if (ret != 0) { - flb_error("[lib] could not create notification channels"); - flb_stop(ctx); - flb_destroy(ctx); - return NULL; - } - #ifdef FLB_HAVE_AWS_ERROR_REPORTER if (is_error_reporting_enabled()) { error_reporter = flb_aws_error_reporter_create(); diff --git a/src/flb_utils.c b/src/flb_utils.c index e816651fb4d..e51602ed598 100644 --- a/src/flb_utils.c +++ b/src/flb_utils.c @@ -89,6 +89,9 @@ void flb_utils_error(int err) case FLB_ERR_CFG_FLUSH_REGISTER: msg = "could not register timer for flushing"; break; + case FLB_ERR_EVENT_LOOP_CREATE: + msg = "could not create event loop"; + break; case FLB_ERR_INPUT_INVALID: msg = "invalid input type"; break; diff --git a/src/fluent-bit.c b/src/fluent-bit.c index be5685a1b9e..1f38d3b9574 100644 --- a/src/fluent-bit.c +++ b/src/fluent-bit.c @@ -1415,7 +1415,18 @@ static int flb_main_run(int argc, char **argv) #ifdef FLB_HAVE_FORK /* Run in background/daemon mode */ if (config->daemon == FLB_TRUE) { +#if defined(__FreeBSD__) || defined(__NetBSD__) || \ + defined(__OpenBSD__) || defined(__DragonFly__) + flb_destroy_event_loop(ctx); +#endif flb_utils_set_daemon(config); +#if defined(__FreeBSD__) || defined(__NetBSD__) || \ + defined(__OpenBSD__) || defined(__DragonFly__) + if (flb_create_event_loop(ctx) != 0) { + flb_error("[daemon] failed to recreate event loop after daemonizing"); + flb_utils_error(FLB_ERR_EVENT_LOOP_CREATE); + } +#endif } #endif