bug-bash
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]