fd leak, custom Shell

Let’s be accurate regarding the file descriptors and bear in mind that during fork and execvp file descriptors are inherited by child processes unless marked as w/ CLOEXEC flag. Check the man pages:

fork(2):
The child inherits copies of the parent’s set of open file descriptors. Each file descriptor in the child refers to the same open file description (see open(2)) as the corresponding file descriptor in the parent.

open(2):
By default, the new file descriptor is set to remain open across an execve(2) (i.e., the FD_CLOEXEC file descriptor flag described in fcntl(2) is initially disabled); the O_CLOEXEC flag, described below, can be used to change this default. The file offset is set to the beginning of the file (see lseek(2)).

But this behaviour, I supposed, exactly what you were relying on by calling fork after pipe…

No other words, lets’ draw this:

             stdin, stdout                                                                   
                   /\                                                                        
                  /  \                                                                       
                 /    \                                                                      
                /      \                                                                     
               / R; W;  \                                                                    
              /          \                                                                   
       Child -            - Parent                                                           
 stdin/out, R(del),W       stdin/out, R(fd_backup), W(del)                                   
                                  /\                                                         
                                 /  \                                                        
                                /    \                                                       
                               /      \                                                      
                              / R1; W1;\                                                     
                             /          \                                                    
                      Child -            - Parent                                            
               stdin/out, R(fd_backup),   stdin, stdout                                      
                            R1(del), W1   R(fd_backup - old);                                
                                          R1(fd_backup - new); W1(del)                       
                                                    / \                                      
                                                   /   \                                     
                                                  /     \                                    
                                                 /R2; W2;\                                   
                                                /         \                                  
                                               /           \                                 
                                        Child -             - Parent                         
                                 stdin, stdout,             stdin, stdout                    
                                R(fd_backup - old),         R (fd_backup - old),             
                                R1(fd_backup - new),        R1 (fd_backup - new),            
                                R2(del),W2                  R2 (fd_backup - newest!),                                                                                            

I hope the picture is self explanatory.

Child processes will die anyway and all their fds will be closed (so no issue with them). But the parent process is left with 3 opened fds and they keep growing with each pipe executed.

Leave a Comment