From: Quentin Monnet <qmo@qmon.net>
To: Kumar Kartikeya Dwivedi <memxor@gmail.com>, bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Eduard Zingerman <eddyz87@gmail.com>,
Emil Tsalapatis <emil@etsalapatis.com>, Tejun Heo <tj@kernel.org>,
kkd@meta.com, kernel-team@meta.com
Subject: Re: [PATCH bpf-next v3 4/5] bpftool: Add option to wait for program stream output
Date: Fri, 25 Sep 2026 15:22:17 +0100 [thread overview]
Message-ID: <d64c6402-175f-4ea6-be6d-1a544a95c97c@qmon.net> (raw)
In-Reply-To: <20260925045536.1480933-5-memxor@gmail.com>
2026-09-25 06:55 UTC+0200 ~ Kumar Kartikeya Dwivedi <memxor@gmail.com>
> bpftool prog tracelog { stdout | stderr } PROG dumps the output buffered
> in a program stream and exits, which is all BPF_PROG_STREAM_READ_BY_FD
> allows. Waiting for further output means rerunning the command.
>
> Add a -w/--wait option that opens the stream with bpf_prog_stream_open()
> in its default blocking mode and keeps printing output as the program
> produces it. Flush each chunk as it arrives so redirected output is not
> held in stdio buffers while the next read blocks. Waiting is opt-in: the
> default dump keeps using BPF_PROG_STREAM_READ_BY_FD and exits once the
> buffered output is drained, so existing scripts behave the same on old and
> new kernels.
>
> A stream descriptor does not keep its program alive, so bpftool drops the
> program descriptor once the stream is open. Waiting then ends with EOF
> when the program is unloaded and otherwise runs until interrupted, as
> bpftool prog tracelog already does for the trace pipe. Exit from the
> SIGINT, SIGHUP and SIGTERM handlers like that command does. A flag set by
> the handler and checked before each read would miss a signal that lands
> between the check and the blocking read(), leaving bpftool asleep until the
> next print.
>
> Waiting requires BPF_PROG_STREAM_OPEN. The bpf() syscall fails with EINVAL
> for an unknown command, which bpftool reports as missing kernel support
> rather than degrading into a dump. Document the option and offer it in the
> bash completion.
>
> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> ---
> .../bpftool/Documentation/bpftool-prog.rst | 12 +++-
> tools/bpf/bpftool/bash-completion/bpftool | 2 +-
> tools/bpf/bpftool/main.c | 7 ++-
> tools/bpf/bpftool/main.h | 1 +
> tools/bpf/bpftool/prog.c | 62 ++++++++++++++++---
> 5 files changed, 73 insertions(+), 11 deletions(-)
>
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
> index 90fe8c61bf42..17aa0d560e32 100644
> --- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst
> +++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
> @@ -18,7 +18,8 @@ SYNOPSIS
>
> *OPTIONS* := { |COMMON_OPTIONS| |
> { **-f** | **--bpffs** } | { **-m** | **--mapcompat** } | { **-n** | **--nomount** } |
> -{ **-L** | **--use-loader** } | [ { **-S** | **--sign** } **-k** <private_key.pem> **-i** <certificate.x509> ] }
> +{ **-L** | **--use-loader** } | [ { **-S** | **--sign** } **-k** <private_key.pem> **-i** <certificate.x509> ] |
> +{ **-w** | **--wait** } }
>
> *COMMANDS* :=
> { **show** | **list** | **dump xlated** | **dump jited** | **pin** | **load** |
> @@ -186,6 +187,11 @@ bpftool prog tracelog { stdout | stderr } *PROG*
> error messages to the standard error stream. This facility should be used
> only for debugging purposes.
>
> + By default, bpftool prints the output buffered so far and exits. With
> + **-w** or **--wait**, it keeps printing new output as the program produces
> + it, until the program is unloaded or <Ctrl+C> is hit. Waiting requires a
> + kernel that supports opening a stream as a file descriptor.
If you do come back for a follow-up (looking at your reply to Sashiko,
regarding _exit(0)): it would be good to mention the mainline kernel
version that brings support for the feature, here.
> +
> bpftool prog run *PROG* data_in *FILE* [data_out *FILE* [data_size_out *L*]] [ctx_in *FILE* [ctx_out *FILE* [ctx_size_out *M*]]] [repeat *N*]
> Run BPF program *PROG* in the kernel testing infrastructure for BPF,
> meaning that the program works on the data and context provided by the
> @@ -267,6 +273,10 @@ OPTIONS
> Path to the X.509 certificate file in PEM or DER format, required when
> signing.
>
> +-w, --wait
> + When dumping a program stream with **bpftool prog tracelog**, wait for new
Nit: **bpftool prog tracelog { stderr | stdout }**
I think it doesn't apply otherwise?
> + output instead of exiting once the buffered output has been printed.
> +
> EXAMPLES
> ========
> **# bpftool prog show**
> diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
> index 9d9ced270685..a28af31937ad 100644
> --- a/tools/bpf/bpftool/bash-completion/bpftool
> +++ b/tools/bpf/bpftool/bash-completion/bpftool
> @@ -269,7 +269,7 @@ _bpftool()
> # Deal with options
> if [[ ${words[cword]} == -* ]]; then
> local c='--version --json --pretty --bpffs --mapcompat --debug \
> - --use-loader --base-btf --sign -i -k'
> + --use-loader --base-btf --sign -i -k --wait'
> COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
> return 0
> fi
> diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
> index 83884b21e708..d15fec71b64e 100644
> --- a/tools/bpf/bpftool/main.c
> +++ b/tools/bpf/bpftool/main.c
> @@ -31,6 +31,7 @@ bool block_mount;
> bool verifier_logs;
> bool relaxed_maps;
> bool use_loader;
> +bool wait_output;
> struct btf *base_btf;
> struct hashmap *refs_table;
> bool sign_progs;
> @@ -462,6 +463,7 @@ int main(int argc, char **argv)
> { "nomount", no_argument, NULL, 'n' },
> { "debug", no_argument, NULL, 'd' },
> { "use-loader", no_argument, NULL, 'L' },
> + { "wait", no_argument, NULL, 'w' },
> { "sign", no_argument, NULL, 'S' },
> { "base-btf", required_argument, NULL, 'B' },
> { 0 }
> @@ -480,7 +482,7 @@ int main(int argc, char **argv)
> bin_name = "bpftool";
>
> opterr = 0;
> - while ((opt = getopt_long(argc, argv, "VhpjfLmndSi:k:B:l",
> + while ((opt = getopt_long(argc, argv, "VhpjfLmndSi:k:B:lw",
> options, NULL)) >= 0) {
> switch (opt) {
> case 'V':
> @@ -530,6 +532,9 @@ int main(int argc, char **argv)
> case 'L':
> use_loader = true;
> break;
> + case 'w':
> + wait_output = true;
> + break;
> case 'S':
> sign_progs = true;
> use_loader = true;
> diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
> index 48eedcb9f6c0..fa2c877a3cbf 100644
> --- a/tools/bpf/bpftool/main.h
> +++ b/tools/bpf/bpftool/main.h
> @@ -89,6 +89,7 @@ extern bool block_mount;
> extern bool verifier_logs;
> extern bool relaxed_maps;
> extern bool use_loader;
> +extern bool wait_output;
> extern struct btf *base_btf;
> extern struct hashmap *refs_table;
> extern bool sign_progs;
> diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
> index 24e40dfab469..5e27b22444f2 100644
> --- a/tools/bpf/bpftool/prog.c
> +++ b/tools/bpf/bpftool/prog.c
> @@ -1119,21 +1119,66 @@ enum prog_tracelog_mode {
> TRACE_STDERR,
> };
>
> +static void exit_stream(int signo)
> +{
> + exit(0);
I'm not sure the deadlock Sashiko mentions can really happen, but given
that the loop already flushes, the suggestion to use _exit(0) here
instead makes sense. Fine by me as a follow-up.
Acked-by: Quentin Monnet <qmo@kernel.org>
Thanks,
Quentin
next prev parent reply other threads:[~2026-09-25 14:29 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-25 4:55 [PATCH bpf-next v3 0/5] File descriptor interface for BPF streams Kumar Kartikeya Dwivedi
2026-09-25 4:55 ` [PATCH bpf-next v3 1/5] bpf: Skip zero-length stream writes Kumar Kartikeya Dwivedi
2026-09-25 4:55 ` [PATCH bpf-next v3 2/5] bpf: Add file descriptor interface for program streams Kumar Kartikeya Dwivedi
2026-09-25 4:55 ` [PATCH bpf-next v3 3/5] libbpf: Add bpf_prog_stream_open() Kumar Kartikeya Dwivedi
2026-09-25 4:55 ` [PATCH bpf-next v3 4/5] bpftool: Add option to wait for program stream output Kumar Kartikeya Dwivedi
2026-09-25 5:15 ` sashiko-bot
2026-09-25 6:13 ` Kumar Kartikeya Dwivedi
2026-09-25 14:22 ` Quentin Monnet [this message]
2026-09-25 4:55 ` [PATCH bpf-next v3 5/5] selftests/bpf: Test program stream file descriptors Kumar Kartikeya Dwivedi
2026-09-25 6:14 ` [PATCH bpf-next v3 0/5] File descriptor interface for BPF streams Kumar Kartikeya Dwivedi
2026-09-25 21:10 ` patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d64c6402-175f-4ea6-be6d-1a544a95c97c@qmon.net \
--to=qmo@qmon.net \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=kernel-team@meta.com \
--cc=kkd@meta.com \
--cc=memxor@gmail.com \
--cc=tj@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox