完善进程管理

This commit is contained in:
xiongziliang 2020-06-08 16:26:55 +08:00
parent d0fc37db65
commit a3089f9a7e
2 changed files with 32 additions and 43 deletions

View File

@ -61,16 +61,16 @@ void Process::run(const string &cmd, const string &log_file_tmp) {
LPTSTR lpDir = const_cast<char*>(cmd.data());
if (CreateProcess(NULL, lpDir, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)){
//下面两行关闭句柄,解除本进程和新进程的关系,不然有可能 不小心调用TerminateProcess函数关掉子进程
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
_pid = pi.dwProcessId;
fprintf(fp, "\r\n\r\n#### pid=%d,cmd=%s #####\r\n\r\n", _pid, cmd.data());
InfoL << "start child proces " << _pid;
_handle = pi.hProcess;
fprintf(fp, "\r\n\r\n#### pid=%d,cmd=%s #####\r\n\r\n", _pid, cmd.data());
InfoL << "start child proces " << _pid << ", log file:" << log_file;
} else {
WarnL << "start child proces fail: " << get_uv_errmsg();
}
fclose(fp);
#else
fclose(fp);
#else
_pid = fork();
if (_pid < 0) {
throw std::runtime_error(StrPrinter << "fork child process falied,err:" << get_uv_errmsg());
@ -125,6 +125,8 @@ void Process::run(const string &cmd, const string &log_file_tmp) {
// EOF: NULL
charpv_params[params.size()] = NULL;
InfoL << "start child proces " << _pid << ", log file:" << log_file;
// TODO: execv or execvp
auto ret = execv(params[0].c_str(), charpv_params);
if (ret < 0) {
@ -132,7 +134,6 @@ void Process::run(const string &cmd, const string &log_file_tmp) {
}
exit(ret);
}
InfoL << "start child proces " << _pid;
#endif // _WIN32
}
@ -143,42 +144,33 @@ void Process::run(const string &cmd, const string &log_file_tmp) {
* @param block
* @return
*/
static bool s_wait(pid_t pid,int *exit_code_ptr,bool block) {
static bool s_wait(pid_t pid, void *handle, int *exit_code_ptr, bool block) {
if (pid <= 0) {
return false;
}
#ifdef _WIN32
HANDLE hProcess = NULL;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); //打开目标进程
if (!hProcess) {
//子进程不在线
return false;
}
DWORD code = 0;
if (block) {
//一直等待
code = WaitForSingleObject(hProcess, INFINITE);
code = WaitForSingleObject(handle, INFINITE);
} else {
code = WaitForSingleObject(hProcess, 0);
code = WaitForSingleObject(handle, 0);
}
if(code == WAIT_FAILED || code == WAIT_OBJECT_0){
//子进程已经退出了,获取子进程退出代码
DWORD exitCode = 0;
if(exit_code_ptr && GetExitCodeProcess(hProcess, &exitCode)){
if(exit_code_ptr && GetExitCodeProcess(handle, &exitCode)){
*exit_code_ptr = exitCode;
}
CloseHandle(hProcess);
return false;
}
CloseHandle(hProcess);
if(code == WAIT_TIMEOUT){
//子进程还在线
return true;
}
//不太可能运行到此处
//不太可能运行到此处
WarnL << "WaitForSingleObject ret:" << code;
return false;
#else
@ -232,30 +224,20 @@ bool signalCtrl(DWORD dwProcessId, DWORD dwCtrlEvent){
}
#endif // _WIN32
static void s_kill(pid_t pid,int max_delay,bool force){
static void s_kill(pid_t pid, void *handle, int max_delay, bool force) {
if (pid <= 0) {
//pid无效
return;
}
#ifdef _WIN32
HANDLE hProcess = NULL;
hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); //打开目标进程
if (!hProcess) {
//子进程可能已经推出了
return;
}
//windows下目前没有比较好的手段往子进程发送SIGTERM或信号
//所以杀死子进程的方式全部强制为立即关闭
force = true;
if(force){
//强制关闭
DWORD ret = TerminateProcess(hProcess, 0); //结束目标进程
CloseHandle(hProcess);
if (ret == 0) {
WarnL << "TerminateProcess " << pid << " failed:" << get_uv_errmsg();
}
//强制关闭子进程
TerminateProcess(handle, 0);
}else{
//非强制关闭,发Ctr+C信号
//非强制关闭发送Ctr+C信号
signalCtrl(pid, CTRL_C_EVENT);
}
#else
@ -266,32 +248,38 @@ static void s_kill(pid_t pid,int max_delay,bool force){
}
#endif // _WIN32
if(force){
if (force) {
//发送SIGKILL信号后阻塞等待退出
s_wait(pid, NULL, true);
s_wait(pid, handle, nullptr, true);
DebugL << "force kill " << pid << " success!";
return;
}
//发送SIGTERM信号后2秒后检查子进程是否已经退出
WorkThreadPool::Instance().getPoller()->doDelayTask(max_delay,[pid](){
if (!s_wait(pid, nullptr, false)) {
WorkThreadPool::Instance().getPoller()->doDelayTask(max_delay, [pid, handle]() {
if (!s_wait(pid, handle, nullptr, false)) {
//进程已经退出了
return 0;
}
//进程还在运行
WarnL << "process still working,force kill it:" << pid;
s_kill(pid,0, true);
s_kill(pid, handle, 0, true);
return 0;
});
}
void Process::kill(int max_delay,bool force) {
void Process::kill(int max_delay, bool force) {
if (_pid <= 0) {
return;
}
s_kill(_pid,max_delay,force);
s_kill(_pid, _handle, max_delay, force);
_pid = -1;
#ifdef _WIN32
if(_handle){
CloseHandle(_handle);
_handle = nullptr;
}
#endif
}
Process::~Process() {
@ -301,7 +289,7 @@ Process::~Process() {
Process::Process() {}
bool Process::wait(bool block) {
return s_wait(_pid,&_exit_code,block);
return s_wait(_pid, _handle, &_exit_code, block);
}
int Process::exit_code() {

View File

@ -31,6 +31,7 @@ public:
int exit_code();
private:
pid_t _pid = -1;
void *_handle = nullptr;
int _exit_code = 0;
};