`bat /dev/zero | head -c 10` hangs while `cat` is not
What steps will reproduce the bug?
$ bat /dev/zero | head -c 10 # hangs forever
^C
$ cat /dev/zero | head -c 10 # while this does not
$ cat /dev/zero | head -c 10 | hexdump # FYI
0000000 0000 0000 0000 0000 0000
000000a
$ bash -c 'bat /dev/zero | head -c 10' # hangs, doesn't matter what shell I used
^C
$ dash -c 'bat /dev/zero | head -c 10'
^C
$ fish -c 'bat /dev/zero | head -c 10'
^C
What happens?
hangs
What did you expect to happen instead?
does not hang, and print ten NUL characters
How did you install bat?
bat version and environment
- bat 0.23.0 (871abd27)
- Arch Linux x64 (linux kernel: 6.4.11-zen2-1-zen)
- fish, version 3.6.1
- alacritty 0.12.2 (9d9982df)
- less 643
Result of bat --diagnostic
Software version
bat 0.23.0 (871abd27)
Operating system
Linux 6.4.11-zen2-1-zen
Command-line
bat --diagnostic
Environment variables
SHELL=/usr/bin/fish
PAGER=<not set>
LESS='-SFR --mouse'
LANG=ko_KR.UTF-8
LC_ALL=ko_KR.UTF-8
BAT_PAGER='less -SFR --mouse'
BAT_CACHE_PATH=<not set>
BAT_CONFIG_PATH=<not set>
BAT_OPTS=<not set>
BAT_STYLE=<not set>
BAT_TABS=<not set>
BAT_THEME=<not set>
XDG_CONFIG_HOME=/home/xnuk/.config
XDG_CACHE_HOME=<not set>
COLORTERM=truecolor
NO_COLOR=<not set>
MANPAGER=<not set>
System Config file
Could not read contents of '/etc/bat/config': No such file or directory (os error 2).
Config file
Could not read contents of '/home/xnuk/.config/bat/config': No such file or directory (os error 2).
Custom assets metadata
Could not read contents of '/home/xnuk/.cache/bat/metadata.yaml': No such file or directory (os error 2).
Custom assets
'/home/xnuk/.cache/bat' not found
Compile time information
- Profile: release
- Target triple: x86_64-unknown-linux-gnu
- Family: unix
- OS: linux
- Architecture: x86_64
- Pointer width: 64
- Endian: little
- CPU features: fxsr,sse,sse2
- Host: x86_64-unknown-linux-gnu
Less version
> less --version
less 643 (PCRE2 regular expressions)
Copyright (C) 1984-2023 Mark Nudelman
less comes with NO WARRANTY, to the extent permitted by law.
For information about the terms of redistribution,
see the file named README in the less distribution.
Home page: https://greenwoodsoftware.com/less
I figured out the problem here. You can see it on line 261 of src/input.rs The input is being read in one line at a time or until the EOT character has been reached. Because /dev/zero is an infinite stream of zeros, it doesn't have a newline character or a EOT character, which means the first line never finishes being read and the program hangs.
After reading a the source code of the cat commands from FreeBSD source and GNU coreutils I understand why they can handle reading from /dev/zero and bat cannot. The cat command typically reads in an exact amount of characters into it's internal buffer than prints that chunk before refilling its buffer with more characters from the file. The cat command never waits for any delimiters which is why it can handle an infinite stream of text.
The README.md does mention that bat should be a drop in replacement for cat when used non-interactively, so refactoring to support this does seem like it's within the projects goals.
This is a very intriguing problem and I would love to know what the core maintainers think should be done.
Thanks for reporting and thanks @johnmatthiggins
for investigating. It has been mentioned by a maintainer before that bat is designed to output only after receiving a \n character in the input: https://github.com/sharkdp/bat/issues/836#issuecomment-589880495
It's worth noting though that something similar was reported before and is accepted as a valid bug: https://github.com/sharkdp/bat/issues/636
I believe the syntax highlighting library we are using expects to be fed (complete) single line inputs, so I'm not sure how solvable this will turn out to be in practice...