[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#31332: touch unnecessarily calls dup2
From: |
Assaf Gordon |
Subject: |
bug#31332: touch unnecessarily calls dup2 |
Date: |
Mon, 29 Oct 2018 21:17:07 -0600 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 |
tags 31332 notabug
close 31332
stop
On 2018-05-01 4:38 a.m., John Steele Scott wrote:
From
https://stackoverflow.com/questions/40446555/why-does-touch-call-the-dup2-syscall
address@hidden:/tmp$ touch --version | head -1
touch (GNU coreutils) 8.25
address@hidden:/tmp$ strace -ttt touch foo 2>&1 | tail -9
1525170579.952032 open("foo", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3
1525170579.952080 dup2(3, 0) = 0
1525170579.952119 close(3) = 0
1525170579.952156 utimensat(0, NULL, NULL, 0) = 0
1525170579.952209 close(0) = 0
1525170579.952257 close(1) = 0
1525170579.952294 close(2) = 0
1525170579.952333 exit_group(0) = ?
1525170579.952450 +++ exited with 0 +++
My analysis from that discussion:
It's a historical artifact.
The open()+dup2() pattern comes from the fd_reopen() function, which is
used
by several of the programs in the coreutils code base.
Not exactly an "artifact" - but an indented operation.
The goal of "fd_reopen" is not just to open a file,
but to ensure the returned file descriptor (an "int") has a specific
value.
For example, standard input (STDIN) is typically file descriptor value
0. calling fd_reopen first opens the file (the kernel returns file
descriptor 3), then it ensures file descriptor 0 is associated with the
same file (and then, calling "close(3)" gets rid of the other file
descriptor).
Checking how fd_reopen is used in coreutils, it is almost always used
to ensure STDIN/STDOUT point to the desired file(s):
====
$ git grep fd_reopen
src/csplit.c: if (! STREQ (name, "-") && fd_reopen (STDIN_FILENO, name,
O_RDONLY, 0) < 0)
src/dd.c:/* Restart on EINTR from fd_reopen(). */
src/dd.c:ifd_reopen (int desired_fd, char const *file, int flag, mode_t
mode)
src/dd.c: ret = fd_reopen (desired_fd, file, flag, mode);
src/dd.c: if (ifd_reopen (STDIN_FILENO, input_file, O_RDONLY |
input_flags, 0) < 0)
src/dd.c: || ifd_reopen (STDOUT_FILENO, output_file, O_RDWR |
opts, perms) < 0)
src/dd.c: && (ifd_reopen (STDOUT_FILENO, output_file, O_WRONLY
| opts, perms)
src/nohup.c: if (fd_reopen (STDIN_FILENO, "/dev/null", O_WRONLY, 0)
< 0)
src/nohup.c: ? fd_reopen (STDOUT_FILENO, file, flags, mode)
src/nohup.c: ? fd_reopen (STDOUT_FILENO, in_home,
flags, mode)
src/split.c: && fd_reopen (STDIN_FILENO, infile, O_RDONLY, 0) < 0)
src/stty.c: if (fd_reopen (STDIN_FILENO, device_name, O_RDONLY |
O_NONBLOCK, 0) < 0)
src/touch.c: fd = fd_reopen (STDIN_FILENO, file,
===
This means the rest of the program can just operate on STDIN (or STDOUT).
As such, I'm closing this item.
Discussion can continue by replying to this thread.
-assaf
- bug#31332: touch unnecessarily calls dup2,
Assaf Gordon <=