📄 subprocess.cpp
字号:
Log(_T("Failed to create gdb process - %s\n"),strerror(errno)); pid=0; break; case 0: // Process is created (we're the child) // No point in outputting except via output streams // Input to child process if (dup2(pipe_ends_w[0], 0) < 0) { _ftprintf(stderr,(_T("dup2 error\n")); exit(1); } // Output from process if (dup2(pipe_ends_r[1], 2) < 0) { _ftprintf(stderr,(_T("dup2 error\n")); exit(2); } if (dup2(pipe_ends_r[1], 1) < 0) { _ftprintf(stderr,(_T("dup2 error\n")); exit(3); } setvbuf(stdout,0,_IONBF,0); setvbuf(stderr,0,_IONBF,0); if(m_bVerbose){ strMsg.Format(_T("*** Process %d created \"%s\"\n"),pid,(LPCTSTR)m_strCmd); } StringArray ar; int argc=m_strCmd.Chop(ar,_TCHAR(' '),true); TCHAR **argv=new TCHAR *[1+argc]; int i; for(i=0;i<argc;i++){ argv[i]=ar[i]; } argv[i]=0; _texecvp(argv[0], argv); delete [] argv; _ftprintf(stderr,(_T("exec error - %s\n"),strerror(errno)); exit(4); default: // Process is created (we're the parent) TRACE(_T("Forked to create gdb process %s - pid is <%d>\n"), pszCmdline, pid); if (fcntl(pipe_ends_r[0], F_SETFL, O_NONBLOCK) <0) { Log(_T("Couldn't set pipe non-blocking - %s\n"),strerror(errno)); } else { m_rPipeHandle=(void *)pipe_ends_r[0]; m_wPipeHandle=(void *)pipe_ends_w[1]; } break; } close (pipe_ends_r[0]); close (pipe_ends_r[1]); } close (pipe_ends_w[0]); close (pipe_ends_w[1]); } return pid;}#endifDWORD CSubprocess::ThreadFunc(){ DWORD dwAvail; while (::PeekNamedPipe(m_hrPipe, NULL, 0, 0, &dwAvail, NULL)){ if(dwAvail){ DWORD dwRead; char *buf=new char[dwAvail+1]; if(!::ReadFile(m_hrPipe, buf, dwAvail, &dwRead, NULL)){ delete [] buf; break; } buf[dwRead]='\0'; Output(String::CStrToUnicodeStr(buf)); delete [] buf; } else { DWORD dw; ::GetExitCodeProcess(m_hProcess, &dw); if(STILL_ACTIVE!=dw){ break; } Sleep(250); } } ::GetExitCodeProcess(m_hProcess, &m_dwExitCode); String strMsg; if(m_bVerbose){ if(PROCESS_KILL_EXIT_CODE==m_dwExitCode){ strMsg.Format(_T("\n*** Process %d killed\n"),m_idProcess); } else { strMsg.Format(_T("\n*** Process %d terminated (rc=%d)\n"),m_idProcess,m_dwExitCode); } Output(strMsg); } if(m_dwParentThreadId || m_hwndParent){ Post(0); } m_idProcess=0; ::CloseHandle(m_hrPipe); ::CloseHandle(m_hwPipe); ::CloseHandle(m_hProcess); m_bThreadRunning=false; DWORD rc=m_dwExitCode; // protect against auto-delete if(m_bAutoDelete){ delete this; } return rc;}bool CSubprocess::Kill(){ if(0!=m_idProcess){ //TRACE(_T("*** Killing process %d(ctrl/c)\n"),m_idProcess); //::GenerateConsoleCtrlEvent( CTRL_C_EVENT, m_idProcess); //if(WAIT_TIMEOUT==WaitForSingleObject(m_hThread,1000)){ //TRACE(_T("*** Killing process %d(ctrl/break)\n"),m_idProcess); //::GenerateConsoleCtrlEvent( CTRL_BREAK_EVENT, m_idProcess); //if(WAIT_TIMEOUT==WaitForSingleObject(m_hThread,1000)){ if(m_bVerbose){ String strMsg; strMsg.Format(_T("*** Killing process %d (TerminateProcess)\n"),m_idProcess); Output(strMsg); } ::TerminateProcess(m_hProcess,PROCESS_KILL_EXIT_CODE); //} //} } return 0==m_idProcess;}void CSubprocess::Output (LPCTSTR psz){ if(m_dwParentThreadId || m_hwndParent){ TCHAR *pszCopy=new TCHAR[1+_tcslen(psz)]; _tcscpy(pszCopy,psz); Post((LPARAM)pszCopy); } else if (m_pfnLogfunc) { m_pfnLogfunc(m_pLogparam,psz); } else { assert(NULL!=m_pstrOutput); (*m_pstrOutput)+=psz; }}void CSubprocess::Post(LPARAM lParam){ if(m_hwndParent){ ::PostMessage(m_hwndParent,WM_SUBPROCESS,(WPARAM)this,lParam); } else { assert(m_dwParentThreadId); ::PostThreadMessage(m_dwParentThreadId,WM_SUBPROCESS,(WPARAM)m_idProcess,lParam); }}void CSubprocess::CygKill(){ // Map win32 pids to cygwin format PtrArray map; int nKillCount; int nGid=-1; do { nKillCount=0; // Execute a "ps -l" to find out what's out there in Cygwin land CSubprocess sp; String strOutput; sp.Run(strOutput,_T("ps -l")); if(0==strOutput.GetLength()){ if(m_bVerbose){ Output(_T("*** Warning: could not run ps to effect a Cygkill()\n")); } } else { // Walk through the lines by line and extract what we need for(LPCTSTR psz=-1+(LPCTSTR)strOutput;psz;psz=_tcschr(psz,_TCHAR('\n'))){ psz++; // move over the '\n' CygProcessInfo cpi; if(0==_tcsstr(psz,_T("ps.exe")) && 4==_stscanf(2+psz,_T("%d %d %d %d"),&cpi.nPid,&cpi.nPpid,&cpi.nPgid,&cpi.nWinpid) && cpi.nWinpid){ for(unsigned int i=0;i<map.size();i++){ if(((CygProcessInfo *)map[i])->nWinpid==cpi.nWinpid){ break; } } if(i==map.size()){ // No existing match - add: map.push_back(new CygProcessInfo(cpi)); if((int)m_idProcess==cpi.nWinpid){ nGid=cpi.nPgid; } } } } // Kill everything in the same group as our process if(-1!=nGid){ for (unsigned int i=0;i<map.size();i++){ CygProcessInfo *pcpi=(CygProcessInfo *)map[i]; if(pcpi->nPgid==nGid){ // Check that the process exists HANDLE hProcess=OpenProcess(PROCESS_TERMINATE,false,pcpi->nWinpid); if(hProcess){ CloseHandle(hProcess); String strCmd,strOut; strCmd.Format(_T("kill %d"),pcpi->nPid); pcpi->nPgid=-pcpi->nPgid; // prevent this being done more than once CSubprocess::Run(strCmd); nKillCount++; } } } } } } while (nKillCount>0); // Now we've sent a kill to every process. Go back and check they are really dead (use windows API this time) for(unsigned int i=0;i<map.size();i++){ CygProcessInfo *pcpi=(CygProcessInfo *)map[i]; if(abs(pcpi->nPgid)==nGid){ HANDLE hProcess=OpenProcess(PROCESS_TERMINATE,false,pcpi->nWinpid); if(hProcess){ ::TerminateProcess(hProcess,0x7fffffff); CloseHandle(hProcess); } } } for(i=0;i<map.size();i++){ delete (CygProcessInfo *)map[i]; }}void CSubprocess::Send(LPCTSTR str){ int nLength=_tcslen(str); char *psz=new char[1+nLength];#ifdef _UNICODE WideCharToMultiByte(CP_ACP, 0, str, -1, psz, 1+nLength, NULL, NULL);#else strcpy(psz,str);#endif DWORD dwWritten; ::WriteFile(m_hwPipe,psz,nLength,&dwWritten,0); delete [] psz;}void CSubprocess::CloseInput(){ ::CloseHandle(m_hwPipe);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -