我想用 process 类记录进程的 id,写入文件 然后用使用 process 类的 close 方法关闭进程
问题是使用 kill pid 的时候,process 类的析构方法不能正常执行析构方法删除掉对应的 pid 文件
加上 signal.signal(signal.SIGTERM, self.signal_handler),即使 handler 中不写任何东西,被 kill 的进程也能调用析构方法
如果不写 signal.signal,析构方法就不会触发,求指教
python 版本为 2.7.6
# coding=utf-8
# from tool import Tool
import os
import signal
import re
class Process:
_pid = None
_pid_dir = None
prefix = 'pid.'
def __init__(self):
t = Tool()
self._pid_dir = t.runtime_dir() # 创建临时目录而已,可手动写死
signal.signal(signal.SIGTERM, self.signal_handler)
def signal_handler(self, signum, frame):
# print('Received signal: ', signum)
pass
def pid_file_name(self, pid):
return self.prefix + str(pid)
def pid_file(self, pid):
"""
获取当前进程的 pid 缓存文件
:return:
"""
return self._pid_dir + '/' + self.pid_file_name(pid)
def save(self, pid=None):
"""
保存当前进程 pid 文件
:return:
"""
self._pid = pid if pid else os.getpid()
os.system('touch %s' % self.pid_file(self._pid))
def close(self):
"""
关闭全部的进程
:return:
"""
for pf in os.listdir(self._pid_dir):
rer = re.match(self.prefix + '(\d+)', pf)
if rer:
pid = int(rer.group(1))
try:
os.kill(pid, 15)
except OSError:
# 抑制异常,不抛出进程不存在的问题,并删除不存在的进程号
self.del_pid_file(pid)
def del_pid_file(self, pid):
"""
删除进程缓存的文件
:param pid:
:return:
"""
pid_file = self.pid_file(pid)
os.path.exists(pid_file) and os.remove(pid_file)
def __del__(self):
"""
如果存在当前进程的 pid 文件,删除 pid 文件
:return:
"""
self._pid and self.del_pid_file(self._pid)
使用 python tester.py xx 和 python tester.py 命令进行对应的调试
import sys
import time
from core.Process import Process
import datetime
p = Process()
m = True if len(sys.argv) == 2 else False
# m = False
if m:
p.save()
time.sleep(70)
else:
p.close()
1
msg7086 2018-06-19 12:24:41 +08:00
kill 的问题先不说。
m = True if len(sys.argv) == 2 else False 这是什么鬼…… 直接写 m = len(sys.argv) == 2 不行么…… 至于 kill term,我猜的是如果你不指定 handler,那么就用系统默认的 term handler,也就是直接杀掉进程。 |
2
wwqgtxx 2018-06-19 16:07:19 +08:00
从 python 规范中只是说__del__会在被垃圾回收的时候调用,而且还说这种用法容易造成死锁、内存泄漏等问题,貌似从来没说过可以当做析构函数使用
|
3
lolizeppelin 2018-06-19 16:11:30 +08:00 via Android
kill 是信号发送
signal_handler 接受信号 你接受信号以后什么都不干 当然就没反应 本来你的对应退出代码就该写在 signal_handler 里 为什么要写 del 里? |
4
ruoge3s OP @msg7086 m = xx 的问题只是一个写法的问题,每个人理解不一样而已.你理解的就是把 len 的长度与 2 的比较结果赋值给 m,我理解的是如果为 2 就赋值 true 否则赋值 false.
不指定 handler 的话,我在使用 os.kill(pid, 15)的时候,也应该通知该进程的信号是 15 啊,并没有直接杀死进程啊. 而运行的脚本这边在收到了-15 信号的时候,没有对应的进行回收,销毁变量,也就没有触发 process 这个对象的销毁,所以也么有进一步的调用到析构方法. 所有,我很迷惑. 那么你的意思是系统的默认的 term handler 无论接收到任何信号,都当成-9 来处理 |
6
ballshapesdsd 2018-06-19 18:27:58 +08:00
啥 python 还有析构函数。。
|
7
ruoge3s OP @lolizeppelin 朋友,你没有看明白问题.
|
8
ruoge3s OP __del__就是啊
|
9
ruoge3s OP @ballshapesdsd __del__就是啊
|
12
msg7086 2018-06-19 23:47:47 +08:00
操作系统默认的 term handler 接收到 term 的时候,除了当成 kill 以外好像也没有别的选择啊。
系统也不可能进入到你程序的内部来退出吧。 |
13
ryd994 2018-06-20 00:50:33 +08:00 via Android
|
15
ryd994 2018-06-20 01:09:06 +08:00 via Android
@msg7086 kill 是内核直接抽内存栈了啊
term 实际上是进程自己处理的,所以自己指定一个 handler 的话是可以不死的 但是 kill 表面上是个信号,但是根本不会被送到进程内,实际上是内核直接处理的 |
16
msg7086 2018-06-20 01:13:02 +08:00
@ryd994 是啊我同意你的观点。kill 是没有 handler 的,term 的默认 handler 类似 kill self。
我说的是 IO block 的情况,是内核自己炸了,所以 kill 也没用。 |
18
msg7086 2018-06-20 01:24:10 +08:00
@ryd994 是啊,NFS 断线是我遇到的最多的 kill 不掉的场景了。
没记错的话需要用 hup 去捅挂载进程,然后才能 kill 掉程序。 你直接 kill 的话,D 状态的程序是 kill 不掉的,否则内核状态会出问题。 |
20
geelaw 2018-06-20 01:33:25 +08:00
析构函数本来就不一定运行啊。
你 C++ 写一个析构函数,然后发送一个导致杀死进程的信号,outstanding 对象的析构函数也不会运行。 另外,__del__ 应该类比于 C# 的 finalizer,而不是 C++ destructor,Python 文档也是这么说的。 终结化器不一定非要运行,包括程序正常退出的情况。终结化器不一定按照你想像的顺序运行,比如,当终结化器运行的时候,或许你的一个字段引用的对象已经被终结化了( C# 也有该现象)。 |