📄 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;
}
}
#endif
void 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 _WIN32
bool 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 // UNIX
bool 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
}
#endif
void 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 _WIN32
DWORD CSubprocess::GetPlatform()
{
OSVERSIONINFO osver;
osver.dwOSVersionInfoSize = sizeof( osver ) ;
return GetVersionEx( &osver ) ? osver.dwPlatformId : (DWORD)-1;
}
#endif
bool 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 + -