A decorator for doing things in a subprocess
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')






