BPF List
 help / color / mirror / Atom feed
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

  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