Python 进程 pid,使用 kill -15 pid,无法执行析构函数,求解释为什么 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
ruoge3s
V2EX    Python

Python 进程 pid,使用 kill -15 pid,无法执行析构函数,求解释为什么

  •  
  •   ruoge3s 2018-06-19 11:27:04 +08:00 4551 次点击
    这是一个创建于 2676 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我想用 process 类记录进程的 id,写入文件 然后用使用 process 类的 close 方法关闭进程

    问题是使用 kill pid 的时候,process 类的析构方法不能正常执行析构方法删除掉对应的 pid 文件

    加上 signal.signal(signal.SIGTERM, self.signal_handler),即使 handler 中不写任何东西,被 kill 的进程也能调用析构方法

    如果不写 signal.signal,析构方法就不会触发,求指教

    python 版本为 2.7.6

    Process.py

    # 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 命令进行对应的调试

    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() 
    22 条回复    2018-06-20 09:56:49 +08:00
    msg7086
        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,也就是直接杀掉进程。
    wwqgtxx
        2
    wwqgtxx  
       2018-06-19 16:07:19 +08:00
    从 python 规范中只是说__del__会在被垃圾回收的时候调用,而且还说这种用法容易造成死锁、内存泄漏等问题,貌似从来没说过可以当做析构函数使用
    lolizeppelin
        3
    lolizeppelin  
       2018-06-19 16:11:30 +08:00 via Android
    kill 是信号发送
    signal_handler 接受信号


    你接受信号以后什么都不干 当然就没反应

    本来你的对应退出代码就该写在 signal_handler 里

    为什么要写 del 里?
    ruoge3s
        4
    ruoge3s  
    OP
       2018-06-19 18:26:27 +08:00
    @msg7086 m = xx 的问题只是一个写法的问题,每个人理解不一样而已.你理解的就是把 len 的长度与 2 的比较结果赋值给 m,我理解的是如果为 2 就赋值 true 否则赋值 false.

    不指定 handler 的话,我在使用 os.kill(pid, 15)的时候,也应该通知该进程的信号是 15 啊,并没有直接杀死进程啊.
    而运行的脚本这边在收到了-15 信号的时候,没有对应的进行回收,销毁变量,也就没有触发 process 这个对象的销毁,所以也么有进一步的调用到析构方法.

    所有,我很迷惑.

    那么你的意思是系统的默认的 term handler 无论接收到任何信号,都当成-9 来处理
    ruoge3s
        5
    ruoge3s  
    OP
       2018-06-19 18:27:37 +08:00
    @wwqgtxx 这个解释看起来合理一点
    ballshapesdsd
        6
    ballshapesdsd  
       2018-06-19 18:27:58 +08:00
    啥 python 还有析构函数。。
    ruoge3s
        7
    ruoge3s  
    OP
       2018-06-19 18:28:05 +08:00
    @lolizeppelin 朋友,你没有看明白问题.
    ruoge3s
        8
    ruoge3s  
    OP
       2018-06-19 18:30:07 +08:00
    __del__就是啊
    ruoge3s
        9
    ruoge3s  
    OP
       2018-06-19 18:30:25 +08:00
    @ballshapesdsd __del__就是啊
    tkmiles
        10
    tkmiles  
       2018-06-19 19:02:19 +08:00
    @ruoge3s python 中的析构还是少用比较好, 可以看一下 gc
    ruoge3s
        11
    ruoge3s  
    OP
       2018-06-19 19:35:55 +08:00 via Android
    @tkmiles 好的。
    msg7086
        12
    msg7086  
       2018-06-19 23:47:47 +08:00
    操作系统默认的 term handler 接收到 term 的时候,除了当成 kill 以外好像也没有别的选择啊。
    系统也不可能进入到你程序的内部来退出吧。
    ryd994
        13
    ryd994  
       2018-06-20 00:50:33 +08:00 via Android
    @msg7086 我记得 term 是由 glibc 的默认 handler 处理
    kill 是内核直接删进程
    区别在于:如果进程 IO block,term 是没有用的,要 kill
    msg7086
        14
    msg7086  
       2018-06-20 00:53:04 +08:00
    @ryd994 嗯应该没错。
    IO block 的话,你说的是 D 状态?那个连 kill 都没用的。
    ryd994
        15
    ryd994  
       2018-06-20 01:09:06 +08:00 via Android
    @msg7086 kill 是内核直接抽内存栈了啊
    term 实际上是进程自己处理的,所以自己指定一个 handler 的话是可以不死的
    但是 kill 表面上是个信号,但是根本不会被送到进程内,实际上是内核直接处理的
    msg7086
        16
    msg7086  
       2018-06-20 01:13:02 +08:00
    @ryd994 是啊我同意你的观点。kill 是没有 handler 的,term 的默认 handler 类似 kill self。
    我说的是 IO block 的情况,是内核自己炸了,所以 kill 也没用。
    ryd994
        17
    ryd994  
       2018-06-20 01:19:29 +08:00 via Android
    @msg7086 呃,举个例子,读写 NFS,结果网断了
    我是说这种情况
    msg7086
        18
    msg7086  
       2018-06-20 01:24:10 +08:00
    @ryd994 是啊,NFS 断线是我遇到的最多的 kill 不掉的场景了。
    没记错的话需要用 hup 去捅挂载进程,然后才能 kill 掉程序。
    你直接 kill 的话,D 状态的程序是 kill 不掉的,否则内核状态会出问题。
    sNullp
        19
    sNullp  
       2018-06-20 01:26:04 +08:00
    @ryd994 在这种情况下 kill 明确是没有用的,因为 stuck 在内核里
    geelaw
        20
    geelaw  
       2018-06-20 01:33:25 +08:00
    析构函数本来就不一定运行啊。

    你 C++ 写一个析构函数,然后发送一个导致杀死进程的信号,outstanding 对象的析构函数也不会运行。

    另外,__del__ 应该类比于 C# 的 finalizer,而不是 C++ destructor,Python 文档也是这么说的。

    终结化器不一定非要运行,包括程序正常退出的情况。终结化器不一定按照你想像的顺序运行,比如,当终结化器运行的时候,或许你的一个字段引用的对象已经被终结化了( C# 也有该现象)。
    ryd994
        21
    ryd994  
       2018-06-20 03:01:39 +08:00 via Android
    @msg7086
    @sNullp
    看来是我记错了,抱歉
    ruoge3s
        22
    ruoge3s  
    OP
       2018-06-20 09:56:49 +08:00
    @geelaw 受教了,我去多读读 python 的关于这点的文档
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5422 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 01:20 PVG 09:20 LAX 18:20 JFK 21:20
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86