【发布时间】: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