📄 subprocess.cpp
字号:
break; case 0: goto Done; continue; default: buf[rc]=_TCHAR('\0'); Output(String::CStrToUnicodeStr(buf)); continue; } } while(!m_bKillThread && m_pfnContinue(m_pContinuationFuncParam));Done: TRACE(_T("Closing fd %d\n"),m_tty); close (m_tty); switch(waitpid(m_idProcess,&m_nExitCode,WNOHANG)); } if(m_bAutoDelete){ delete this; }}#endifvoid CSubprocess::Output (LPCTSTR psz){ m_pfnLogfunc(m_pLogparam,psz);}void CSubprocess::Send(LPCTSTR str){ char *psz=String(str).GetCString(); int nToWrite=strlen(psz); const char *c=psz; do {#ifdef _WIN32 DWORD dwWritten; if(!::WriteFile(m_hwPipe,psz,nToWrite,&dwWritten,0)){ break; }#else int dwWritten = write(m_tty, c, nToWrite); if(-1==dwWritten){ break; } #endif nToWrite-=(int)dwWritten; c+=(int)dwWritten; } while (nToWrite>0); //::FlushFileBuffers(m_hwPipe); delete [] psz;}bool CSubprocess::Kill(bool bRecurse){TRACE(_T("CSubprocess::Kill pid %d recurse=%d\n"),m_idProcess,bRecurse); PInfoArray arPinfo; bool rc=false; if(m_idProcess && -1!=m_idProcess){ // Start of with the easy one: if(bRecurse) { // Need to gather this information before we orphan our grandchildren: PSExtract(arPinfo); } #ifdef _WIN32 if(m_hProcess){ TRACE(_T("Terminate process %s\n"),(LPCTSTR)Name(m_idProcess)); rc=(TRUE==::TerminateProcess(m_hProcess,PROCESS_KILL_EXIT_CODE)); // dtor's (or subsequent Run's) responsibility to close the handle }#else rc=(0==kill(m_idProcess,SIGTERM)); int status; waitpid(m_idProcess,&status,WNOHANG);#endif if(bRecurse) { // kill process *and* its children // FIXME: needs to be top-down for(int i=0;i<(signed)arPinfo.size();i++){ if(arPinfo[i].IsChildOf(m_idProcess)){ #ifdef _WIN32 // begin hack const String strName(Name(arPinfo[i].PID)); if(_tcsstr(strName,_T("eCosTest")) || _tcsstr(strName,_T("cmd.EXE")) || _tcsstr(strName,_T("CMD.EXE")) || arPinfo[i].PID==(signed)GetCurrentProcessId()){ continue; } // end hack HANDLE hProcess=::OpenProcess(PROCESS_TERMINATE,false,arPinfo[i].PID); if(hProcess){ TRACE(_T("Terminate process %s\n"),(LPCTSTR)Name(arPinfo[i].PID)); rc&=(TRUE==::TerminateProcess(hProcess,PROCESS_KILL_EXIT_CODE)); CloseHandle(hProcess); } else { rc=false; }#else rc&=(0==kill(arPinfo[i].PID,SIGTERM)); int status; waitpid(arPinfo[i].PID,&status,WNOHANG);#endif } } } } return rc;}Time CSubprocess::CpuTime(bool bRecurse) const{ Time t=0; // kill process *and* its children // FIXME: needs to be top-down #ifdef _WIN32 __int64 ftCreation,ftExit,ftKernel,ftUser; if(m_hProcess && ::GetProcessTimes (m_hProcess,(FILETIME *)&ftCreation,(FILETIME *)&ftExit,(FILETIME *)&ftKernel,(FILETIME *)&ftUser)){ t+=Time((ftKernel+ftUser)/10000); } if(bRecurse){ PInfoArray arPinfo; PSExtract(arPinfo); if(m_idProcess && -1!=m_idProcess){ for(int i=0;i<(signed)arPinfo.size();i++){ if(arPinfo[i].IsChildOf(m_idProcess)){ t+=arPinfo[i].tCpu; } } } }#else PInfoArray arPinfo; PSExtract(arPinfo); for(int i=0;i<(signed)arPinfo.size();i++){ if(arPinfo[i].PID==m_idProcess || arPinfo[i].IsChildOf(m_idProcess)){ t+=arPinfo[i].tCpu; } }#endif return t;}#ifdef _WIN32bool CSubprocess::PSExtract(CSubprocess::PInfoArray &arPinfo){ bool rc=false; arPinfo.clear(); // If Windows NT: switch(GetPlatform()) { case VER_PLATFORM_WIN32_NT: if(hInstLib1) { // Get procedure addresses. static BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * ) = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))GetProcAddress( hInstLib1, "EnumProcesses" ) ; if( lpfEnumProcesses) { if(hInstLib2) { static DWORD (WINAPI *lpfNtQueryInformationProcess)( HANDLE, int, void *, DWORD, LPDWORD ) = (DWORD(WINAPI *)(HANDLE, int, void *, DWORD, LPDWORD)) GetProcAddress( hInstLib2,"NtQueryInformationProcess" ) ; if(lpfNtQueryInformationProcess){ DWORD dwMaxPids=256; DWORD dwPidSize; DWORD *arPids = NULL ; do { delete [] arPids; arPids=new DWORD[dwMaxPids]; } while(lpfEnumProcesses(arPids, dwMaxPids, &dwPidSize) && dwPidSize/sizeof(DWORD)==dwMaxPids) ; if(dwPidSize/sizeof(DWORD)<dwMaxPids){ rc=true; for( DWORD dwIndex = 0 ; (signed)dwIndex < dwPidSize/sizeof(DWORD); dwIndex++ ) { // Regardless of OpenProcess success or failure, we // still call the enum func with the ProcID. DWORD pid=arPids[dwIndex]; HANDLE hProcess=::OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pid ); if (hProcess ) { struct { DWORD ExitStatus; // receives process termination status DWORD PebBaseAddress; // receives process environment block address DWORD AffinityMask; // receives process affinity mask DWORD BasePriority; // receives process priority class ULONG UniqueProcessId; // receives process identifier ULONG InheritedFromUniqueProcessId; // receives parent process identifier } pbi; memset( &pbi, 0, sizeof(pbi)); DWORD retLen; __int64 ftCreation,ftExit,ftKernel,ftUser; if(lpfNtQueryInformationProcess(hProcess, 0 /*ProcessBasicInformation*/, &pbi, sizeof(pbi), &retLen)>=0 && TRUE==::GetProcessTimes (hProcess,(FILETIME *)&ftCreation,(FILETIME *)&ftExit,(FILETIME *)&ftKernel,(FILETIME *)&ftUser)){ // The second test is important. It excludes orphaned processes who appear to have been adopted by virtue of a new // process having been created with the same ID as their original parent. PInfo p; p.PID=pid; p.PPID=pbi.InheritedFromUniqueProcessId; p.tCreation=ftCreation; p.tCpu=Time((ftKernel+ftUser)/10000); arPinfo.push_back(p); } CloseHandle(hProcess); } } } delete [] arPids; } } } } break; case VER_PLATFORM_WIN32_WINDOWS: if( hInstLib1) { static HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD)= (HANDLE(WINAPI *)(DWORD,DWORD))GetProcAddress( hInstLib1,"CreateToolhelp32Snapshot" ) ; static BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32)= (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))GetProcAddress( hInstLib1, "Process32First" ) ; static BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32)= (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))GetProcAddress( hInstLib1, "Process32Next" ) ; if( lpfProcess32Next && lpfProcess32First && lpfCreateToolhelp32Snapshot) { // Get a handle to a Toolhelp snapshot of the systems // processes. HANDLE hSnapShot = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) ; if(INVALID_HANDLE_VALUE != hSnapShot) { // Get the first process' information. PROCESSENTRY32 procentry; procentry.dwSize = sizeof(PROCESSENTRY32) ; if(lpfProcess32First( hSnapShot, &procentry )){ rc=true; do { PInfo p; p.PID=procentry.th32ProcessID; p.PPID=procentry.th32ParentProcessID; arPinfo.push_back(p); } while(lpfProcess32Next( hSnapShot, &procentry )); } CloseHandle(hSnapShot); } } } break; default: break; } SetParents(arPinfo); if(!rc){ ERROR(_T("Couldn't get process information!\n")); } return rc;}#else // UNIXbool CSubprocess::PSExtract(CSubprocess::PInfoArray &arPinfo){ arPinfo.clear(); int i; FILE *f=popen("ps -l",_T("r") MODE_TEXT); if(f){ char buf[100]; while(fgets(buf,sizeof(buf)-1,f)){ TCHAR discard[100]; PInfo p; // Output is in the form // F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD //100 S 490 877 876 0 70 0 - 368 wait4 pts/0 00:00:00 bash int F,UID,C,PRI,NI,SZ,HH,MM,SS; bool rc=(15==_stscanf(buf,_T("%d %s %d %d %d %d %d %d %s %d %s %s %d:%d:%d"),&F,discard,&UID,&p.PID,&p.PPID,&C,&PRI,&NI,discard,&SZ,discard,discard,&HH,&MM,&SS)); if(rc){ p.tCpu=1000*(SS+60*(60*HH+MM)); arPinfo.push_back(p); } } pclose(f); for(i=0;i<(signed)arPinfo.size();i++){ int pid=arPinfo[i].PPID; arPinfo[i].pParent=0; for(int j=0;j<(signed)arPinfo.size();j++){ if(i!=j && arPinfo[j].PID==pid){ arPinfo[i].pParent=&arPinfo[j]; break; } } } } else { ERROR(_T("Failed to run ps -l\n")); } return true; //FIXME}#endifvoid CSubprocess::SetParents(CSubprocess::PInfoArray &arPinfo){ int i; for(i=0;i<(signed)arPinfo.size();i++){ PInfo &p=arPinfo[i]; p.pParent=0; for(int j=0;j<(signed)arPinfo.size();j++){ if(arPinfo[j].PID==p.PPID #ifdef _WIN32 && arPinfo[j].tCreation<p.tCreation#endif ) { arPinfo[i].pParent=&arPinfo[j]; break; } } } // Check for circularity bool bCircularity=false; for(i=0;i<(signed)arPinfo.size();i++){ PInfo *p=&arPinfo[i]; for(int j=0;j<(signed)arPinfo.size() && p;j++){ p=p->pParent; } // If all is well, p should be NULL here. Otherwise we have a loop. if(p){ // Make sure it can't foul things up: arPinfo[i].pParent=0; bCircularity=true; } } if(bCircularity){ ERROR(_T("!!! Circularly linked process list at index %d\n"),i); for(int k=0;k<(signed)arPinfo.size();k++){ const PInfo &p=arPinfo[k]; ERROR(_T("%d: %s ppid=%4d\n"),k,(LPCTSTR)Name(p.PID),p.PPID); } }}bool CSubprocess::PInfo::IsChildOf(int pid) const{ for(PInfo *p=pParent;p && p!=this;p=p->pParent) { // guard against circular linkage if(p->PID==pid){ return true; } } return false;}const String CSubprocess::Name(int pid){ String str(String::SFormat(_T("id=%d"),pid));#ifdef _DEBUG#ifdef _WIN32 if(VER_PLATFORM_WIN32_NT==GetPlatform() && hInstLib1){ static BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *, DWORD, LPDWORD ) = (BOOL(WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) GetProcAddress( hInstLib1,"EnumProcessModules" ) ; static DWORD (WINAPI *lpfGetModuleFileNameEx)( HANDLE, HMODULE, LPTSTR, DWORD )= (DWORD (WINAPI *)(HANDLE, HMODULE,LPTSTR, DWORD )) GetProcAddress( hInstLib1,"GetModuleFileNameExA" ) ; if( lpfEnumProcessModules && lpfGetModuleFileNameEx ) { HANDLE hProcess=::OpenProcess(PROCESS_ALL_ACCESS,false,pid); if(hProcess) { HMODULE hMod; DWORD dwSize; if(lpfEnumProcessModules( hProcess, &hMod, sizeof(HMODULE), &dwSize ) ){ // Get Full pathname: TCHAR buf[1+MAX_PATH]; lpfGetModuleFileNameEx( hProcess, hMod, buf, MAX_PATH); str+=_TCHAR(' '); str+=buf; } CloseHandle(hProcess); } } }#endif#endif return str;}#ifdef _WIN32DWORD CSubprocess::GetPlatform(){ OSVERSIONINFO osver; osver.dwOSVersionInfoSize = sizeof( osver ) ; return GetVersionEx( &osver ) ? osver.dwPlatformId : (DWORD)-1;}#endifbool CSubprocess::ProcessAlive(){ return !m_bThreadTerminated;}void CSubprocess::CloseInput(){#ifdef _WIN32 CloseHandle(m_hwPipe);m_hwPipe=INVALID_HANDLE_VALUE;#else close(m_tty);#endif}bool CSubprocess::Wait(Duration dTimeout){ return CeCosThreadUtils::WaitFor(m_bThreadTerminated,dTimeout);}const String CSubprocess::ErrorString() const{#ifdef _WIN32 TCHAR *pszMsg; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, m_nErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)&pszMsg, 0, NULL ); return pszMsg;#else return strerror(errno);#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -