Creating subprocesses in new contracts on Solaris 10

Solaris 10 introduced "contracts" for processes. You can read all about it in the contract(4) manpage but simply put it's a grouping of processes under another ID, and you can "monitor" these groups, e.g. be notified when a process in a group coredumps etc. This is actually one of the tools of Solaris' init replacement smf(5), which is probably the main reason people care about contracts.

Suppose you have a daemon managed by SMF which executes subprocesses as part of it's life (e.g. because of multiprocessing). If your application is not aware of contracts all subprocesses will be in the same contract. Which is fine until the main process dies a miserable death and one expects SMF to restart it. Only it doesn't since it sees the contract as still being alive and sees no harm. Time to start your subprocesses in a different contract then.

Anyway, whatever your motivation, starting the subprocesses in new contracts is normally done by activating the process contract template, i.e. opening /system/contract/process/template and then calling ct_tmpl_activate(3) on the filedescriptor. Only problem is that this isn't exposed to python.

Fortunately the libcontract(3) functions we need for this are very simple, so ctypes can handle this very nicely. The code is pretty simple:

import ctypes
import os

fd = os.open('/system/contract/process/template', os.O_RDWR)
libct = ctypes.cdll.LoadLibrary('libcontract.so.1')
rv = libct.ct_tmpl_activate(fd)
if rv != 0:
    raise Exception('oops')

That's all there is to it. Each fork(2) call will now result in a process running in it's own contract.

It's nice when C-APIs are simple enough to be used from inside python instead of having to write wrappers.

PS: Needless to say you can do a whole lot more with contracts, just read up on the libcontract API docs.