📄 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 + -