【问题标题】:Why does os.kill(pid, 0) return None although process has terminated?为什么 os.kill(pid, 0) 尽管进程已终止但返回 None ?
【发布时间】:2012-11-27 23:25:32
【问题描述】:

这个问题与this answer 有关我的其他问题之一。我在这个答案中被告知可以使用os.kill(pid, 0) 来检查子进程是否已终止。如果它仍在运行,则返回 None。如果它已终止,则会引发 OSError。到目前为止,这一直运行良好,但现在我处于os.kill(pid, 0) 仍然返回None 的情况,尽管子进程已经终止。进程 ID 为 82430,在 OSX 的活动监视器中,我再也找不到具有此 ID 的进程。但是,当我打开 Python shell 并输入 os.kill(82430, 0) 时,它仍然返回 None。我不明白。

准确地说,我通过 Ajax GET 请求在 Django 视图中定期检查子进程的状态,如上所示。

服务器端的 Django 视图

def monitor_process(request):
    response_data = {}

    try:
        os.kill(int(request.GET['process_id']), 0)
        response_data['process_status'] = 'running'
    except OSError:
        response_data['process_status'] = 'finished'

    return HttpResponse(json.dumps(response_data), mimetype='application/json')

客户端的 Ajax 调用

var monitorProcess = function(processId) {

    $.ajax({
        dataType: 'json',
        type: 'GET',
        url: '/monitor_process/',
        data: {'process_id': processId},
        success: function(response) {

            if (response.process_status == 'running') {
                // Only this branch is always executed

                // ...
            }

            else if (response.process_status == 'finished') {
                // This branch never gets executed

                // Stop checking for process status
                // The periodic check was started by 
                // window.setInterval in a different Ajax call
                clearInterval(monitorProcessId);

                // ...

            }
        }
    });
}; 

尽管进程在某些时候停止并在活动监视器中消失,os.kill() 显然无法识别它。为什么会这样?非常感谢!

【问题讨论】:

  • 线程呢?如果有任何线程与该进程关联,os.kill 不会返回任何 OSError,您是否也检查了这些?
  • @SamueleMattiuzzo 你到底是什么意思?到目前为止,我对线程没有任何经验,只有 Python 的 subprocess 模块。请更详细地向我解释一下。谢谢!
  • 我将其发布为答案,因为它太长了,无法作为评论:)

标签: python django


【解决方案1】:

这与 python 无关,更多的是关于进程本身:每个正在运行的进程可能会产生一些具有不同 PID 的线程。如果父母没有被正确杀死,他们会留在那里(“僵尸线程”)。它们与它们的父级在同一 ID 下分组在一起。这就是为什么,在 python 中,你可以使用

os.killpg(pgid, sig) 

杀死所有组。您可以在

下查看
/proc/<PID>/task/ 

(您的实际进程 ID 在哪里)用于生成的任何线程

【讨论】:

  • 有趣。你可能是对的,因为我刚刚发现当我退出 Django 的开发服务器(它是我正在运行的子进程的父进程)时,对os.kill(82430, 0) 的调用最终会引发OSError。但是,显然,并非我以与上面所示相同的方式监视和杀死的所有子进程都显示了这种行为。有点奇怪。
  • 理论上,如果你的假设是正确的,那么调用os.killpg() 会一直杀死 Django 的开发服务器,这对我来说当然是不可行的。我可以通过将我的原始子流程 A 包装在另一个子流程 B 中来规避这个问题吗?那么,A 的父进程应该是 B 而不是开发服务器进程了。我说的对吗?
  • 嗯...我不完全确定(从未深入研究过),但我认为您可以在不杀死 django 的情况下安全地关闭进程。想想 chrome 浏览器:应用程序为添加的每个选项卡生成一个线程。如果你杀了他的团队,如果你也杀了你的整个系统,那就太奇怪了,对吧?
  • 当然,但这是我正确退出子进程的唯一方法。顺便问一下,/proc/&lt;PID&gt;/task/ 呢?这是目录路径吗?我运行 OSX 10.8.2 的机器上不存在目录 /proc
  • 哎哟。假设您使用的是Linux机器,那是我的错。据我所知,osx 不支持 procfs,它负责(在 linux 上)该文件夹。我想你只需要深入研究“ps”命令
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-27
  • 2017-02-14
  • 1970-01-01
  • 2020-12-12
  • 2022-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多