Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the rules of closing file descriptors after calling dup/dup2?

I feel like this is a topic I've taken for granted. In the past I literally just closed as many file descriptors "because I was told to". Most of the time this worked, but occasionally I ran into some unpredictable behaviour.

Thus, I'd like to ask - what the rule for closing file descriptors after calling dup / dup2?

Let's say I want to perform cat < in > out.

fd[IN] = open("in", O_RDONLY);
saved_stdin = dup(STDIN_FILENO);
dup2(fd[IN], STDIN_FILENO);
close(fd[IN])

fd[OUT] = open("out", O_WRONLY | O_CREAT | O_TRUNC, 0644);
saved_stdout = dup(STDOUT_FILENO);
dup2(fd[OUT], STDOUT_FILENO);
close(fd[OUT])


// Later on when I want to restore stdin and stdout
dup2(saved_stdin, STDIN_FILENO);
close(saved_stdin);
dup2(saved_stdout, STDINOUT_FILENO);
close(saved_stdout);

Is this correct or should I be closing more file descriptors?

like image 812
doctopus Avatar asked Nov 06 '22 18:11

doctopus


1 Answers

The rule is indeed quite simple. For both dup() variants, it is true, that:

  • The source fd remains open and will have to be closed once it is no longer needed.

  • The target file descriptor,

    • when using dup(), is always an unused one
    • when using dup2(), is implicitly closed and replaced by a copy of the source fd.
  • The new target fd has to be closed, when it is no longer needed.

Source fd refers to the file descriptor to be duplicated, while target fd is the new file descriptor.

int new_fd = dup(source_fd);
dup2(source_fd, new_fd);

So yes, your code does the necessary closes, and no unneeded ones.

like image 65
Ctx Avatar answered Nov 15 '22 12:11

Ctx