Windows: Winsock send errors never reach net_error, so the keepalive pool reuses a dead connection ("could not write forward header")
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 35/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- c
- Ambito
- backend, networking
Direzione di ricerca
Start with src/flb_io.c around net_io_propagate_critical_error() and the send failure path, then trace connection release and reuse in src/flb_upstream.c. Read the Windows socket error handling in include/fluent-bit/flb_socket.h and event mask update in lib/monkey/mk_core/mk_event_libevent.c; reproduce using the issue's Windows sender and Linux receiver steps. Done when a failed send discards the dead pooled connection and the next flush reconnects.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Bug Report
Describe the bug
On Windows, a failed send() on a plain TCP upstream connection never sets its net_error. With net.keepalive on (the default) the dead connection goes back to the keepalive pool and is handed out again, so after a receiver restart a forwarder busy at that moment keeps writing into it instead of reconnecting.
I run Fluent Bit 5.1.5 (the latest release) on a fleet of 15 Windows machines forwarding to one Linux receiver. After a receiver restart on 2026-11-06 at 14:26 CET (again at 14:28), one machine logged could not write forward header 2,773 times in 47 minutes; the other 14 (same version and output config) resumed within about two minutes. At the next receiver restart (2026-11-07 00:36 CET) the same machine failed 223 times in 4 minutes, until I restarted its service. It was sending a backlog both times; machines whose pooled connection was idle recovered silently. Nothing was lost (filesystem buffer, retry_limit false), but the receiver got nothing from it meanwhile.
The affected machine's log (message texts verbatim; times and counts from my review):
- 14:26:14 to 15:13:14, about once per second, only:
[error] [output:forward:forward.0] could not write forward header [ warn] [engine] failed to flush chunk '...', retry in ... seconds: task_id=..., input=... > output=forward.0 (out_id=0) - No
[net]or connect error. The receiver was up and the others were delivering, so a new connection would have worked: the attempts reused the dead pooled one. - 15:13:14: all buffered chunks (task_id 0 to 332)
succeeded at retry 1to11in one burst, consistent with the backoff leaving the connection idle for 30 s and the idle sweep dropping it.
Cause, from the source (master fc966e9, 2026-11-07)
net_io_propagate_critical_error()(src/flb_io.c:263-279) switches onerrno. Winsock reports throughWSAGetLastError()and leaveserrnoalone, so on Windows nothing matches andnet_errorstays-1.flb_upstream_conn_release()recycles a keepalive connection whenevernet_error == -1(src/flb_upstream.c:984-987).- The handout check in
flb_upstream_conn_get()(src/flb_upstream.c:865-879) misses it: on Windowsflb_socket_error()isevutil_socket_geterror()(include/fluent-bit/flb_socket.h:31), which returns the thread'sWSAGetLastError()and readsSO_ERRORonly when that isWSAEWOULDBLOCK. - The close watch on idle pooled connections never fires: the libevent backend of the Windows build maps only READ and WRITE (
lib/monkey/mk_core/mk_event_libevent.c:228-233), andMK_EVENT_CLOSE(16 | 8 | 8192) has neither bit. Only the idle sweep (src/flb_upstream.c:1178-1187) remains, and a busy forwarder never idles for 30 s: each failed attempt releases the connection and refreshests_available.
On Linux errno carries ECONNRESET/EPIPE and the same code works. TLS is not affected: tls_net_read()/tls_net_write() in src/tls/openssl.c set net_error themselves on every fatal error.
A second defect, found by reading only: _mk_event_update() (lib/monkey/mk_core/mk_event_libevent.c:159-201) never updates event->mask. A pooled connection stays registered as MK_EVENT_CLOSE; when its send() would block, net_io_write_async() re-registers it for MK_EVENT_WRITE, then reads the stale mask (src/flb_io.c:516, 530) and returns -1 (553-559) without setting net_error.
917dc321 (2026-11-07, "io: mark blocking send timeouts as critical connection errors") added ETIMEDOUT to the switch and a #ifndef FLB_SYSTEM_WINDOWS branch to fd_io_write() (src/flb_io.c:343-354); Windows is unchanged. v5.1.5 (0039c4f0) has the same code a few lines earlier (src/flb_io.c:260-275, src/flb_upstream.c:966-1006); the 5.1 branch head (537321f) has no change. I found no open PR.
To Reproduce
As posted in #10079 on 2025-04-25:
- Linux:
fluent-bit -i forward -o null. - Windows: a
dummyinput and aforwardoutput to that host,net.keepaliveat its default. - Restart the receiver while the Windows side is sending.
- Windows logs
could not write forward headeron every attempt until 30 s pass without one or the service restarts. Withnet.keepalive offthe next flush succeeds.
My evidence is production on 5.1.5 (logs above) plus the source reading, not a lab run.
Expected behavior
The first failed send() marks the connection broken, flb_upstream_conn_release() destroys it and the next attempt connects anew, as on Linux. A receiver restart costs at most one failed flush per busy connection.
Your Environment
- Version used: 5.1.5 on Windows (MSI) and on the Linux receiver
- Configuration: forwarder output during both incidents; receiver input
# [SERVICE] flush 5, storage.path set; inputs winevtlog, tail (storage.type filesystem) [OUTPUT] name forward match * host <receiver> port 24224 retry_limit false storage.total_limit_size 300M # not set: net.keepalive (default on), Require_ack_response (default off)[INPUT] name forward listen 0.0.0.0 port 24224 buffer_chunk_size 1M buffer_max_size 8M storage.type filesystem - Environment and OS: physical Windows 11 machine (the affected one); receiver: Linux VM, systemd; no containers
- Filters and plugins: winevtlog, tail → forward over plain TCP (no TLS, no shared_key); receiver forward → file; no filters
Additional context
- Workaround, rolled out to all 15 machines from 2026-11-07:
net.keepalive off(each flush opens its own connection, a failed one is always destroyed) plusRequire_ack_response On(a chunk counts as sent only after the ack). At a planned receiver restart on 2026-11-08 the 14 machines converted by then logged nothing; all 15 resumed. - #10079 (Windows 3.1.7 forwarders to Linux, same message, about 70 % data loss with
retry_limit 5) was reproduced there on 3.2.0 and 4.0.1 and closed as stale on 2025-07-29. - Fix sketch: capture the error right after
send()/recv()fails (WSAGetLastError()on_WIN32), beforenet_io_restore_event()runs (src/flb_io.c:565), and pass it tonet_io_propagate_critical_error(); there map theWSAE*codes (WSAECONNRESETis 10054, notECONNRESET) or treat every error exceptWSAEWOULDBLOCKas critical, as the TLS backend does._mk_event_update()should setevent->mask. A narrower stopgap: out_forward could callflb_upstream_conn_recycle(u_conn, FLB_FALSE)after a failed write (plugins/out_forward/forward.c:1550-1563). - I can test a patch build on one of my Windows machines.
- Lingua principale
- C
- Stelle
- 8.2k
- Fork
- 2k
- Merge medio
- 3g 20h
- PR unite (30g)
- 99
Preparare l'ambiente
Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.
- Include un Dockerfile o un file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di fluent/fluent-bit
-
in_tail: files falsely detected as rotated on macOS with threaded inputs, causing duplicate recordsForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
fluent/fluent-bit#12780 ·
I maintainer di solito rispondono entro 1 giorno
-
status: waiting-for-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
fluent/fluent-bit#12683 · 2 commenti · 6 reazioni ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
fluent/fluent-bit#12657 ·
I maintainer di solito rispondono entro 1 giorno
-
http: Transfer-Encoding chunked plus Content-Length hangs forever (CL branch shadows the chunked path)Forse già presa @sarankumar1325 l’ha presa 14 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
fluent/fluent-bit#12656 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
fluent/fluent-bit#12649 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di fluent/fluent-bit
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
micropython/micropython#19942 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 3 giorni
-
快速入门那里会不会对新手不太友好,提出优化方案Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 84/100
-
-disable-symbolserver is ignored on macOS/Linux: PDBs are still downloaded from msdl.microsoft.comAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 77/100