📄 pipechan.cxx
字号:
// and set ourselves as out own process group so we don't get signals // from our parent's terminal (hopefully!) PSETPGRP(); // setup the arguments, not as we are about to execl or exit, we don't // care about memory leaks, they are not real! char ** args = (char **)calloc(argumentList.GetSize()+2, sizeof(char *)); args[0] = strdup(subProgName.GetTitle()); PINDEX i; for (i = 0; i < argumentList.GetSize(); i++) args[i+1] = strdup(argumentList[i].GetPointer()); // Set up new environment if one specified. if (environment != NULL) {#if defined(P_SOLARIS) || defined(P_FREEBSD) || defined(P_OPENBSD) || defined (P_NETBSD) || defined(__BEOS__) || defined(P_MACOSX) || defined(P_MACOS) || defined (P_AIX) || defined(P_IRIX) || defined(P_QNX) extern char ** environ;# if defined(P_MACOSX)# define environ (*_NSGetEnviron())# endif# define __environ environ#endif __environ = (char **)calloc(environment->GetSize()+1, sizeof(char*)); for (i = 0; i < environment->GetSize(); i++) { PString str = environment->GetKeyAt(i) + '=' + environment->GetDataAt(i); __environ[i] = strdup(str); } } // execute the child as required if (searchPath) execvp(subProgram, args); else execv(subProgram, args); exit(2); return FALSE;#endif // P_VXWORKS || P_RTEMS}BOOL PPipeChannel::Close(){ // close pipe from child if (fromChildPipe[0] != -1) { ::close(fromChildPipe[0]); fromChildPipe[0] = -1; } if (fromChildPipe[1] != -1) { ::close(fromChildPipe[1]); fromChildPipe[1] = -1; } // close pipe to child if (toChildPipe[0] != -1) { ::close(toChildPipe[0]); toChildPipe[0] = -1; } if (toChildPipe[1] != -1) { ::close(toChildPipe[1]); toChildPipe[1] = -1; } // close pipe to child if (stderrChildPipe[0] != -1) { ::close(stderrChildPipe[0]); stderrChildPipe[0] = -1; } if (stderrChildPipe[1] != -1) { ::close(stderrChildPipe[1]); stderrChildPipe[1] = -1; } // kill the child process if (IsRunning()) { kill (childPid, SIGKILL); WaitForTermination(); } // ensure this channel looks like it is closed os_handle = -1; childPid = 0; return TRUE;}BOOL PPipeChannel::Read(void * buffer, PINDEX len){ PAssert(IsOpen(), "Attempt to read from closed pipe"); PAssert(fromChildPipe[0] != -1, "Attempt to read from write-only pipe"); os_handle = fromChildPipe[0]; BOOL status = PChannel::Read(buffer, len); os_handle = 0; return status;}BOOL PPipeChannel::Write(const void * buffer, PINDEX len){ PAssert(IsOpen(), "Attempt to write to closed pipe"); PAssert(toChildPipe[1] != -1, "Attempt to write to read-only pipe"); os_handle = toChildPipe[1]; BOOL status = PChannel::Write(buffer, len); os_handle = 0; return status;}BOOL PPipeChannel::Execute(){ flush(); clear(); if (toChildPipe[1] != -1) { ::close(toChildPipe[1]); toChildPipe[1] = -1; } return TRUE;}PPipeChannel::~PPipeChannel(){ Close();}int PPipeChannel::GetReturnCode() const{ return retVal;}BOOL PPipeChannel::IsRunning() const{ if (childPid == 0) return FALSE;#if defined(P_PTHREADS) || defined(P_MAC_MPTHREADS) int err; int status; if ((err = waitpid(childPid, &status, WNOHANG)) == 0) return TRUE; if (err != childPid) return FALSE; PPipeChannel * thisW = (PPipeChannel *)this; thisW->childPid = 0; if (WIFEXITED(status)) { thisW->retVal = WEXITSTATUS(status); PTRACE(2, "PipeChannel\tChild exited with code " << retVal); } else if (WIFSIGNALED(status)) { PTRACE(2, "PipeChannel\tChild was signalled with " << WTERMSIG(status)); thisW->retVal = -1; } else if (WIFSTOPPED(status)) { PTRACE(2, "PipeChannel\tChild was stopped with " << WSTOPSIG(status)); thisW->retVal = -1; } else { PTRACE(2, "PipeChannel\tChild was stopped with unknown status" << status); thisW->retVal = -1; } return FALSE;#else return kill(childPid, 0) == 0;#endif}int PPipeChannel::WaitForTermination(){ if (childPid == 0) return retVal; int err;#if defined(P_PTHREADS) || defined(P_MAC_MPTHREADS) int status; do { err = waitpid(childPid, &status, 0); if (err == childPid) { childPid = 0; if (WIFEXITED(status)) { retVal = WEXITSTATUS(status); PTRACE(2, "PipeChannel\tChild exited with code " << retVal); } else if (WIFSIGNALED(status)) { PTRACE(2, "PipeChannel\tChild was signalled with " << WTERMSIG(status)); retVal = -1; } else if (WIFSTOPPED(status)) { PTRACE(2, "PipeChannel\tChild was stopped with " << WSTOPSIG(status)); retVal = -1; } else { PTRACE(2, "PipeChannel\tChild was stopped with unknown status" << status); retVal = -1; } return retVal; } } while (errno == EINTR);#else if ((err = kill (childPid, 0)) == 0) return retVal = PThread::Current()->PXBlockOnChildTerminate(childPid, PMaxTimeInterval);#endif ConvertOSError(err); return -1;}int PPipeChannel::WaitForTermination(const PTimeInterval & timeout){ if (childPid == 0) return retVal; int err;#if defined(P_PTHREADS) || defined(P_MAC_MPTHREADS) PAssert(timeout == PMaxTimeInterval, PUnimplementedFunction); int status; do { err = waitpid(childPid, &status, 0); if (err == childPid) { childPid = 0; if (WIFEXITED(status)) { retVal = WEXITSTATUS(status); PTRACE(2, "PipeChannel\tChild exited with code " << retVal); } else if (WIFSIGNALED(status)) { PTRACE(2, "PipeChannel\tChild was signalled with " << WTERMSIG(status)); retVal = -1; } else if (WIFSTOPPED(status)) { PTRACE(2, "PipeChannel\tChild was stopped with " << WSTOPSIG(status)); retVal = -1; } else { PTRACE(2, "PipeChannel\tChild was stopped with unknown status" << status); retVal = -1; } return retVal; } } while (errno == EINTR);#else if ((err = kill (childPid, 0)) == 0) return retVal = PThread::Current()->PXBlockOnChildTerminate(childPid, timeout);#endif ConvertOSError(err); return -1;}BOOL PPipeChannel::Kill(int killType){ return ConvertOSError(kill (childPid, killType));}BOOL PPipeChannel::CanReadAndWrite(){ return TRUE;}BOOL PPipeChannel::ReadStandardError(PString & errors, BOOL wait){ PAssert(IsOpen(), "Attempt to read from closed pipe"); PAssert(stderrChildPipe[0] != -1, "Attempt to read from write-only pipe"); os_handle = stderrChildPipe[0]; BOOL status = FALSE;#ifndef BE_BONELESS int available; if (ConvertOSError(ioctl(stderrChildPipe[0], FIONREAD, &available))) { if (available != 0) status = PChannel::Read(errors.GetPointer(available+1), available); else if (wait) { char firstByte; status = PChannel::Read(&firstByte, 1); if (status) { errors = firstByte; if (ConvertOSError(ioctl(stderrChildPipe[0], FIONREAD, &available))) { if (available != 0) status = PChannel::Read(errors.GetPointer(available+2)+1, available); } } } }#endif os_handle = 0; return status;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -