Bug Report
Describe the bug
out_s3's current_buffer_size accounting underflows (size_t wrap to ~2^64) whenever Fluent Bit starts with leftover files in store_dir. After the wrap, every subsequent buffer write fails the store_dir_limit_size check and the output rejects all new data ("Buffer is full") until the process is restarted — and the wrap re-occurs on any restart that again finds leftover files.
Root cause (verified in v5.0.9 and present on master)
set_files_context() in plugins/out_s3/s3_store.c assigns each pre-existing file a real size but never credits it to the running total:
file_size = cio_chunk_get_real_size(fsf->chunk);
if (file_size > 0) {
s3_file->size = (size_t) file_size;
}
/* ctx->current_buffer_size is NOT incremented here */
ctx->current_buffer_size starts at 0. When the startup resend (put_all_chunks()) successfully uploads a leftover file, s3_store_file_delete() runs:
ctx->current_buffer_size -= s3_file->size; /* 0 - size -> wraps */
current_buffer_size is size_t, so it wraps to 2^64 - <leftover bytes>. From then on s3_store_buffer_put()'s guard
if (ctx->store_dir_limit_size > 0 && ctx->current_buffer_size + bytes >= ctx->store_dir_limit_size)
is permanently true and the output logs, per attempted write:
[error] [output:s3:s3.3] Buffer is full: current_buffer_size=18446744073709481984, new_data=13772, store_dir_limit_size=2000000000 bytes
(18446744073709481984 = 2^64 − 69632 — exactly the leftover bytes resent and deleted at startup.)
For comparison, v2.2.2's set_files_context() left s3_file->size at 0 for loaded files, so the delete subtracted 0 — the accounting ignored leftovers but never underflowed. The regression is the size assignment being added without the matching credit.
To Reproduce
- Configure an
s3 output with store_dir and a nonzero store_dir_limit_size, against any reachable S3 endpoint.
- Run Fluent Bit with steady input; stop it while at least one buffered file remains in
store_dir (e.g. kill between upload_timeout cycles).
- Start Fluent Bit again. The startup scan re-sends and deletes the leftover file(s).
- Every subsequent write to that output fails with
Buffer is full: current_buffer_size=18446744073709....
Observed live on two independent instances (arm64, Debian trixie image ghcr.io/fluent/fluent-bit:5.0.9-debug), deterministic on every restart-with-leftovers.
Expected behavior
Leftover files loaded at startup should be counted into current_buffer_size (they occupy the store_dir the limit governs), i.e. set_files_context() should also do:
ctx->current_buffer_size += s3_file->size;
which both fixes the underflow and makes the limit honest about pre-existing usage. (Defensive clamping in s3_store_file_delete() — as s3_chunk_retry_exhausted_cleanup() already does — would additionally protect against any other asymmetry.)
Your Environment
- Version used: v5.0.9 (also inspected on current master — same code)
- Configuration:
s3 output, use_put_object on, compression gzip, total_file_size 8M, upload_timeout 10s, store_dir on a persistent volume, store_dir_limit_size 2G, workers 2
- Environment: Docker (
ghcr.io/fluent/fluent-bit:5.0.9-debug), linux/arm64 and linux/amd64
- Filters and plugins: custom input plugins (not involved — the accounting is output-side)
Bug Report
Describe the bug
out_s3'scurrent_buffer_sizeaccounting underflows (size_t wrap to ~2^64) whenever Fluent Bit starts with leftover files instore_dir. After the wrap, every subsequent buffer write fails thestore_dir_limit_sizecheck and the output rejects all new data ("Buffer is full") until the process is restarted — and the wrap re-occurs on any restart that again finds leftover files.Root cause (verified in v5.0.9 and present on master)
set_files_context()inplugins/out_s3/s3_store.cassigns each pre-existing file a real size but never credits it to the running total:ctx->current_buffer_sizestarts at 0. When the startup resend (put_all_chunks()) successfully uploads a leftover file,s3_store_file_delete()runs:current_buffer_sizeissize_t, so it wraps to2^64 - <leftover bytes>. From then ons3_store_buffer_put()'s guardis permanently true and the output logs, per attempted write:
(
18446744073709481984= 2^64 − 69632 — exactly the leftover bytes resent and deleted at startup.)For comparison, v2.2.2's
set_files_context()lefts3_file->sizeat 0 for loaded files, so the delete subtracted 0 — the accounting ignored leftovers but never underflowed. The regression is the size assignment being added without the matching credit.To Reproduce
s3output withstore_dirand a nonzerostore_dir_limit_size, against any reachable S3 endpoint.store_dir(e.g. kill betweenupload_timeoutcycles).Buffer is full: current_buffer_size=18446744073709....Observed live on two independent instances (arm64, Debian trixie image
ghcr.io/fluent/fluent-bit:5.0.9-debug), deterministic on every restart-with-leftovers.Expected behavior
Leftover files loaded at startup should be counted into
current_buffer_size(they occupy the store_dir the limit governs), i.e.set_files_context()should also do:which both fixes the underflow and makes the limit honest about pre-existing usage. (Defensive clamping in
s3_store_file_delete()— ass3_chunk_retry_exhausted_cleanup()already does — would additionally protect against any other asymmetry.)Your Environment
s3output,use_put_object on,compression gzip,total_file_size 8M,upload_timeout 10s,store_diron a persistent volume,store_dir_limit_size 2G,workers 2ghcr.io/fluent/fluent-bit:5.0.9-debug), linux/arm64 and linux/amd64