完善进程管理

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

View File

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