35 #ifdef _FORTIFY_SOURCE
36 # undef _FORTIFY_SOURCE
38 #define _FORTIFY_SOURCE 0
52 #elif defined NCBI_OS_UNIX
59 # include <sys/time.h>
60 # include <sys/types.h>
61 # include <sys/wait.h>
64 # error "The CPipe class is supported only on Windows and Unix"
67 #define NCBI_USE_ERRCODE_X Connect_Pipe
70 #define IS_SET(flags, mask) (((flags) & (mask)) == (mask))
73 #define PIPE_THROW(err, errtxt) \
74 THROW0_TRACE(x_FormatError(int(err), errtxt))
107 DWORD rv = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
108 FORMAT_MESSAGE_FROM_SYSTEM |
109 FORMAT_MESSAGE_MAX_WIDTH_MASK |
110 FORMAT_MESSAGE_IGNORE_INSERTS,
112 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
116 errstr = errmsg.c_str();
121 ::LocalFree((HLOCAL) tmpstr);
132 return retval.
get() ? retval.
get() : message;
138 return "[CPipe::" + where +
"] " + what;
143 const STimeout* timeout,
int* exitcode)
149 if (x_exitcode < 0) {
152 }
else if (!exitinfo.
IsAlive()) {
156 x_exitcode = -(exitinfo.
GetSignal() + 1000);
163 unsigned long x_timeout;
164 if (!timeout || (timeout->
sec | timeout->
usec)) {
173 killed = process.
Kill (x_timeout);
189 *exitcode = x_exitcode;
213 const vector<string>& args)
217 for (
auto&& arg : args) {
232 #if defined(NCBI_OS_MSWIN)
240 return (
error == ERROR_NO_DATA ||
241 error == ERROR_BROKEN_PIPE ||
242 error == ERROR_PIPE_NOT_CONNECTED ?
true :
false);
258 const string& current_dir,
259 const char*
const envp[],
308 m_Flags(0), m_SelfHandles(
false)
323 const vector<string>& args,
325 const string& current_dir,
326 const char*
const envp[],
349 if (
cmd.find_first_of(
":\\/") ==
NPOS) {
357 const string& comspec =
env->Get(
"COMSPEC");
362 if (x_cmd_line.empty()) {
363 x_cmd_line = cmd_line;
373 while (envp[
count]) {
378 env_block.
reset(block);
382 #if defined(NCBI_OS_MSWIN) && defined(_UNICODE)
384 size_t n =
tmp.size();
385 memcpy(block,
tmp.data(),
n *
sizeof(
TXChar));
386 block[
n++] =
_TX(
'\0');
388 size_t n = strlen(envp[
i]) + 1;
389 memcpy(block, envp[
i],
n);
396 HANDLE stdout_handle = ::GetStdHandle(STD_OUTPUT_HANDLE);
397 if (stdout_handle ==
NULL) {
400 HANDLE stderr_handle = ::GetStdHandle(STD_ERROR_HANDLE);
401 if (stderr_handle ==
NULL) {
410 ::FlushFileBuffers(stdout_handle);
413 ::FlushFileBuffers(stderr_handle);
417 SECURITY_ATTRIBUTES attr;
418 attr.nLength =
sizeof(attr);
419 attr.bInheritHandle =
TRUE;
420 attr.lpSecurityDescriptor =
NULL;
426 &attr, (
DWORD) pipe_size)) {
428 "Failed CreatePipe(stdin)");
430 ::SetHandleInformation(
m_ChildStdIn, HANDLE_FLAG_INHERIT, 0);
437 if (!::CreatePipe(&
m_ChildStdOut, &child_stdout, &attr, 0)) {
439 "Failed CreatePipe(stdout)");
441 ::SetHandleInformation(
m_ChildStdOut, HANDLE_FLAG_INHERIT, 0);
448 if (!::CreatePipe(&
m_ChildStdErr, &child_stderr, &attr, 0)) {
450 "Failed CreatePipe(stderr)");
452 ::SetHandleInformation(
m_ChildStdErr, HANDLE_FLAG_INHERIT, 0);
456 HANDLE current_process = ::GetCurrentProcess();
457 if (!::DuplicateHandle(current_process, stderr_handle,
458 current_process, &child_stderr,
459 0,
TRUE, DUPLICATE_SAME_ACCESS)) {
461 "Failed DuplicateHandle(stderr)");
465 child_stderr = child_stdout;
470 PROCESS_INFORMATION pinfo;
471 ::ZeroMemory(&pinfo,
sizeof(pinfo));
472 ::ZeroMemory(&sinfo,
sizeof(sinfo));
473 sinfo.cb =
sizeof(sinfo);
474 sinfo.hStdError = child_stderr;
475 sinfo.hStdOutput = child_stdout;
476 sinfo.hStdInput = child_stdin;
477 sinfo.dwFlags = STARTF_USESTDHANDLES;
478 # if defined(_UNICODE)
479 DWORD dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
481 DWORD dwCreationFlags = 0;
484 dwCreationFlags |= CREATE_NEW_PROCESS_GROUP;
485 if (!::CreateProcess(
NULL,
488 dwCreationFlags, env_block.
get(),
494 "Failed CreateProcess('" + cmd_line +
"')");
503 catch (
string& what) {
504 static const STimeout kZeroZimeout = {0, 0};
505 Close(0, &kZeroZimeout);
516 && child_stderr != child_stdout) {
536 "Failed FlushFileBuffers(stdout)");
541 "Failed GetStdHandle(stdout)");
546 "Failed GetStdHandle(stdin)");
639 _ASSERT(!(from_handle & (from_handle - 1)));
659 DWORD bytes_avail = 0;
667 unsigned long x_sleep = 1;
679 "Failed PeekNamedPipe("
688 if (x_timeout != INFINITE) {
689 if (x_sleep > x_timeout) {
692 x_timeout -= x_sleep;
704 if (bytes_avail >
count) {
707 BOOL ok = ::ReadFile(fd,
buf, bytes_avail, &bytes_avail,
NULL);
711 "Failed to read data from pipe I/O handle "
715 *n_read = (size_t) bytes_avail;
720 catch (
string& what) {
729 size_t* n_written,
const STimeout* timeout)
const
732 _ASSERT(!n_written || !*n_written);
755 DWORD bytes_written = 0;
757 unsigned long x_sleep = 1;
760 &bytes_written,
NULL);
770 "Failed to write data to pipe I/O handle "
777 if (x_timeout != INFINITE) {
778 if (x_sleep > x_timeout) {
781 x_timeout -= x_sleep;
792 *n_written = bytes_written;
796 catch (
string& what) {
818 "All pipe I/O handles closed");
822 catch (
string& what) {
832 switch (from_handle) {
852 DWORD state = PIPE_READMODE_BYTE | PIPE_NOWAIT;
855 "Failed to set pipe I/O handle non-blocking");
873 unsigned long x_sleep = 1;
877 DWORD bytes_avail = 0;
879 &bytes_avail,
NULL)) {
884 "Failed PeekNamedPipe(stdout)");
887 }
else if (bytes_avail) {
893 DWORD bytes_avail = 0;
895 &bytes_avail,
NULL)) {
900 "Failed PeekNamedPipe(stderr)");
903 }
else if (bytes_avail) {
914 if (x_timeout != INFINITE) {
915 if (x_sleep > x_timeout) {
918 x_timeout -= x_sleep;
932 #elif defined(NCBI_OS_UNIX)
955 const vector<string>& args,
957 const string& current_dir,
958 const char*
const envp[],
1007 : m_ChildStdIn(-1), m_ChildStdOut(-1), m_ChildStdErr(-1),
1008 m_Pid((
TPid)(-1)), m_Flags(0), m_SelfHandles(
false)
1010 m_UsePoll = s_UsePoll->
Get();
1026 [[noreturn]]
static void s_Exit(
int status,
int fd)
1028 int errcode = errno;
1029 (void) ::write(fd, &errcode,
sizeof(errcode));
1035 #ifndef HAVE_EXECVPE
1041 static int s_ExecShell(
const char*
command,
1042 char *
const argv[],
char *
const envp[],
1045 static const char kDefaultShell[] =
"/bin/sh";
1049 for (
i = 0; argv[
i]; ++
i);
1054 string xshell = xenv.
Get(
"SHELL");
1055 const char* shell = xshell.empty() ? kDefaultShell : xshell.c_str();
1058 const char** args =
new const char*[
i + 1];
1064 for (;
i > 1; --
i) {
1065 args[
i] = argv[
i - 1];
1069 return ::execve(shell, (
char**) args, envp);
1074 static int s_ExecVPE(
const char*
file,
char*
const argv[],
char*
const envp[])
1079 static const char kDefaultPath[] =
":/bin:/usr/bin";
1096 if (strchr(
file,
'/')) {
1097 ::execve(
file, argv, envp);
1098 return errno == ENOEXEC ? s_ExecShell(
file, argv, envp, *
env) : -1;
1102 const string& xpath =
env->Get(
"PATH");
1103 const char* path = xpath.empty() ? kDefaultPath : xpath.c_str();
1106 size_t file_len = strlen(
file) + 1;
1107 char*
buf =
new char[strlen(path) + 1 + file_len];
1110 bool eacces_err =
false;
1112 const char*
next = strchr(path,
':');
1113 size_t len =
next ? (size_t)(
next - path) : strlen(path);
1118 if (
buf[
len - 1] !=
'/') {
1132 ::execve(
buf, argv, envp);
1133 if ((
error = errno) == ENOEXEC) {
1134 return s_ExecShell(
buf, argv, envp, *
env);
1162 # define execvpe s_ExecVPE
1166 static int x_SafeFD(
int fd,
int safe)
1168 if (fd == safe || fd > STDERR_FILENO) {
1171 int temp = ::fcntl(fd, F_DUPFD, STDERR_FILENO + 1);
1177 static bool x_SafePipe(
int pipe[2],
int n,
int safe)
1180 if ((pipe[0] = x_SafeFD(pipe[0],
n == 0 ? safe : -1)) == -1) {
1183 }
else if ((pipe[1] = x_SafeFD(pipe[1],
n == 1 ? safe : -1)) == -1) {
1192 const vector<string>& args,
1194 const string& current_dir,
1195 const char*
const envp[],
1202 if (m_Pid != (
TPid)(-1)) {
1209 int pipe_in[2], pipe_out[2], pipe_err[2];
1216 int status_pipe[2] = {-1, -1};
1226 if (::pipe(pipe_in) < 0
1230 "Failed to create pipe for stdin");
1239 if (::pipe(pipe_out) < 0
1243 "Failed to create pipe for stdout");
1252 if (::pipe(pipe_err) < 0
1253 || !x_SafePipe(pipe_err, 1, STDERR_FILENO)) {
1256 "Failed to create pipe for stderr");
1264 if (::pipe(status_pipe) < 0
1265 || !x_SafePipe(status_pipe, -1, -1)) {
1267 "Failed to create status pipe");
1269 ::fcntl(status_pipe[1], F_SETFD,
1270 ::fcntl(status_pipe[1], F_GETFD, 0) | FD_CLOEXEC);
1273 switch (m_Pid = ::fork()) {
1295 s_Exit(-1, status_pipe[1]);
1302 (void) ::freopen(
"/dev/null",
"r", stdin);
1307 s_Exit(-1, status_pipe[1]);
1313 (void) ::freopen(
"/dev/null",
"w", stdout);
1316 if (pipe_err[1] != STDERR_FILENO) {
1317 if (::dup2(pipe_err[1], STDERR_FILENO) < 0) {
1318 s_Exit(-1, status_pipe[1]);
1328 s_Exit(-1, status_pipe[1]);
1331 (void) ::freopen(
"/dev/null",
"a", stderr);
1336 ::signal(SIGPIPE, SIG_DFL);
1341 const char** argv =
new const char*[args.size() + 2];
1343 argv[
i = 0] =
cmd.c_str();
1344 for (
auto&& arg : args) {
1345 argv[++
i] = arg.c_str();
1350 if (!current_dir.empty() && current_dir !=
".") {
1351 (void) ::chdir(current_dir.c_str());
1356 status = execvpe(argv[0],
1357 const_cast<char**
>(argv),
1358 const_cast<char**
>(envp));
1360 status = ::execvp(argv[0],
1361 const_cast<char**
>(argv));
1363 s_Exit(status, status_pipe[1]);
1382 status_pipe[1] = -1;
1392 while ((
n = ::read(status_pipe[0], &errcode,
sizeof(errcode))) < 0) {
1397 status_pipe[0] = -1;
1401 status = eIO_Closed;
1402 ::waitpid(m_Pid,
NULL, 0);
1403 PIPE_THROW((
size_t)
n <
sizeof(errcode) ? 0 : errcode,
1409 catch (
string& what) {
1411 if (pipe_in[0] != -1) {
1414 if (pipe_out[1] != -1) {
1417 if (pipe_err[1] != -1) {
1420 if (status_pipe[0] != -1) {
1423 if (status_pipe[1] != -1) {
1438 if (m_Pid != (
TPid)(-1)) {
1477 if (m_Pid == (
TPid)(-1)) {
1481 status = eIO_Closed;
1537 _ASSERT(!(from_handle & (from_handle - 1)));
1542 if (m_Pid == (
TPid)(-1)) {
1560 if (bytes_read >= 0) {
1562 *n_read = (size_t) bytes_read;
1569 if (
error == EAGAIN ||
error == EWOULDBLOCK) {
1571 if ((timeout && !(timeout->
sec | timeout->
usec))
1572 || !
x_Poll(from_handle, timeout)) {
1578 if (
error != EINTR) {
1580 "Failed to read data from pipe I/O handle "
1590 catch (
string& what) {
1599 size_t* n_written,
const STimeout* timeout)
const
1602 _ASSERT(!n_written || !*n_written);
1607 if (m_Pid == (
TPid)(-1)) {
1612 status = eIO_Closed;
1625 if (bytes_written >= 0) {
1627 *n_written = (size_t) bytes_written;
1634 if (errno == EAGAIN || errno == EWOULDBLOCK) {
1636 if ((timeout && !(timeout->
sec | timeout->
usec))
1643 if (errno != EINTR) {
1644 if (
error == EPIPE) {
1646 status = eIO_Closed;
1649 "Failed to write data to pipe I/O handle "
1659 catch (
string& what) {
1673 if (m_Pid == (
TPid)(-1)) {
1681 "All pipe I/O handles closed");
1685 catch (
string& what) {
1695 switch (from_handle) {
1712 if (::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL, 0) | O_NONBLOCK) < 0) {
1714 "Failed to set pipe I/O handle non-blocking");
1725 struct pollfd poll_fds[3] = {
1730 int timeout_msec(timeout
1731 ? timeout->
sec * 1000 + (timeout->
usec + 500) / 1000
1737 poll_fds[0].
fd = -1;
1739 poll_fds[1].
fd = -1;
1741 poll_fds[2].
fd = -1;
1744 int n =
::poll(poll_fds, 3, timeout_msec);
1764 if ((
n = errno) != EINTR) {
1775 struct timeval*
tmp;
1780 tmo.tv_sec = timeout->
sec;
1781 tmo.tv_usec = timeout->
usec;
1837 +
" too large (maximum allowed "
1841 int n = ::select(
max + 1,
1843 wr ? &wfds : 0, &efds,
tmp);
1867 if ((
n = errno) != EINTR) {
1892 : m_PipeSize(pipe_size),
1893 m_PipeHandle(new
CPipeHandle), m_ReadHandle(eStdOut),
1894 m_ReadStatus(eIO_Closed), m_WriteStatus(eIO_Closed),
1895 m_ReadTimeout(0), m_WriteTimeout(0), m_CloseTimeout(0)
1902 const vector<string>& args,
1904 const string& current_dir,
1905 const char*
const envp[],
1907 : m_PipeSize(pipe_size),
1908 m_PipeHandle(0), m_ReadHandle(eStdOut),
1909 m_ReadStatus(eIO_Closed), m_WriteStatus(eIO_Closed),
1910 m_ReadTimeout(0), m_WriteTimeout(0), m_CloseTimeout(0)
1912 unique_ptr<CPipeHandle> pipe_handle_ptr(
new CPipeHandle);
1913 EIO_Status status = pipe_handle_ptr->Open(
cmd, args, create_flags,
1914 current_dir, envp, pipe_size);
1917 "[CPipe::CPipe] Failed: " +
string(
IO_StatusStr(status)));
1931 const vector<string>& args,
1933 const string& current_dir,
1934 const char*
const envp[],
1958 catch (
string& err) {
1997 if (from_handle ==
eStdIn) {
2012 if (from_handle ==
eStdIn) {
2071 switch (direction) {
2144 const vector<string>& args,
2149 const string& current_dir,
2150 const char*
const envp[],
2158 ktm = *kill_timeout;
2163 CPipe pipe(pipe_size);
2170 "[CPipe::ExecWait] Cannot execute '"
2179 pipe.
Close(&exit_code);
2185 #ifndef NCBI_OS_LINUX
2186 const size_t buf_size = 16 * 1024;
2188 const size_t buf_size = 192 * 1024;
2193 size_t bytes_in_inbuf = 0;
2194 size_t bytes_written = 0;
2195 bool load_in =
true;
2200 static const STimeout kNoWait = {0, 0};
2201 static const STimeout kWait = {1, 0};
2205 if ((rmask &
fStdIn) || load_in) {
2206 bool done_in =
false;
2207 if (!bytes_in_inbuf) {
2210 }
else if ((bytes_in_inbuf =
2212 (
in,
inbuf.get(), buf_size)) != 0) {
2215 }
else if (!
in.good()) {
2217 }
else if (!(rmask & ~
fStdIn)) {
2221 if (bytes_in_inbuf && (rmask &
fStdIn)) {
2223 status = pipe.
Write(
inbuf.get() + bytes_written,
2224 bytes_in_inbuf, &x_written);
2225 bytes_in_inbuf -= x_written;
2227 if (bytes_in_inbuf) {
2231 "Cannot pass input data to '"
2236 }
else if (!bytes_in_inbuf) {
2239 bytes_written += x_written;
2251 status = pipe.
Read(
buf.get(), buf_size, &x_read);
2253 out.write(
buf.get(), x_read);
2263 err.write(
buf.get(), x_read);
2273 switch (watcher->
Watch(pid)) {
2290 pipe.
Close(&exit_code);
2293 pipe.
Close(&exit_code);
2300 switch (GetErrCode()) {
2301 case eOpen:
return "eOpen";
static CNcbiApplication * Instance(void)
Singleton method.
EIO_Status CloseHandle(CPipe::EChildIOHandle handle)
CPipe::TChildPollMask Poll(CPipe::TChildPollMask mask, const STimeout *timeout) const
EIO_Status Write(const void *data, size_t count, size_t *written, const STimeout *timeout) const
void x_SetNonBlockingMode(HANDLE fd) const
CPipe::TCreateFlags m_Flags
EIO_Status Read(void *buf, size_t count, size_t *n_read, const CPipe::EChildIOHandle from_handle, const STimeout *timeout) const
CPipe::TChildPollMask x_Poll(CPipe::TChildPollMask mask, const STimeout *timeout) const
TProcessHandle GetProcessHandle(void) const
EIO_Status Open(const string &cmd, const vector< string > &args, CPipe::TCreateFlags create_flags, const string ¤t_dir, const char *const envp[], size_t pipe_size)
HANDLE x_GetHandle(CPipe::EChildIOHandle from_handle) const
EIO_Status Close(int *exitcode, const STimeout *timeout)
Callback interface for ExecWait()
Extended exit information for waited process.
T & Get(void)
Create the variable if not created yet, return the reference.
std::ofstream out("events_result.xml")
main entry point for tests
static DLIST_TYPE *DLIST_NAME() next(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
#define poll(fds, nfds, timeout)
void reset(element_type *p=0, EOwnership ownership=eTakeOwnership)
Reset will delete the old pointer (if owned), set content to the new value, and assume the ownership ...
CNcbiEnvironment & SetEnvironment(void)
Get a non-const copy of the application's cached environment.
static CNcbiApplicationGuard InstanceGuard(void)
Singleton method.
element_type * get(void) const
Get pointer.
@ eTakeOwnership
An object can take ownership of another.
@ eNoOwnership
No ownership is assumed.
#define ERR_POST_ONCE(message)
Error posting only once during program execution.
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
const string & Get(const string &name, bool *found=NULL) const
Get environment value by name.
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
void Trace(CExceptionArgs_Base &args)
virtual const char * GetErrCodeString(void) const override
Translate from the error code value to its string representation.
static string QuoteArg(const string &arg)
Quote argument.
#define NCBI_PARAM_TYPE(section, name)
Generate typename for a parameter from its {section, name} attributes.
#define NCBI_PARAM_DECL(type, section, name)
Parameter declaration.
#define NCBI_PARAM_DEF_EX(type, section, name, default_value, flags, env)
Definition of a parameter with additional flags.
@ eParam_Default
Default flags.
virtual EAction Watch(TProcessHandle)=0
This method is getting called periodically during the process execution by the ExecWait() method.
EIO_Status m_ReadStatus
Last read status.
EIO_Status Write(const void *data, size_t count, size_t *written=0)
Write data to pipe (data always goes to the child's eStdIn handle).
EIO_Status Open(const string &cmd, const vector< string > &args, TCreateFlags create_flags=0, const string ¤t_dir=kEmptyStr, const char *const envp[]=0, size_t pipe_size=0)
Open pipe.
EChildIOHandle m_ReadHandle
Default handle used for read.
EChildIOHandle
Which of the child I/O handles to use.
TChildPollMask Poll(TChildPollMask mask, const STimeout *timeout=0)
Wait for I/O event(s).
EFinish
ExecWait return code.
TProcessHandle GetProcessHandle(void) const
Get the process handle for the piped child.
unsigned int TChildPollMask
bitwise OR of "EChildIOHandle"
static EFinish ExecWait(const string &cmd, const vector< string > &args, CNcbiIstream &in, CNcbiOstream &out, CNcbiOstream &err, int &exit_code, const string ¤t_dir=kEmptyStr, const char *const envp[]=0, IProcessWatcher *watcher=0, const STimeout *kill_timeout=0, size_t pipe_size=0)
Execute a command with a vector of arguments, and wait for its completion.
void OpenSelf(void)
Open the standard streams of the current process.
EIO_Status SetReadHandle(EChildIOHandle from_handle)
Set standard output handle to read data from.
virtual EAction OnStart(TProcessHandle)
This method is called when the process has just been started by the ExecWait() method.
const STimeout * m_ReadTimeout
eIO_Read timeout
size_t m_PipeSize
Pipe size.
CPipe(size_t pipe_size=0)
Constructor.
virtual ~IProcessWatcher()
STimeout m_CloseTimeoutValue
Storage for m_CloseTimeout.
EIO_Status SetTimeout(EIO_Event event, const STimeout *timeout)
Specify timeout for the pipe I/O.
STimeout m_WriteTimeoutValue
Storage for m_WriteTimeout.
CPipeHandle * m_PipeHandle
Internal OS-specific pipe handle.
EIO_Status Read(void *buf, size_t count, size_t *read=0, EChildIOHandle from_handle=eDefault)
Read data from the pipe's default read handle.
STimeout m_ReadTimeoutValue
Storage for m_ReadTimeout.
const STimeout * m_CloseTimeout
eIO_Close timeout
unsigned int TCreateFlags
bitwise OR of "ECreateFlag"
const STimeout * GetTimeout(EIO_Event event) const
Get pipe I/O timeout.
EIO_Status CloseHandle(EChildIOHandle handle)
Close the specified child's pipe handle (even for CPipe opened with OpenSelf()).
EIO_Status m_WriteStatus
Last write status.
virtual const char * GetErrCodeString(void) const override
Translate from an error code value to its string representation.
EIO_Status Close(int *exitcode=0)
Close pipe.
const STimeout * m_WriteTimeout
eIO_Write timeout
EIO_Status Status(EIO_Event direction) const
Return a status of the last I/O operation.
@ eDefault
see SetReadHandle()
@ eDone
Process finished normally.
@ eCanceled
Watcher requested to bail out.
@ fKillOnClose
Close(): kill child process if it hasn't terminated within the allotted time.
@ fNewGroup
UNIX: new process group will be created, and the child process will become the leader of the new proc...
@ fKeepOnClose
Close(): just return eIO_Timeout if Close() cannot complete within the allotted time; don't close any...
@ fSigPipe_Restore
Restore SIGPIPE processing for child process to system default.
@ fStdErr_Open
Do open child's stderr.
@ fStdIn_Close
Do not open child's stdin.
@ fStdOut_Close
Do not open child's stdout.
@ fStdErr_Share
Keep stderr (share it with child)
@ fStdErr_StdOut
Redirect stderr to whatever stdout goes.
@ eContinue
Continue running.
@ eStop
Kill the child process and exit.
@ eExit
Exit without waiting for the child process.
bool IsPresent(void) const
TRUE if the object contains information about the process state.
bool KillGroup(unsigned long timeout=kDefaultKillTimeout) const
Terminate a group of processes.
bool IsExited(void) const
TRUE if the process terminated normally.
int GetSignal(void) const
Get the signal number that has caused the process to terminate (UNIX only).
bool Kill(unsigned long timeout=kDefaultKillTimeout)
Terminate process.
int Wait(unsigned long timeout=kInfiniteTimeoutMs, CExitInfo *info=0) const
Wait until process terminates.
static const unsigned long kDefaultKillTimeout
Default wait time (milliseconds) between "soft" and "hard" attempts to terminate a process.
pid_t TPid
Process identifier (PID) and process handle.
bool IsAlive(void) const
TRUE if the process is still alive.
bool IsSignaled(void) const
TRUE if the process terminated by a signal (UNIX only).
int GetExitCode(void) const
Get process exit code.
@ ePid
A real process identifier (pid).
@ eHandle
A process handle (MS Windows).
#define END_NCBI_SCOPE
End previously defined NCBI scope.
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
#define NCBI_AS_STRING(value)
Convert some value to string even if this value is macro itself.
ESwitch SOCK_SetInterruptOnSignalAPI(ESwitch on_off)
Control restartability of I/O interrupted by signals.
IO_PREFIX::ostream CNcbiOstream
Portable alias for ostream.
IO_PREFIX::istream CNcbiIstream
Portable alias for istream.
static streamsize Readsome(CNcbiIstream &is, CT_CHAR_TYPE *buf, streamsize buf_size)
static int CompareNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive compare of a substring with another string.
static const string BoolToString(bool value)
Convert bool to string.
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
#define DEFINE_STATIC_FAST_MUTEX(id)
Define static fast mutex and initialize it.
const long kMicroSecondsPerSecond
Number of microseconds in one second.
unsigned long NcbiTimeoutToMs(const STimeout *timeout)
unsigned int usec
microseconds (modulo 1,000,000)
const char * IO_StatusStr(EIO_Status status)
Get the text form of an enum status value.
STimeout * NcbiMsToTimeout(STimeout *timeout, unsigned long ms)
const char * NcbiMessagePlusError(int *dynamic, const char *message, int error, const char *descr)
Add current "error" (and maybe its description) to the message: <message>[ {error=[[<error>][,...
EIO_Event
I/O event (or direction).
@ eIO_Timeout
timeout expired before any I/O succeeded
@ eIO_Interrupt
signal arrival prevented any I/O to succeed
@ eIO_Success
everything is fine, no error occurred
@ eIO_Unknown
unknown I/O error (likely fatal but can retry)
@ eIO_InvalidArg
bad argument / parameter value(s) supplied
@ eIO_ReadWrite
eIO_Read | eIO_Write (also, eCONN_OnFlush)
@ eIO_Close
also serves as an error indicator in SOCK_Poll
#define INVALID_HANDLE_VALUE
A value for an invalid file handle.
#define HANDLE
An abstraction for a file handle.
Definition of all error codes used in connect library (xconnect.lib, xconnext.lib etc).
const struct ncbi::grid::netcache::search::fields::SIZE size
static const STimeout kZeroTimeout
static string x_FormatError(int error, const string &message)
AutoPtr< char, CDeleter< char > > TTempCharPtr
static string s_FormatErrorMessage(const string &where, const string &what)
const unsigned long kWaitPrecision
static const STimeout * s_SetTimeout(const STimeout *from, STimeout *to)
#define IS_SET(flags, mask)
static string x_GetHandleName(CPipe::EChildIOHandle handle)
#define PIPE_THROW(err, errtxt)
static bool x_IsDisconnectError(DWORD error)
static string x_CommandLine(const string &cmd, const vector< string > &args)
static EIO_Status s_Close(CProcess &process, CPipe::TCreateFlags flags, const STimeout *timeout, int *exitcode)
Portable class to work with a spawned process via pipes.
Static variables safety - create on demand, destroy on application termination.
#define TRUE
bool replacment for C indicating true.
void SleepMilliSec(unsigned long ml_sec, EInterruptOnSignal onsignal=eRestartOnSignal)
Defines a portable execute class.
std::istream & in(std::istream &in_, double &x_)