This is an automated email from the ASF dual-hosted git repository.
bneradt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 4c2e3e2fbb txn_box: Log text block reload failures (#13411)
4c2e3e2fbb is described below
commit 4c2e3e2fbb5ed5ab9dcac8f8f719fd35b313c5d8
Author: Brian Neradt <[email protected]>
AuthorDate: Fri Jul 31 17:07:21 2026 -0500
txn_box: Log text block reload failures (#13411)
Text blocks silently lose their file-backed content when a periodic
reload can no longer read the configured file. Requests then see an
empty block without an operator-visible diagnostic.
This logs the transition to unavailable content once and adds
regression coverage for a file that becomes unreadable. This also
documents the error and fallback behavior.
The original txn_box repository is defunct, so fixes for the plugin are
now tracked in the Traffic Server repository. This patch addresses:
https://github.com/SolidWallOfCode/txn_box/issues/90
---
.../plugins/txn_box/user/DirectiveReference.en.rst | 7 ++++---
plugins/experimental/txn_box/plugin/src/text_block.cc | 16 ++++++++++++++--
.../txn_box/static_file/static_file.replay.yaml | 5 +++++
.../txn_box/static_file/txn_box_static_file.test.py | 13 +++++++++++++
.../pluginTest/txn_box/static_file/unreadable.txt | 1 +
5 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/doc/admin-guide/plugins/txn_box/user/DirectiveReference.en.rst
b/doc/admin-guide/plugins/txn_box/user/DirectiveReference.en.rst
index 25fcc18fb2..f53ae06aab 100755
--- a/doc/admin-guide/plugins/txn_box/user/DirectiveReference.en.rst
+++ b/doc/admin-guide/plugins/txn_box/user/DirectiveReference.en.rst
@@ -434,9 +434,10 @@ Utility
One of ``path`` and ``text`` must be present. If both are present ``path``
takes precedence. The
file contents are used if the file can be read, otherwise the value in
``text`` is used. If
only ``path`` is present it is a configuration error if the file specified
by ``path`` cannot
- be read. If update checking is enabled and the file disappears, the text
will be used. If the
- file is avaiable during a subsequent check and is updated (newer than the
last load time) it will
- be loaded and used instead of the text.
+ be read. If update checking is enabled and the file disappears or becomes
unreadable, an error is
+ logged and the text fallback, if configured, will be used. If the file is
available during a
+ subsequent check and is updated (newer than the last load time) it will be
loaded and used instead
+ of the text.
.. seealso:: :ex:`text-block`.
diff --git a/plugins/experimental/txn_box/plugin/src/text_block.cc
b/plugins/experimental/txn_box/plugin/src/text_block.cc
index 01644c2790..8b2d68821b 100644
--- a/plugins/experimental/txn_box/plugin/src/text_block.cc
+++ b/plugins/experimental/txn_box/plugin/src/text_block.cc
@@ -319,8 +319,20 @@ Do_text_block_define::Updater::operator()()
// If control flow gets here, the file is no longer accessible and the
content
// should be cleared. If the file shows up again, it should have a modified
time
// later than the previously existing file, so that can be left unchanged.
- std::unique_lock lock(_block->_content_mutex);
- _block->_content.reset();
+ bool content_was_available = false;
+ {
+ std::unique_lock lock(_block->_content_mutex);
+ content_was_available = static_cast<bool>(_block->_content);
+ _block->_content.reset();
+ }
+
+ if (content_was_available) {
+ std::string msg;
+
+ swoc::bwprint(msg, R"([{}] Unable to read file "{}" for text block "{}" -
{}.)", Config::PLUGIN_TAG, _block->_path,
+ _block->_name, ec);
+ ts::Log_Error(msg);
+ }
}
/*
------------------------------------------------------------------------------------
*/
diff --git
a/tests/gold_tests/pluginTest/txn_box/static_file/static_file.replay.yaml
b/tests/gold_tests/pluginTest/txn_box/static_file/static_file.replay.yaml
index 89ba1bef7c..f100520723 100644
--- a/tests/gold_tests/pluginTest/txn_box/static_file/static_file.replay.yaml
+++ b/tests/gold_tests/pluginTest/txn_box/static_file/static_file.replay.yaml
@@ -30,6 +30,11 @@ meta:
text: "Concert missing."
duration: "2 minutes 30 seconds"
+ - text-block-define:
+ name: "unreadable"
+ path: "unreadable.txt"
+ duration: "1 second"
+
# -- doc-jwt-->
- text-block-define:
name: "default-jwt"
diff --git
a/tests/gold_tests/pluginTest/txn_box/static_file/txn_box_static_file.test.py
b/tests/gold_tests/pluginTest/txn_box/static_file/txn_box_static_file.test.py
index 0741991081..520833d1a4 100644
---
a/tests/gold_tests/pluginTest/txn_box/static_file/txn_box_static_file.test.py
+++
b/tests/gold_tests/pluginTest/txn_box/static_file/txn_box_static_file.test.py
@@ -1,6 +1,8 @@
'''
Static file serving and handling.
'''
+import os.path
+
# @file
#
# Licensed to the Apache Software Foundation (ASF) under one
@@ -36,4 +38,15 @@ r = Test.TxnBoxTestAndRun(
remap=[['http://base.ex', ['--key=meta.txn-box.remap',
'static_file.replay.yaml']]])
ts = r.Variables.TS
ts.Setup.Copy("static_file.txt", ts.Variables.CONFIGDIR)
+ts.Setup.Copy("unreadable.txt", ts.Variables.CONFIGDIR)
ts.Disk.records_config.update({'proxy.config.diags.debug.enabled': 1,
'proxy.config.diags.debug.tags': 'txn_box|http'})
+ts.Disk.diags_log.Content = Testers.ContainsExpression(
+ 'Unable to read file ".*unreadable.txt" for text block "unreadable"',
+ "Verify that losing access to text block content is logged.")
+
+r.StillRunningAfter = ts
+
+tr = Test.AddTestRun("Make text block file unreadable")
+tr.StillRunningBefore = ts
+tr.Processes.Default.Command = f"chmod 000
{os.path.join(ts.Variables.CONFIGDIR, 'unreadable.txt')} && sleep 2"
+tr.Processes.Default.ReturnCode = 0
diff --git a/tests/gold_tests/pluginTest/txn_box/static_file/unreadable.txt
b/tests/gold_tests/pluginTest/txn_box/static_file/unreadable.txt
new file mode 100644
index 0000000000..998cbd95a8
--- /dev/null
+++ b/tests/gold_tests/pluginTest/txn_box/static_file/unreadable.txt
@@ -0,0 +1 @@
+Unreadable text block content.