简体   繁体   English

psutil始终返回pid存在

[英]psutil always returning pid exists

I have Flask application that exposed API that can run application in background and can kill it later by specifying the PID. 我有Flask应用程序,该应用程序公开了可以在后台运行应用程序的API,以后可以通过指定PID杀死它。 However, for unit testing purpose, after killing the PID and checking if the PID is killed using psutil.pid_exists(pid) it seems to always returning true. 但是,出于单元测试的目的,在杀死PID并使用psutil.pid_exists(pid)检查PID是否被杀死psutil.pid_exists(pid)它似乎总是返回true。 I have checked manually that PID does not exist and run psutil.pid_exists(pid) on different python console and it returned true. 我已经手动检查了PID是否不存在,并在其他python控制台上运行psutil.pid_exists(pid)并返回true。 This is causing my test to fail. 这导致我的测试失败。

In views.py , I have: views.py ,我有:

@api.route('/cancel/<pid>', methods=['POST'])
def cancel(pid=None):
    try:
        os.kill(int(pid), signal.SIGTERM)

        data = dict(
            message = 'Successfully killed pid ' + pid)

        return jsonify(status='success', data=data), 200
    except:
        data = dict(
            message = 'Fail to kill job with pid ' + pid)
        return jsonify(status='error', data=data), 400

And in my test: 在我的测试中:

def test_cancel_job(self):
    # run_script will run something in the background and return the PID
    jobid, pid, cmd = run_script('fake_db', 'fake_cancel_jobid', 'tests/doubles/child.py')

    if not psutil.pid_exists(pid):
        raise Exception('Process is not running')

    # kill the job and assert it is successful
    resp = self.client.post('/api/cancel/' + str(pid))
    self.assert200(resp)

    # at this point, I have confirmed that the PID has been killed
    # but, the line below still get executed
    # psutil.pid_exists(pid) returns true

    # check pid is really killed
    if psutil.pid_exists(pid):
        raise Exception('Process {0} still exist'.format(pid))

I'm running on OSX if that make any difference. 如果有任何区别,我正在OSX上运行。

Update: I've tried running on the test on my build server (Ubuntu 14.04) and the test failed. 更新:我尝试在构建服务器(Ubuntu 14.04)上的测试上运行,但测试失败。

This is my run_script 这是我的run_script

def run_script(db, jobid, script):
    log = SCRIPTS_LOG + jobid + ".log"

    if not os.path.exists(SCRIPTS_LOG):
        os.makedirs(SCRIPTS_LOG)

    with open(log, "w") as output:
        cmd = ["nohup", "python", script, db]
        p = subprocess.Popen(cmd, stdout=output)

        return jobid, p.pid, " ".join(cmd)

and my child.py 和我的child.py

#!/usr/bin/env python

import time
import os, sys
if 'TEST_ENV' not in os.environ:
    os.environ['TEST_ENV'] = 'Set some env'

    try:
        os.execv(sys.argv[0], sys.argv)
    except Exception, exc:
        print "Failed re-exec:", exc
        sys.exit(1)


def main(argv):
    db = argv[0]

    while True:
        print 'Running child with params ', db
        time.sleep(1)


if __name__ == '__main__':
    main(sys.argv[1:])

I added a simple scripts that demonstrate this. 我添加了一个简单的脚本来演示这一点。 https://github.com/shulhi/kill-pid/tree/master https://github.com/shulhi/kill-pid/tree/master

It takes time to terminate a running process. 终止正在运行的进程需要花费时间。 In this case it's a child process, so os.wait() or one of its variants will know exactly how long to wait. 在这种情况下,它是一个子进程,因此os.wait()或其变体之一将确切知道要等待多长时间。 To future-proof, i'd use os.waitpid(pid, os.WEXITED) . 为了os.waitpid(pid, os.WEXITED)未来发展,我将使用os.waitpid(pid, os.WEXITED)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM