【问题标题】:How to find out whether child process still is running?如何找出子进程是否仍在运行?
【发布时间】:2015-09-10 20:45:04
【问题描述】:

我正在我的应用程序中生成一个进程:

int status = posix_spawnp(&m_iProcessHandle, (char*)strProgramFilepath.c_str(), NULL, NULL, argsWrapper.m_pBuffer, NULL);

当我想查看进程是否还在运行时,我使用kill:

int iReturn = kill(m_iProcessHandle,0);

但在生成的进程完成其工作后,它会挂起。 kill 命令的返回值始终为 0。不是 -1。我在代码中调用 kill ,但如果我从命令行调用它,则没有错误 - 生成的进程仍然存在。

只有当我的应用程序退出时,命令行 kill 才会返回“No such process”。

我可以在我的代码中改变这种行为:

int iResult = waitpid(m_iProcessHandle, &iStatus, 0);

对 waitpd 的调用会关闭生成的进程,我可以调用 kill 并返回 -1,但到那时我知道生成的进程已经死了。

然后 waitpd 阻止了我的应用程序!

如何在不阻塞我的应用程序的情况下测试生成的进程以查看它是否正在运行?

更新

感谢您的帮助!我已经实施了您的建议,结果如下:

// background-task.cpp
//

#include <spawn.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>

#include "background-task.h"


CBackgroundTask::CBackgroundTask()
{

    // Initialize member variables
    m_iProcessHandle = 0;

}

CBackgroundTask::~CBackgroundTask()
{

    // Clean up (kill first)
    _lowLevel_cleanup(true);

}

bool CBackgroundTask::IsRunning()
{

    // Shortcuts
    if (m_iProcessHandle == 0)
        return false;

    // Wait for the process to finish
    int iStatus = 0;
    int iResult = waitpid(m_iProcessHandle, &iStatus, WNOHANG);
    return (iResult != -1);

}

void CBackgroundTask::Wait()
{

    // Wait (clean up without killing)
    _lowLevel_cleanup(false);

}

void CBackgroundTask::Stop()
{

    // Stop (kill and clean up)
    _lowLevel_cleanup(true);

}

void CBackgroundTask::_start(const string& strProgramFilepath, const string& strArgs, int iNice /*=0*/)
{

    // Call pre-start
    _preStart();

    // Split the args and build array of char-strings
    CCharStringAarray argsWrapper(strArgs,' ');

    // Run the command
    int status = posix_spawnp(&m_iProcessHandle, (char*)strProgramFilepath.c_str(), NULL, NULL, argsWrapper.m_pBuffer, NULL);
    if (status == 0)
    {

        // Process created
        cout << "posix_spawn process=" << m_iProcessHandle << "  status=" <<     status << endl;

    }
    else
    {

        // Failed
        cout << "posix_spawn: error=" << status << endl;

    }

    // If process created...
    if(m_iProcessHandle != 0)
    {

        // If need to adjust nice...
        if (iNice != 0)
        {

            // Change the nice
            stringstream ss;
            ss << "sudo renice -n " << iNice << " -p " << m_iProcessHandle;
            _runCommand(ss.str());

        }

    }
    else
    {

        // Call post-stop success=false
        _postStop(false);

    }

}

void CBackgroundTask::_runCommand(const string& strCommand)
{

    // Diagnostics
    cout << "Running command: " << COUT_GREEN << strCommand << endl << COUT_RESET;

    // Run command
    system(strCommand.c_str());

}

void CBackgroundTask::_lowLevel_cleanup(bool bKill)
{

    // Shortcuts
    if (m_iProcessHandle == 0)
        return;

    // Diagnostics
    cout << "Cleaning up process " << m_iProcessHandle << endl;

    // If killing...
    if (bKill)
    {

        // Kill the process
        kill(m_iProcessHandle, SIGKILL);

    }

    // Diagnostics
    cout << "Waiting for process " << m_iProcessHandle << " to finish" << endl;

    // Wait for the process to finish
    int iStatus = 0;
    int iResult = waitpid(m_iProcessHandle, &iStatus, 0);

    // Diagnostics
    cout << "waitpid: status=" << iStatus << "   result=" << iResult << endl;

    // Reset the process-handle
    m_iProcessHandle = 0;

    // Call post-stop with success
    _postStop(true);

    // Diagnostics
    cout << "Process cleaned" << endl;

}

【问题讨论】:

  • 您是否尝试对waitpid 使用WNOHANG 选项?
  • 生成的进程(即使被终止然后被称为僵尸)持有一个进程ID,直到父进程通过wait()正确reap子进程和朋友。如果您想要异步通知,请为SIGCHLD 安装一个处理程序(并从那里调用wait())。
  • 仅供参考,waitpid(...) 中的“等待”有点用词不当。 wait(...) 和朋友的主要目的是获取“僵尸”进程的状态,以便内核可以真正杀死它并重新使用它的进程 ID。 wait() 和朋友 wait 让进程进入僵尸状态(如果你没有指定WNOHANG)是次要特性。
  • 可能是relevant

标签: c++ linux posix spawn


【解决方案1】:

在父进程调用wait() 函数之一以获取子进程的退出状态之前,子进程一直以zombie process 的形式存在。如果您在此期间运行ps,您会看到该进程仍处于Z 状态。所以kill()返回0,因为进程存在。

如果您不需要获取孩子的状态,请参阅How can I prevent zombie child processes?了解如何让孩子在退出时立即消失。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-10
    • 1970-01-01
    • 2011-03-07
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    • 2021-12-11
    相关资源
    最近更新 更多