[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
exec redirection is undone if fd (>9) has O_CLOEXEC
From: |
Koichi Murase |
Subject: |
exec redirection is undone if fd (>9) has O_CLOEXEC |
Date: |
Sat, 24 Feb 2024 14:11:25 +0900 |
I have a question. Maybe it's not technically a bug as fd > 9 is
involved, but the resulting behavior appears to be strange. I
received some reports from users in my project and tried to find out
what is happening. This is a reduced case:
#!/usr/bin/env bash
enable -f /path/to/lib/bash/fdflags fdflags
exec 50>1.txt
fdflags -s +cloexec 50
exec 50>2.txt
echo hello >&50
ls -l 1.txt 2.txt
The result is
$ ./reduced.sh
-rw-r--r-- 1 murase murase 6 2024-02-24 13:53:01 1.txt
-rw-r--r-- 1 murase murase 0 2024-02-24 13:53:01 2.txt
I expect that the string `hello' is saved in 2.txt, but it actually
goes into 1.txt. It turned out that the redirection "50>2.txt" is
actually performed, but it's immediately undone at the end of `exec'
command. The undo redirection is set up in the if statement starting
on redir.c:1288 (devel 43ecbeb3). The code comment says:
/* experimental: if we're saving a redirection to undo for a file
descriptor above SHELL_FD_BASE, add a redirection to be undone if
the exec builtin causes redirections to be discarded. There needs
to be a difference between fds that are used to save other fds and
then are the target of user redirections and fds that are just the
target of user redirections. We use the close-on-exec flag to tell
the difference; fds > SHELL_FD_BASE that have the close-on-exec flag
set are assumed to be fds used internally to save others. */
This piece of the code seems to be introduced in commit cac4cdbf
(ChangeLog says the change to redir.c was made on 2011-10-09):
https://git.savannah.gnu.org/cgit/bash.git/commit/?h=devel&id=cac4cdbf5
I'm just curious about the background of this different treatment for
"fds that are used to save other fds and then are the target of user
redirections" (quoted from the code comment). Also, it says
"experimental", but is there any alternative implementation, where the
user-supplied O_CLOEXEC fds are not undone?
Even if there is a technical background, the current behavior observed
by the users is strange, and this behavior doesn't seem to be
specified in the Bash documentation. The documentation just says
Redirections using file descriptors greater than 9 should be used
with care, as they may conflict with file descriptors the shell uses
internally.
but this behavior is non-trivial even if the user treats the fds with
"care". Note that, in the actual code, the number 50 in the above
reduced case is chosen to be a number that is not used (which can be
tested by e.g. « ! : >&50 ». There can be false-negatives with this
test, but that's fine).
--
Koichi
- exec redirection is undone if fd (>9) has O_CLOEXEC,
Koichi Murase <=