* babeltrace 2.1.2: sink.ctf.fs does not deduplicate identical clocks
@ 2026-08-04 15:27 MOESSBAUER, Felix via lttng-dev
2026-08-06 18:45 ` Philippe Proulx via lttng-dev
0 siblings, 1 reply; 2+ messages in thread
From: MOESSBAUER, Felix via lttng-dev @ 2026-08-04 15:27 UTC (permalink / raw)
To: MOESSBAUER, Felix via lttng-dev
[-- Attachment #1: Type: text/plain, Size: 1695 bytes --]
Hi,
while porting the bt2-ftrace-to-ctf [1] plugin to babeltrace 2.1, I
noticed that the sink.ctf.fs creates invalid clock definitions if
multiple stream-classes share the same clock-class. In this case, the
clock definition is added multiple times to the CTF 2 metadata,
resulting in the following assertion on read-back:
ERROR: [Babeltrace CLI] (babeltrace2.c:2705)
Command-line error: retcode=1
CAUSED BY [Source auto-discovery] (autodisc/autodisc.c:493)
babeltrace.support-info query failed.
CAUSED BY [libbabeltrace2] (lib/graph/query-executor.c:233)
Component class's "query" method failed: query-exec-
addr=0x55cba00c12e0, cc-addr=0x55cba00b4100, cc-type=SOURCE, cc-
name="fs", cc-partial-descr="Read CTF traces from
the file sy", cc-is-frozen=0, cc-so-handle-addr=0x55cba00b1930, cc-
so-handle-path="<...>/build/babeltrace-plugin-ctf.so",
object="babeltrace.support-info", params-addr=0x55cba00cd470, params-
type=MAP, params-element-count=2, log-level=WARNING
CAUSED BY ['source.ctf.fs'] (plugins/ctf/common/src/metadata/json/ctf-
2-metadata-stream-parser.cpp:130)
[1:1 @ 8512 bytes] Invalid fragment #12.
CAUSED BY ['source.ctf.fs'] (plugins/ctf/common/src/metadata/json/ctf-
2-metadata-stream-parser.cpp:367)
[1:1 @ 17024 bytes] Duplicate clock class fragment with ID `local`.
When running with MIP=0, the CTF 1.8 data does not have this issue (or
the reader ignores the duplicated definitions).
[1] https://github.com/siemens/bt2-ftrace-to-ctf
Attached you will find an AI generated reproducer using just the
babeltrace2 Python bindings.
Best regards,
Felix Moessbauer
--
Siemens AG
Linux Expert Center
Friedrich-Ludwig-Bauer-Str. 3
85748 Garching, Germany
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: repro.py --]
[-- Type: text/x-python3; name="repro.py", Size: 4650 bytes --]
#!/usr/bin/env python3
#
# Minimal, self-contained reproducer for a babeltrace2 CTF-2 sink bug.
#
# A single trace that contains two data stream classes sharing ONE clock class
# is written to CTF 2 by sink.ctf.fs. The sink emits one `clock-class` metadata
# fragment PER stream class (both with the same id, here "the_clock") instead
# of emitting the shared clock class only once. Reading the resulting trace
# back then fails with:
#
# Duplicate clock class fragment with ID `the_clock`.
#
# This depends only on babeltrace2 and its bundled `ctf`/`utils` plugins; no
# external trace files or third-party plugins are needed.
#
# Usage:
# python3 repro.py <output-dir>
#
# The script writes the trace in a child process (so sink.ctf.fs flushes the
# metadata file on component teardown), then reads it back in the parent.
import os
import subprocess
import sys
import bt2
class TheIter(bt2._UserMessageIterator):
def __init__(self, config, port):
stream = port.user_data
self._msgs = [
self._create_stream_beginning_message(stream),
self._create_stream_end_message(stream),
]
self._i = 0
def __next__(self):
if self._i >= len(self._msgs):
raise StopIteration
msg = self._msgs[self._i]
self._i += 1
return msg
@bt2.plugin_component_class
class TheSource(bt2._UserSourceComponent, message_iterator_class=TheIter):
"""One trace, two stream classes, ONE shared clock class."""
def __init__(self, config, params, obj):
tc = self._create_trace_class(assigns_automatic_stream_class_id=False)
cc = self._create_clock_class(frequency=1000000000, name="the_clock")
sc0 = tc.create_stream_class(
id=0,
default_clock_class=cc,
supports_packets=True,
assigns_automatic_stream_id=False,
)
sc1 = tc.create_stream_class(
id=1,
default_clock_class=cc,
supports_packets=True,
assigns_automatic_stream_id=False,
)
trace = tc()
self._add_output_port("out0", trace.create_stream(sc0, id=0))
self._add_output_port("out1", trace.create_stream(sc1, id=1))
def write_trace(out_dir):
ctf = bt2.find_plugin("ctf")
utils = bt2.find_plugin("utils")
sink_cls = ctf.sink_component_classes["fs"]
# CTF 2 requires MIP 1. The ctf.fs sink has a single input port, so mux
# the two source ports into it.
graph = bt2.Graph(mip_version=1)
src = graph.add_component(TheSource, "src")
muxer = graph.add_component(utils.filter_component_classes["muxer"], "mux")
sink = graph.add_component(
sink_cls, "sink", params={"path": out_dir, "ctf-version": "2"}
)
out_ports = list(src.output_ports.values())
graph.connect_ports(out_ports[0], list(muxer.input_ports.values())[0])
graph.connect_ports(out_ports[1], list(muxer.input_ports.values())[1])
graph.connect_ports(
list(muxer.output_ports.values())[0],
list(sink.input_ports.values())[0],
)
graph.run()
def read_trace(trace_dir):
for _ in bt2.TraceCollectionMessageIterator(trace_dir):
pass
def main():
if len(sys.argv) < 2:
print("usage: repro.py <output-dir>", file=sys.stderr)
return 2
# Internal entry points, invoked as child processes.
if sys.argv[1] == "--write":
write_trace(sys.argv[2])
return 0
if sys.argv[1] == "--read":
read_trace(sys.argv[2])
return 0
out_dir = sys.argv[1]
trace_dir = os.path.join(out_dir, "trace")
# Write in a child process so the sink flushes the metadata on teardown.
subprocess.run([sys.executable, __file__, "--write", out_dir], check=True)
print("wrote CTF-2 trace to", trace_dir)
with open(os.path.join(trace_dir, "metadata"), "rb") as f:
n_clock = f.read().count(b'"type":"clock-class"')
print("clock-class fragments written to metadata:", n_clock)
# Read back with the CLI for a clear, unwrapped error message.
proc = subprocess.run(
["babeltrace2", trace_dir],
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE,
text=True,
)
if proc.returncode != 0:
print("\nREAD-BACK FAILED (bug reproduced):", file=sys.stderr)
for line in proc.stderr.splitlines():
if "Duplicate clock class" in line or "Invalid fragment" in line:
print(" " + line.split("] ", 1)[-1], file=sys.stderr)
return 1
print("read-back OK (bug NOT reproduced)")
return 0
if __name__ == "__main__":
sys.exit(main())
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: babeltrace 2.1.2: sink.ctf.fs does not deduplicate identical clocks
2026-08-04 15:27 babeltrace 2.1.2: sink.ctf.fs does not deduplicate identical clocks MOESSBAUER, Felix via lttng-dev
@ 2026-08-06 18:45 ` Philippe Proulx via lttng-dev
0 siblings, 0 replies; 2+ messages in thread
From: Philippe Proulx via lttng-dev @ 2026-08-06 18:45 UTC (permalink / raw)
To: MOESSBAUER, Felix; +Cc: MOESSBAUER, Felix via lttng-dev
On Tue, Aug 4, 2026 at 11:28 AM MOESSBAUER, Felix via lttng-dev
<lttng-dev@lists.lttng.org> wrote:
>
> Hi,
>
> while porting the bt2-ftrace-to-ctf [1] plugin to babeltrace 2.1, I
> noticed that the sink.ctf.fs creates invalid clock definitions if
> multiple stream-classes share the same clock-class. In this case, the
> clock definition is added multiple times to the CTF 2 metadata,
> resulting in the following assertion on read-back:
>
> ERROR: [Babeltrace CLI] (babeltrace2.c:2705)
> Command-line error: retcode=1
> CAUSED BY [Source auto-discovery] (autodisc/autodisc.c:493)
> babeltrace.support-info query failed.
> CAUSED BY [libbabeltrace2] (lib/graph/query-executor.c:233)
> Component class's "query" method failed: query-exec-
> addr=0x55cba00c12e0, cc-addr=0x55cba00b4100, cc-type=SOURCE, cc-
> name="fs", cc-partial-descr="Read CTF traces from
> the file sy", cc-is-frozen=0, cc-so-handle-addr=0x55cba00b1930, cc-
> so-handle-path="<...>/build/babeltrace-plugin-ctf.so",
> object="babeltrace.support-info", params-addr=0x55cba00cd470, params-
> type=MAP, params-element-count=2, log-level=WARNING
> CAUSED BY ['source.ctf.fs'] (plugins/ctf/common/src/metadata/json/ctf-
> 2-metadata-stream-parser.cpp:130)
> [1:1 @ 8512 bytes] Invalid fragment #12.
> CAUSED BY ['source.ctf.fs'] (plugins/ctf/common/src/metadata/json/ctf-
> 2-metadata-stream-parser.cpp:367)
> [1:1 @ 17024 bytes] Duplicate clock class fragment with ID `local`.
See <https://review.lttng.org/c/babeltrace/+/18460>.
Let's continue the discussion on Gerrit if need be.
Thank you for the report and reproducer.
Philippe
>
> When running with MIP=0, the CTF 1.8 data does not have this issue (or
> the reader ignores the duplicated definitions).
>
> [1] https://github.com/siemens/bt2-ftrace-to-ctf
>
> Attached you will find an AI generated reproducer using just the
> babeltrace2 Python bindings.
>
> Best regards,
> Felix Moessbauer
>
> --
> Siemens AG
> Linux Expert Center
> Friedrich-Ludwig-Bauer-Str. 3
> 85748 Garching, Germany
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-06 18:46 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-04 15:27 babeltrace 2.1.2: sink.ctf.fs does not deduplicate identical clocks MOESSBAUER, Felix via lttng-dev
2026-08-06 18:45 ` Philippe Proulx via lttng-dev
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox