OK, got a solution that has been working well for last few days now. I made 2 mistakes previously that caused me trouble:
1) The child processes are independent. I had used ctrl+c to kill web2py, which was passed on to the child processes. When kill -9 [web2py PID] was used the child processes continued fine. 2) The parent process can kill child processes but they became zombie processes until the parent process dies. Originally I was checking /proc/PID for process existence so seemed to always exist. Now using the psutil package, which has some useful cross platform features. Much better than parsing output of ps! The scheduler was not helpful for this use case. Here are some functions I used in case they help others: def exists(pid): """Return whether the process exists""" try: p = psutil.Process(pid) if p.status == psutil.STATUS_ZOMBIE: return False # ignore zombie processes else: return True except psutil.NoSuchProcess: return False def stop(pid): """Try to kill this process, first with interrupt and then kill signal """ success = True try: p = psutil.Process(pid) p.terminate() time.sleep(1) # if don't delay here a bit then exists() call will usually fail - better way? if exists(pid): # was not able to terminate process so try kill p.kill() time.sleep(1) if exists(pid): success = False except psutil.NoSuchProcess: pass return success --