Python Multiprocess with SIGTERM supported
来源:互联网 发布:网络领域破解版 编辑:程序博客网 时间:2024/06/05 00:20
Python does not have a standard daemon module
Creating a daemon on Unix requires a “double-fork” recipe that I can only say is partly magic. The recipe cited here seems to be the most-often cited resource for how to fork a daemon. It dates from 2001.
http://code.activestate.com/recipes/66012/
One may wonder why this recipe hasn’t been turned into a standard Python daemon package. I can think of two reasons. One: the code is small enough that it doesn’t deserve to be a package. Two: a good package would handle many possible daemonization needs. This recipe imposes restrictions on the daemon and only works for simple cases.
If you’re will to accept its restrictions (like only the normal IN/OUT/ERR file descriptors open) then it seems to be fine. I was quite happy to keep my service simple. Stdout and stderr are the only two streams used, and the only signal handled is SIGTERM.
In the end, I chose to use the variant posted by Clark Evans here that added the daemon start/stop/restart behavior.
http://code.activestate.com/recipes/66012/#c9
Python masks signals to subprocesses
This is where I got a little hung-up. My service was running subprocesses: both as simple commands and as long-running threads. I was having a hard time terminating sub-programs when I wanted my service to stop.
I found a great resource in this article:
http://www.doughellmann.com/PyMOTW/subprocess/
Python masks the signals to subprocesses it starts. (Here “masks” means “does not propagate”) If you use the subprocess module to start a long-running job like this “sleep” command:
import subprocess job = subprocess.Popen(["sleep", "6000"]) (se, so) = job.communicate()
and then kill the parent Python process with a SIGTERM, the child “sleep” process will keep on running. The article referenced above explains how to set a Unix “session ID” (os.setsid) and how to send a signal to a “process group” (os.killpg). I modified the technique a little bit in the interest of simplification.
Use the threading.setDaemon() flag
Python will not exit if normal threads are still running: you must shut them down explicitly. However, Pythonwill exit if only “daemon” threads are running. A daemon thread is simply something you deem unimportant enough that it does not require an explicit shut-down step. Write a daemon thread like this:
class myThread(threading.Thread):
def __init__(self, args ...):
...
threading.Thread.__init__(self)
self.setDaemon(True)
Putting it all together
SIGTERM_SENT = Falsedef sigterm_handler(signum, frame):
print >>sys.stderr, "SIGTERM handler. Shutting Down."
global SIGTERM_SENT
if not SIGTERM_SENT:
SIGTERM_SENT = True
print >>sys.stderr, "Sending TERM to PG"
os.killpg(0, signal.SIGTERM)
sys.exit()
def main():
# set session ID to this process so we can kill group in sigterm handler
os.setsid()
signal.signal(signal.SIGTERM, sigterm_handler)
while True:
# ... run daemon threads and subprocesses with impunity.
# ... this function never returns ...
from daemonize import startstop
if __name__== "__main__":
startstop(stdout="/var/log/example.log",
pidfile="/var/run/example.pid")
main()
Here’s what we came up with. (Start at the bottom.) The startstop function does the daemonization double-fork. Thus, the PID of the daemon is a grandchild of starting Python process. When main() is called, the effective PID is that of the daemon. Calling os.setsid() sets the session id to the PID of the daemon. (The PID is the one written to the pid-file).
The sigterm handler is called when a SIGTERM arrives. Its main purpose is to send SIGTERM to the process group of the session. (Recall that Python has masked the signals to its subprocess children, so we have manage sending the signals.) This step terminates the child processes. However, it also re-sends SIGTERM to the main daemon process – which we didn’t want. We use the SIGTERM_SENT flag so that on the second receipt of the TERM signal, we ignore it.
In the end, this recipe is fairly simple. Your mileage may vary, but if keep your use of subprocesses and threads simple, this might work for you too.
- Python Multiprocess with SIGTERM supported
- python multiprocess
- python os、multiprocess、 threading
- 【原创】python multiprocess…
- python的multiprocess的使用
- 【python】多进程锁multiprocess.Lock
- Python 多进程锁multiprocess Lock
- python+multiprocess+theano+pylucene--内存泄露解决方案
- python multiprocess 包中工具类Queue的使用
- 打包python程序(win7(64) +python3.5 + pyqt5 + multiprocess)
- python multiprocess 包中工具类Queue的使用
- android:multiprocess
- SIGTERM SIGINT
- SIGTERM SIGINT
- SIGTERM SIGINT
- multiprocess Poll.map python多进程提取处理大量文本的关键词
- Going multiprocess on Android
- python 转码报错decoding Unicode is not supported
- 怎么获取本地时间存入mysql数据库,数据库类型是datetime
- js使用技巧5
- wubi
- RACLE中用一条SQL实现其它进制到十进制的转换
- POJ1129 Channel Allocation [图染色 暴搜]
- Python Multiprocess with SIGTERM supported
- 深入嵌入式linux知识要点
- 1350. Piggy banks
- RTX的实时TCP-IP协议栈
- js使用技巧6
- linux环境变量设置 (PS1,PS2)
- 使用 EditPlus 替换行编号和空行的方法
- Android中TabHost嵌套TabHost
- asp.net frameset的使用小结