1

Say I open a parent process with a master process that assigns the stdout to a file for logging.

Then say I use the parent process to open a child with execvp (or any other of the exec family of functions).

According to documentation, the child will retain the parent's process id.

Main Question: Does that mean the child will inherit the parent's pipes (stdout and stderr specifically)?

2

For the documented answer, we need to look at the man page for the system call that the exec family of functions calls, execve:

By default, file descriptors remain open across an execve(). File descriptors that are marked close-on-exec are closed; see the description of FD_CLOEXEC in fcntl(2).

So, if the process did not set the close-on-exec flag in the pipes' file descriptors, they will remain open after an exec.

1

Yes, using exec and inheriting the same pid as the parent means the child keeps the pipe connections by default, so long as file-descriptors are not marked close-on-exec (which might be done via fcntl, see Mark Plotnick's answer).

I was on the verge of self answering with empirical data when I wrote up my question, and I followed through with a self-answer, so here's how I did it:

in file master.py:

import subprocess
import logging

def main():
    proc = ['python', 'parent.py']
    logpath = 'parent.log'
    with open(logpath, 'ab') as f:
        p = subprocess.Popen(proc, stdout=f, stderr=subprocess.STDOUT)
        logging.warn('task started, waiting to finish')
        res = p.wait()
        logging.warn(res)

if __name__ == '__main__':
    main()

in parent.py:

import os
import logging

def main():
    proc = ['python', 'child.py']
    logging.warn('parent is logging, pid: {0}'.format(os.getpid()))
    os.execvp(proc[0], proc)

if __name__ == '__main__':
    main()

and in child.py:

import os
import logging
import time

def main():
    for i in range(2):
         logging.warn('child is logging, pid: {0}'.format(os.getpid()))
         time.sleep(15)

if __name__ == '__main__':
    main()

When I run python master.py on the commandline, the commandline outputs this:

WARNING:root:task started, waiting to finish

and about 15 seconds later:

WARNING:root:0

and the parent.log file contains this:

WARNING:root:parent is logging, pid 8515
WARNING:root:child is logging, pid 8515
WARNING:root:child is logging, pid 8515

which demonstrates empirically that the child inherits the pipes along with the pid from the parent when using the exec family of functions. It was hard to find supporting documentation on this, but there is an example given here (about halfway through the material.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.