omfwd: flush pending data before zip teardown

Why:
Tests for imptcp stream compression exposed a teardown gap when
omfwd used stream compression with
compression.stream.flushOnTXEnd="off". The final compressed bytes
were only emitted during target destruction, so pending buffered data
needed an explicit send before the zlib stream was finished.

Impact:
Sender teardown now preserves buffered TCP data before final stream
compression shutdown.

Before/After:
Before, the final message could be stranded until teardown and lost
to a clean receiver shutdown. After, omfwd flushes buffered data
before calling doZipFinish().

Technical Overview:
DestructTargetData() now checks for buffered TCP payload before the
target is dismantled.
If buffered data exists on a connected target, it is sent through the
normal TCPSendBuf() path with flush semantics before zip teardown.
The existing doZipFinish() call remains responsible for emitting the
final Z_FINISH bytes for stream compression.
This keeps teardown behavior aligned with the regular commit path
without changing normal transactional sending logic.

With the help of AI-Agents: Codex
This commit is contained in:
Rainer Gerhards 2026-04-20 18:12:28 +02:00
parent be0d4917d5
commit 375a009307

View File

@ -295,6 +295,7 @@ ENDinitConfVars
static rsRetVal doTryResume(targetData_t *);
static rsRetVal doZipFinish(targetData_t *);
static rsRetVal TCPSendBuf(targetData_t *, uchar *, unsigned, sbool);
/* this function gets the default template. It coordinates action between
* old-style and new-style configuration parts.
@ -692,7 +693,13 @@ finalize_it:
}
static void DestructTargetData(targetData_t *const pTarget, const sbool bIsRebind) {
// TODO: do we need to do a final send? if so, old bug!
if (pTarget->bIsConnected && pTarget->offsSndBuf != 0) {
rsRetVal localRet = TCPSendBuf(pTarget, pTarget->sndBuf, pTarget->offsSndBuf, IS_FLUSH);
if (localRet == RS_RET_OK || localRet == RS_RET_DEFER_COMMIT || localRet == RS_RET_PREVIOUS_COMMITTED) {
pTarget->offsSndBuf = 0;
}
}
doZipFinish(pTarget);
if (pTarget->pNetstrm != NULL) {