Tommy
Tommy

Reputation: 13672

Python; popen do not pass std*

I have a chain of three processes: Process A calls B to spawn C, then B dies. We can call B a "bridge" between two systems A and C.

I want to make sure that C DOES NOT inherit any file descriptors that A opens in order to prevent zombying, which I am currently observing (sometimes A calls B to kill C, and after this, I am seeing defunct C processes hanging around, but I don't know what the code in A looks like).

To make sure this issue isn't due to stdin/out/err being passed down, I am currently doing the following in B

def _close_fds(): #workaround carstens bug
    for fd in [0, 1, 2]:
        try:
            os.close(fd)
        except Exception:
            logger.info("File descriptor was not open")

...
_close_fds() #make sure there are no open file descriptors for the chile to enherit
pid = subprocess.Popen([_ROOT_PATH  + "something.py"]).pid
...

Is there a better way to do this?

Upvotes: 0

Views: 87

Answers (2)

Roland Smith
Roland Smith

Reputation: 43533

When you are starting process C from B, and you don't want it to inherit any file handles, use the following arguments in subprocess.Popen;

  1. close_fds=True
  2. Set stdin, stdout and stderr to subprocess.PIPE or subprocess.DEVNULL.

The first closes all file handles except stdin, stdout and stderr. The arguments listed under (2) take care of those.

Upvotes: 3

alexis
alexis

Reputation: 50220

The os module provides a nice function, os.closerange(), that will do this for you in one call:

os.closerange(0, 3)

If you're hunting after phantom open files, I would go a little higher just in case:

os.closerange(0, 10)

To find out what you actually need to close, you can check /proc/self/fd for a list of the file descriptors that your process has open (if your OS supports it), and/or use the open_files() method from psutil. See the answers to this question for even more ideas.

Upvotes: 1

Related Questions