Manually assigning a file descriptor number will happily interfere with fish's own internal selection of file descriptor numbers. This is possibly the same root cause as #3303 and would be resolved blocked by the proposal in #12547. I don't think this is a straight duplicate of either of those; my apologies if I'm wrong here.
$ fish --no-config
rpatterson@macbook-pro ~> echo $FISH_VERSION
4.5.0
rpatterson@macbook-pro ~> cat Downloads/test.py
import os, sys
# Verify stdout is actually a tty
is_tty = os.isatty(1)
# Write the result to fd 3 (captured by fish)
os.write(3, f"stdout_isatty={is_tty}\n".encode())
# Write visible output to stdout (which should be /dev/tty)
print(f"(visible on tty)")
rpatterson@macbook-pro ~> set x (python Downloads/test.py 3>&1 >/dev/tty); echo "x: $x"
(visible on tty)
x: stdout_isatty=True
rpatterson@macbook-pro ~> cd . # Do nothing
rpatterson@macbook-pro ~> set x (python Downloads/test.py 3>&1 >/dev/tty); echo "x: $x"
x: stdout_isatty=False (visible on tty)
rpatterson@macbook-pro ~> cd . # Do nothing again
rpatterson@macbook-pro ~> set x (python Downloads/test.py 3>&1 >/dev/tty); echo "x: $x"
(visible on tty)
x: stdout_isatty=True
rpatterson@macbook-pro ~> cd . # Do nothing an odd number of times
rpatterson@macbook-pro ~> set x (python Downloads/test.py 3>&1 >/dev/tty); echo "x: $x"
x: stdout_isatty=False (visible on tty)
My goal here is to run an interactive command (attached to the TTY) with the output to FD 3 gets stored in the variable. In this demonstration, we see that writing to FD 1 (stdout) actually goes to FD 3, because fish incorrectly merged the two FDs.
Notes:
- The
cd is an infuriating red herring. Internally, cd causes fish to open the directory FD, which consumes/releases an FD, shifting around which ones are free.
wopen_cloexec("/dev/tty") goes to the next free FD.
dup2_list_resolve_chain can clobber that FD.
Manually assigning a file descriptor number will happily interfere with fish's own internal selection of file descriptor numbers. This is possibly the same root cause as #3303 and would be
resolvedblocked by the proposal in #12547. I don't think this is a straight duplicate of either of those; my apologies if I'm wrong here.My goal here is to run an interactive command (attached to the TTY) with the output to FD 3 gets stored in the variable. In this demonstration, we see that writing to FD 1 (stdout) actually goes to FD 3, because fish incorrectly merged the two FDs.
Notes:
cdis an infuriating red herring. Internally,cdcauses fish to open the directory FD, which consumes/releases an FD, shifting around which ones are free.wopen_cloexec("/dev/tty")goes to the next free FD.dup2_list_resolve_chaincan clobber that FD.