Home Company Services Portfolio Contact us nav spacer

A decorator for doing things in a subprocess

by Izak Burger posted on Jul 23, 2009 09:50 AM last modified Jul 23, 2009 02:04 PM —

If you need to fork or drop privileges often, this will help.

This is a simple idea I came up with to make it easier to perform the often repeated task of forking a process and dropping privileges, as is often required of processes on a unix host. I came up with two simple decorators. This is not complete, it allows the sub process to return anything that can be pickled, but communication is not bi-directional. Perhaps it should be :-)

Note: Source code below display's badly because of a bug in deliverance, but it should cut-and-paste fine.


  import os
  import pickle
  import pwd

  def fork_and_exec(fn):
      def _fork_and_run(*args, **kwargs):
          readend, writeend = os.pipe()
          readend = os.fdopen(readend, "r")
          writeend = os.fdopen(writeend, "w")
          pid = os.fork()
          if pid==0:
              readend.close()
              result = fn(*args, **kwargs)
              pickle.dump(result, writeend)
              writeend.flush()
              os._exit(0)

          writeend.close()
          result = pickle.load(readend)
          pid, status = os.waitpid(pid, 0)
          return result
      return _fork_and_run

  def drop_privileges(user, ignore=False):
      def _wrap(fn):
          def _new(*args, **kwargs):
              try:
                  pw = pwd.getpwnam(user)
                  os.setregid(pw[3], pw[3])
                  os.setreuid(pw[2], pw[2])
              except KeyError:
                  if not ignore:
                      raise
              except OSError:
                  if not ignore:
                      raise
              return fn(*args, **kwargs)
          return _new
      return _wrap

I'm sure it can be made simpler by using the subprocess module, but this old C coder is sticking with what he knows.

Here is an example of how you'd use it:


    @fork_and_exec
    @drop_privileges("nobody")
    def getpid(name):
        return [os.getpid(), os.geteuid(), 'Bob', 'Alice', name]

    print "my pid is %d" % os.getpid()
    print "my uid is %d" % os.geteuid()
    print '===='
    print getpid('Roger')
Document Actions
Add comment

You can add a comment by filling out the form below. Plain text formatting.

(Required)
Tell us your name.
(Required)
Enter your e-mail address.
(Required)
(Required)