35 #ifdef _FORTIFY_SOURCE
36 # undef _FORTIFY_SOURCE
38 #define _FORTIFY_SOURCE 0
51 #elif defined NCBI_OS_UNIX
58 # include <sys/time.h>
59 # include <sys/types.h>
60 # include <sys/wait.h>
63 # error "The CPipe class is supported only on Windows and Unix"
66 #define NCBI_USE_ERRCODE_X Connect_Pipe
69 #define IS_SET(flags, mask) (((flags) & (mask)) == (mask))
72 #define PIPE_THROW(err, errtxt) \
73 THROW0_TRACE(x_FormatError(int(err), errtxt))
106 DWORD rv = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
107 FORMAT_MESSAGE_FROM_SYSTEM |
108 FORMAT_MESSAGE_MAX_WIDTH_MASK |
109 FORMAT_MESSAGE_IGNORE_INSERTS,
111 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
115 errstr = errmsg.c_str();
120 ::LocalFree((HLOCAL) tmpstr);
131 return retval.
get() ? retval.
get() : message;
137 return "[CPipe::" + where +
"] " + what;
142 const STimeout* timeout,
int* exitcode)
148 if (x_exitcode < 0) {
151 }
else if (!exitinfo.
IsAlive()) {
155 x_exitcode = -(exitinfo.
GetSignal() + 1000);
162 unsigned long x_timeout;
163 if (!timeout || (timeout->
sec | timeout->
usec)) {
172 killed = process.
Kill (x_timeout);
188 *exitcode = x_exitcode;
212 const vector<string>& args)
216 for (
auto&& arg : args) {
231 #if defined(NCBI_OS_MSWIN)
239 return (
error == ERROR_NO_DATA ||
240 error == ERROR_BROKEN_PIPE ||
241 error == ERROR_PIPE_NOT_CONNECTED ?
true :
false);
257 const string& current_dir,
258 const char*
const env[],
307 m_Flags(0), m_SelfHandles(
false)
322 const vector<string>& args,
324 const string& current_dir,
325 const char*
const env[],
355 size += strlen(
env[count++]) + 1;
359 env_block.
reset(block);
362 for (
int i = 0;
i < count; ++
i) {
363 #if defined(NCBI_OS_MSWIN) && defined(_UNICODE)
365 size_t n =
tmp.size();
366 memcpy(block,
tmp.data(),
n *
sizeof(
TXChar));
367 block[
n++] =
_TX(
'\0');
369 size_t n = strlen(
env[
i]) + 1;
370 memcpy(block,
env[
i],
n);
377 HANDLE stdout_handle = ::GetStdHandle(STD_OUTPUT_HANDLE);
378 if (stdout_handle ==
NULL) {
381 HANDLE stderr_handle = ::GetStdHandle(STD_ERROR_HANDLE);
382 if (stderr_handle ==
NULL) {
391 ::FlushFileBuffers(stdout_handle);
394 ::FlushFileBuffers(stderr_handle);
398 SECURITY_ATTRIBUTES attr;
399 attr.nLength =
sizeof(attr);
400 attr.bInheritHandle =
TRUE;
401 attr.lpSecurityDescriptor =
NULL;
407 &attr, (
DWORD) pipe_size)) {
409 "Failed CreatePipe(stdin)");
411 ::SetHandleInformation(
m_ChildStdIn, HANDLE_FLAG_INHERIT, 0);
418 if (!::CreatePipe(&
m_ChildStdOut, &child_stdout, &attr, 0)) {
420 "Failed CreatePipe(stdout)");
422 ::SetHandleInformation(
m_ChildStdOut, HANDLE_FLAG_INHERIT, 0);
429 if (!::CreatePipe(&
m_ChildStdErr, &child_stderr, &attr, 0)) {
431 "Failed CreatePipe(stderr)");
433 ::SetHandleInformation(
m_ChildStdErr, HANDLE_FLAG_INHERIT, 0);
437 HANDLE current_process = ::GetCurrentProcess();
438 if (!::DuplicateHandle(current_process, stderr_handle,
439 current_process, &child_stderr,
440 0,
TRUE, DUPLICATE_SAME_ACCESS)) {
442 "Failed DuplicateHandle(stderr)");
446 child_stderr = child_stdout;
451 PROCESS_INFORMATION pinfo;
452 ::ZeroMemory(&pinfo,
sizeof(pinfo));
453 ::ZeroMemory(&sinfo,
sizeof(sinfo));
454 sinfo.cb =
sizeof(sinfo);
455 sinfo.hStdError = child_stderr;
456 sinfo.hStdOutput = child_stdout;
457 sinfo.hStdInput = child_stdin;
458 sinfo.dwFlags = STARTF_USESTDHANDLES;
459 # if defined(_UNICODE)
460 DWORD dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
462 DWORD dwCreationFlags = 0;
464 if (!::CreateProcess(
NULL,
467 dwCreationFlags, env_block.
get(),
473 "Failed CreateProcess('" + cmd_line +
"')");
482 catch (
string& what) {
483 static const STimeout kZeroZimeout = {0, 0};
484 Close(0, &kZeroZimeout);
495 && child_stderr != child_stdout) {
515 "Failed FlushFileBuffers(stdout)");
520 "Failed GetStdHandle(stdout)");
525 "Failed GetStdHandle(stdin)");
618 _ASSERT(!(from_handle & (from_handle - 1)));
638 DWORD bytes_avail = 0;
646 unsigned long x_sleep = 1;
658 "Failed PeekNamedPipe("
667 if (x_timeout != INFINITE) {
668 if (x_sleep > x_timeout) {
671 x_timeout -= x_sleep;
683 if (bytes_avail > count) {
684 bytes_avail = (
DWORD) count;
686 BOOL ok = ::ReadFile(fd,
buf, bytes_avail, &bytes_avail,
NULL);
690 "Failed to read data from pipe I/O handle "
694 *n_read = (size_t) bytes_avail;
699 catch (
string& what) {
708 size_t* n_written,
const STimeout* timeout)
const
711 _ASSERT(!n_written || !*n_written);
734 DWORD bytes_written = 0;
736 unsigned long x_sleep = 1;
739 &bytes_written,
NULL);
749 "Failed to write data to pipe I/O handle "
756 if (x_timeout != INFINITE) {
757 if (x_sleep > x_timeout) {
760 x_timeout -= x_sleep;
771 *n_written = bytes_written;
775 catch (
string& what) {
797 "All pipe I/O handles closed");
801 catch (
string& what) {
811 switch (from_handle) {
831 DWORD state = PIPE_READMODE_BYTE | PIPE_NOWAIT;
834 "Failed to set pipe I/O handle non-blocking");
852 unsigned long x_sleep = 1;
856 DWORD bytes_avail = 0;
858 &bytes_avail,
NULL)) {
863 "Failed PeekNamedPipe(stdout)");
866 }
else if (bytes_avail) {
872 DWORD bytes_avail = 0;
874 &bytes_avail,
NULL)) {
879 "Failed PeekNamedPipe(stderr)");
882 }
else if (bytes_avail) {
893 if (x_timeout != INFINITE) {
894 if (x_sleep > x_timeout) {
897 x_timeout -= x_sleep;
911 #elif defined(NCBI_OS_UNIX)
929 const vector<string>& args,
931 const string& current_dir,
932 const char*
const env[],
981 : m_ChildStdIn(-1), m_ChildStdOut(-1), m_ChildStdErr(-1),
982 m_Pid((
TPid)(-1)), m_Flags(0), m_SelfHandles(
false)
986 m_UsePoll = use_poll_param.Get();
1002 static void s_Exit(
int status,
int fd)
1004 int errcode = errno;
1005 (void) ::write(fd, &errcode,
sizeof(errcode));
1011 #ifndef HAVE_EXECVPE
1017 static int s_ExecShell(
const char*
command,
1018 char *
const argv[],
char *
const envp[])
1020 static const char kShell[] =
"/bin/sh";
1024 for (
i = 0; argv[
i]; ++
i);
1029 const char** args =
new const char*[
i + 1];
1035 for (;
i > 1; --
i) {
1036 args[
i] = argv[
i - 1];
1040 return ::execve(kShell, (
char**) args, envp);
1045 static int s_ExecVPE(
const char*
file,
char*
const argv[],
char*
const envp[])
1050 static const char* kPathDefault =
":/bin:/usr/bin";
1059 if (strchr(
file,
'/')) {
1060 ::execve(
file, argv, envp);
1061 return errno == ENOEXEC ? s_ExecShell(
file, argv, envp) : -1;
1065 const char* path = getenv(
"PATH");
1067 path = kPathDefault;
1069 size_t file_len = strlen(
file) + 1;
1070 char*
buf =
new char[strlen(path) + 1 + file_len];
1073 bool eacces_err =
false;
1075 const char*
next = strchr(path,
':');
1076 size_t len =
next ? (size_t)(
next - path) : strlen(path);
1081 if (
buf[
len - 1] !=
'/') {
1095 ::execve(
buf, argv, envp);
1096 if ((
error = errno) == ENOEXEC) {
1097 return s_ExecShell(
buf, argv, envp);
1125 # define execvpe s_ExecVPE
1129 static int x_SafeFD(
int fd,
int safe)
1131 if (fd == safe || fd > STDERR_FILENO) {
1134 int temp = ::fcntl(fd, F_DUPFD, STDERR_FILENO + 1);
1140 static bool x_SafePipe(
int pipe[2],
int n,
int safe)
1143 if ((pipe[0] = x_SafeFD(pipe[0],
n == 0 ? safe : -1)) == -1) {
1146 }
else if ((pipe[1] = x_SafeFD(pipe[1],
n == 1 ? safe : -1)) == -1) {
1155 const vector<string>& args,
1157 const string& current_dir,
1158 const char*
const env[],
1165 if (m_Pid != (
TPid)(-1)) {
1172 int pipe_in[2], pipe_out[2], pipe_err[2];
1179 int status_pipe[2] = {-1, -1};
1189 if (::pipe(pipe_in) < 0
1193 "Failed to create pipe for stdin");
1202 if (::pipe(pipe_out) < 0
1206 "Failed to create pipe for stdout");
1215 if (::pipe(pipe_err) < 0
1216 || !x_SafePipe(pipe_err, 1, STDERR_FILENO)) {
1219 "Failed to create pipe for stderr");
1227 if (::pipe(status_pipe) < 0
1228 || !x_SafePipe(status_pipe, -1, -1)) {
1230 "Failed to create status pipe");
1232 ::fcntl(status_pipe[1], F_SETFD,
1233 ::fcntl(status_pipe[1], F_GETFD, 0) | FD_CLOEXEC);
1236 switch (m_Pid = ::fork()) {
1258 s_Exit(-1, status_pipe[1]);
1265 (void) ::freopen(
"/dev/null",
"r", stdin);
1270 s_Exit(-1, status_pipe[1]);
1276 (void) ::freopen(
"/dev/null",
"w", stdout);
1279 if (pipe_err[1] != STDERR_FILENO) {
1280 if (::dup2(pipe_err[1], STDERR_FILENO) < 0) {
1281 s_Exit(-1, status_pipe[1]);
1291 s_Exit(-1, status_pipe[1]);
1294 (void) ::freopen(
"/dev/null",
"a", stderr);
1299 ::signal(SIGPIPE, SIG_DFL);
1304 const char** x_args =
new const char*[args.size() + 2];
1306 x_args[
i = 0] =
cmd.c_str();
1307 for (
auto&& arg : args) {
1308 x_args[++
i] = arg.c_str();
1313 if (!current_dir.empty() && current_dir !=
".") {
1314 (void) ::chdir(current_dir.c_str());
1319 status = execvpe(
cmd.c_str(),
1320 const_cast<char**
>(x_args),
1321 const_cast<char**
>(
env));
1323 status = ::execvp(
cmd.c_str(),
1324 const_cast<char**
>(x_args));
1326 s_Exit(status, status_pipe[1]);
1345 status_pipe[1] = -1;
1355 while ((
n = ::read(status_pipe[0], &errcode,
sizeof(errcode))) < 0) {
1360 status_pipe[0] = -1;
1364 status = eIO_Closed;
1365 ::waitpid(m_Pid,
NULL, 0);
1366 PIPE_THROW((
size_t)
n <
sizeof(errcode) ? 0 : errcode,
1372 catch (
string& what) {
1374 if (pipe_in[0] != -1) {
1377 if (pipe_out[1] != -1) {
1380 if (pipe_err[1] != -1) {
1383 if (status_pipe[0] != -1) {
1386 if (status_pipe[1] != -1) {
1401 if (m_Pid != (
TPid)(-1)) {
1440 if (m_Pid == (
TPid)(-1)) {
1444 status = eIO_Closed;
1500 _ASSERT(!(from_handle & (from_handle - 1)));
1505 if (m_Pid == (
TPid)(-1)) {
1523 if (bytes_read >= 0) {
1525 *n_read = (size_t) bytes_read;
1532 if (
error == EAGAIN ||
error == EWOULDBLOCK) {
1534 if ((timeout && !(timeout->
sec | timeout->
usec))
1535 || !
x_Poll(from_handle, timeout)) {
1541 if (
error != EINTR) {
1543 "Failed to read data from pipe I/O handle "
1553 catch (
string& what) {
1562 size_t* n_written,
const STimeout* timeout)
const
1565 _ASSERT(!n_written || !*n_written);
1570 if (m_Pid == (
TPid)(-1)) {
1575 status = eIO_Closed;
1588 if (bytes_written >= 0) {
1590 *n_written = (size_t) bytes_written;
1597 if (errno == EAGAIN || errno == EWOULDBLOCK) {
1599 if ((timeout && !(timeout->
sec | timeout->
usec))
1606 if (errno != EINTR) {
1607 if (
error == EPIPE) {
1609 status = eIO_Closed;
1612 "Failed to write data to pipe I/O handle "
1622 catch (
string& what) {
1636 if (m_Pid == (
TPid)(-1)) {
1644 "All pipe I/O handles closed");
1648 catch (
string& what) {
1658 switch (from_handle) {
1675 if (::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL, 0) | O_NONBLOCK) < 0) {
1677 "Failed to set pipe I/O handle non-blocking");
1688 struct pollfd poll_fds[3] = {
1693 int timeout_msec(timeout
1694 ? timeout->
sec * 1000 + (timeout->
usec + 500) / 1000
1700 poll_fds[0].
fd = -1;
1702 poll_fds[1].
fd = -1;
1704 poll_fds[2].
fd = -1;
1707 int n =
::poll(poll_fds, 3, timeout_msec);
1727 if ((
n = errno) != EINTR) {
1738 struct timeval*
tmp;
1743 tmo.tv_sec = timeout->
sec;
1744 tmo.tv_usec = timeout->
usec;
1800 +
" too large (maximum allowed "
1804 int n = ::select(
max + 1,
1806 wr ? &wfds : 0, &efds,
tmp);
1830 if ((
n = errno) != EINTR) {
1855 : m_PipeSize(pipe_size),
1856 m_PipeHandle(new
CPipeHandle), m_ReadHandle(eStdOut),
1857 m_ReadStatus(eIO_Closed), m_WriteStatus(eIO_Closed),
1858 m_ReadTimeout(0), m_WriteTimeout(0), m_CloseTimeout(0)
1865 const vector<string>& args,
1867 const string& current_dir,
1868 const char*
const env[],
1870 : m_PipeSize(pipe_size),
1871 m_PipeHandle(0), m_ReadHandle(eStdOut),
1872 m_ReadStatus(eIO_Closed), m_WriteStatus(eIO_Closed),
1873 m_ReadTimeout(0), m_WriteTimeout(0), m_CloseTimeout(0)
1875 unique_ptr<CPipeHandle> pipe_handle_ptr(
new CPipeHandle);
1876 EIO_Status status = pipe_handle_ptr->Open(
cmd, args, create_flags,
1877 current_dir,
env, pipe_size);
1880 "[CPipe::CPipe] Failed: " +
string(
IO_StatusStr(status)));
1894 const vector<string>& args,
1896 const string& current_dir,
1897 const char*
const env[],
1921 catch (
string& err) {
1960 if (from_handle ==
eStdIn) {
1975 if (from_handle ==
eStdIn) {
1982 if (count && !
buf) {
1997 if (count && !data) {
2034 switch (direction) {
2107 const vector<string>& args,
2112 const string& current_dir,
2113 const char*
const env[],
2121 ktm = *kill_timeout;
2126 CPipe pipe(pipe_size);
2133 "[CPipe::ExecWait] Cannot execute '"
2142 pipe.
Close(&exit_code);
2148 #ifndef NCBI_OS_LINUX
2149 const size_t buf_size = 16 * 1024;
2151 const size_t buf_size = 192 * 1024;
2156 size_t bytes_in_inbuf = 0;
2157 size_t bytes_written = 0;
2158 bool load_in =
true;
2163 static const STimeout kNoWait = {0, 0};
2164 static const STimeout kWait = {1, 0};
2168 if ((rmask &
fStdIn) || load_in) {
2169 bool done_in =
false;
2170 if (!bytes_in_inbuf) {
2173 }
else if ((bytes_in_inbuf =
2175 (
in,
inbuf.get(), buf_size)) != 0) {
2178 }
else if (!
in.good()) {
2180 }
else if (!(rmask & ~
fStdIn)) {
2184 if (bytes_in_inbuf && (rmask &
fStdIn)) {
2186 status = pipe.
Write(
inbuf.get() + bytes_written,
2187 bytes_in_inbuf, &x_written);
2188 bytes_in_inbuf -= x_written;
2190 if (bytes_in_inbuf) {
2194 "Cannot pass input data to '"
2199 }
else if (!bytes_in_inbuf) {
2202 bytes_written += x_written;
2214 status = pipe.
Read(
buf.get(), buf_size, &x_read);
2216 out.write(
buf.get(), x_read);
2226 err.write(
buf.get(), x_read);
2236 switch (watcher->
Watch(pid)) {
2253 pipe.
Close(&exit_code);
2256 pipe.
Close(&exit_code);
2263 switch (GetErrCode()) {
2264 case eOpen:
return "eOpen";
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
EIO_Status Open(const string &cmd, const vector< string > &args, CPipe::TCreateFlags create_flags, const string ¤t_dir, const char *const env[], size_t pipe_size)
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
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.
static DLIST_TYPE *DLIST_NAME() next(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
std::ofstream out("events_result.xml")
main entry point for tests
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 ...
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.
#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).
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"
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.
EIO_Status Open(const string &cmd, const vector< string > &args, TCreateFlags create_flags=0, const string ¤t_dir=kEmptyStr, const char *const env[]=0, size_t pipe_size=0)
Open pipe.
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.
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 env[]=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.
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 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.
void SleepMilliSec(unsigned long ml_sec, EInterruptOnSignal onsignal=eRestartOnSignal)
Defines a portable execute class.
std::istream & in(std::istream &in_, double &x_)
Provide poll call where missing.
#define poll(fds, nfds, timeout)