NCBI C++ ToolKit
ncbi_process.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef CORELIB___NCBI_PROCESS__HPP
2 #define CORELIB___NCBI_PROCESS__HPP
3 
4 /* $Id: ncbi_process.hpp 99384 2023-03-20 17:50:49Z ivanov $
5  * ===========================================================================
6  *
7  * PUBLIC DOMAIN NOTICE
8  * National Center for Biotechnology Information
9  *
10  * This software/database is a "United States Government Work" under the
11  * terms of the United States Copyright Act. It was written as part of
12  * the author's official duties as a United States Government employee and
13  * thus cannot be copyrighted. This software/database is freely available
14  * to the public for use. The National Library of Medicine and the U.S.
15  * Government have not placed any restriction on its use or reproduction.
16  *
17  * Although all reasonable efforts have been taken to ensure the accuracy
18  * and reliability of the software and data, the NLM and the U.S.
19  * Government do not and cannot warrant the performance or results that
20  * may be obtained by using this software or data. The NLM and the U.S.
21  * Government disclaim all warranties, express or implied, including
22  * warranties of performance, merchantability or fitness for any particular
23  * purpose.
24  *
25  * Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Authors: Aaron Ucko, Vladimir Ivanov
30  *
31  *
32  */
33 
34 /// @file ncbi_process.hpp
35 /// Defines process management classes.
36 ///
37 /// Defines classes:
38 /// CProcess
39 /// CPIDGuard
40 ///
41 /// Implemented for: UNIX, MS-Windows
42 
43 
45 
46 #if defined(NCBI_OS_UNIX)
47 # include <sys/types.h>
48 #elif defined(NCBI_OS_MSWIN)
49 # include <corelib/ncbi_os_mswin.hpp>
50 #else
51 # error "CProcess is not implemented on this platform"
52 #endif
53 
54 
56 
57 /** @addtogroup Process
58  *
59  * @{
60  */
61 
62 /// Infinite timeout in milliseconds.
63 /// @deprecated Need to be removed to use constants from CProcessBase and derived classes
64 const unsigned long kInfiniteTimeoutMs = kMax_ULong;
65 
66 // This workaround is obsolete now. LinuxThreads library has been replaced by NPTL
67 // which does not need it.
68 /*
69 /// Turn on/off workaround for Linux PID and PPID
70 #if defined(NCBI_OS_LINUX)
71 # define NCBI_THREAD_PID_WORKAROUND
72 #endif
73 */
74 
75 /// Process identifier (PID) and process handle.
76 #if defined(NCBI_OS_UNIX)
77  typedef pid_t TPid;
79 #elif defined(NCBI_OS_MSWIN)
80  typedef DWORD TPid;
81  typedef HANDLE TProcessHandle;
82 #else
83  typedef int TPid;
84  typedef TPid TProcessHandle;
85 #endif
86 
87 
88 
89 /////////////////////////////////////////////////////////////////////////////
90 ///
91 /// CProcessBase --
92 ///
93 /// Base class that defines common types and constants for CProcess and CCurrentProcess.
94 /// @sa CProcess, CCurrentProcess
95 
97 {
98 public:
99  /// Process information "target"
100  enum EWhat {
101  eProcess, ///< Current process
102  eChildren, ///< All children of the calling process
103  eThread ///< Current thread
104  };
105 
106  /// Process memory usage information, in bytes.
107  ///
108  /// Values sets to 0 if unknown,
109  /// @note
110  /// Resident set size represent physical memory usage,
111  /// all other members - virtual memory usage.
112  /// @note
113  /// Resident size alone is the wrong place to look to determine if your processes
114  /// are getting too big. If the system gets overloaded with processes that
115  /// using more and more (virtual) memory over time, that resident portion can even shrink.
116  struct SMemoryUsage {
117  size_t total; ///< Total memory usage
118  size_t total_peak; ///< Peak total memory usage
119  size_t resident; ///< Resident/working set size (RSS).
120  ///< RSS is the portion of memory occupied by a process
121  ///< that is held in main memory (RAM).
122  size_t resident_peak; ///< Peak resident set size ("high water mark")
123  size_t shared; ///< Shared memory usage
124  size_t data; ///< Data segment size
125  size_t stack; ///< Stack size of the initial thread in the process
126  size_t text; ///< Text (code) segment size
127  size_t lib; ///< Shared library code size
128  size_t swap; ///< Swap space usage
129  };
130 
131  /// Default wait time (milliseconds) between "soft" and "hard"
132  /// attempts to terminate a process.
133  static const unsigned long kDefaultKillTimeout;
134 
135  /// Infinite timeout (milliseconds).
136  static const unsigned long kInfiniteTimeoutMs;
137 };
138 
139 
140 /////////////////////////////////////////////////////////////////////////////
141 ///
142 /// CCurrentProcess --
143 ///
144 /// This class defines methods related to the current process.
145 /// For arbitrary process please see CProcess.
146 ///
147 /// Static methods only.
148 ///
149 /// @sa CProcess
150 
152 {
153 public:
154  /////////////////////////////////////////////////////////////////////////////
155  // Process information
156 
157  /// Get process handle for the current process (esp. on Windows).
158  /// @note
159  /// On Windows process identifiers and process handles are different.
160  /// On UNIX handle/pid are the same and GetHandle()/GetPid()
161  /// return the same value.
162  /// @sa
163  /// GetPid
164  static TProcessHandle GetHandle(void);
165 
166  /// Get process identifier (pid) for the current process.
167  /// @sa
168  /// GetHandle
169  static TPid GetPid(void);
170 
171  /// Get process identifier (pid) for the parent of the current process.
172  /// @sa
173  /// GetPid
174  static TPid GetParentPid(void);
175 
176  /// Get current process execution times.
177  ///
178  /// @param real
179  /// Pointer to a variable that receives the amount of time in second that
180  /// the current process/thread has executed, when available.
181  /// @note
182  /// Here is no portable solution to get 'real' process execution time,
183  /// not all OS have an API to get such information from the system,
184  /// or it can include children times as well...
185  /// but it is available on some platforms like Windows, Linux and BSD.
186  /// @param user
187  /// Pointer to a variable that receives the amount of time in seconds that
188  /// the process, process tree or thread has executed in user mode.
189  /// Note, that this value can exceed the amount of "real" time if
190  /// the process executes across multiple CPU cores (OS dependent).
191  /// @param sys
192  /// Pointer to a variable that receives the amount of time in second that
193  /// the current process, process tree or thread has executed in kernel mode.
194  /// @param what
195  /// Applies to user and system time parameters only,
196  /// real time calculates for the current process only.
197  /// Defines what times to measure: current thread, process or children processes:
198  /// - eProcess:
199  /// Current process, which is the sum of resources used
200  /// by all threads in the process.
201  /// - eChildren: (limited support)
202  /// All children of the calling process that have terminated already
203  /// and been waited for. These statistics will include the resources
204  /// used by grandchildren, and further removed descendants, if all of
205  /// the intervening descendants waited on their terminated children.
206  /// - eThread: (limited support)
207  /// Usage statistics for the calling thread.
208  /// @return
209  /// TRUE on success; or FALSE on error.
210  /// If some value cannot be calculated on a current platform for "what" target,
211  /// it will be set to a negative value.
212  /// @note
213  /// NULL arguments will not be filled in.
214  /// @sa
215  /// CProcess::GetTimes
216  static bool GetTimes(double* real, double* user, double* sys, EWhat what = eProcess);
217 
218  /// Get current process memory usage.
219  ///
220  /// @sa
221  /// CProcess::GetMemoryUsage, SMemoryUsage
222  static bool GetMemoryUsage(SMemoryUsage& usage);
223 
224  /// Get the number of threads in the current process.
225  ///
226  /// @return
227  /// Number of threads in the current process, or -1 on error.
228  /// @sa
229  /// CProcess::GetThreadCount
230  static int GetThreadCount(void);
231 
232  /// Get the number of file descriptors consumed by the current process,
233  /// and optional system wide file descriptor limits.
234  ///
235  /// @param soft_limit
236  /// Pointer to a variable that receives system wide soft limit.
237  /// -1 means it was impossible to get the limit.
238  /// @param hard_limit
239  /// Pointer to a variable that receives system wide hard limit.
240  /// -1 means it was impossible to get the limit.
241  /// @return
242  /// Number of file descriptors consumed by the process, or -1 on error.
243  /// @note
244  /// NULL arguments will not be filled in.
245  /// @sa
246  /// CProcess::GetFileDescriptorsCount
247  /// @note Unix inly
248  static int GetFileDescriptorsCount(int* soft_limit = NULL, int* hard_limit = NULL);
249 
250 
251  /////////////////////////////////////////////////////////////////////////////
252  // Forks & Daemons
253 
254  /// Forking flags.
255  enum FForkFlags {
256  fFF_UpdateDiag = 1, ///< Reset diagnostics timer and log an
257  ///< app-start message in the child process.
258  fFF_Exec = 2, ///< User plans to use exec(3) or execve(2) to "replace" forked child
259  ///< process with another program as soon as possible after fork,
260  ///< so we can skip some initialization and checks. Cancels fFF_UpdateDiag.
261  fFF_AllowExceptions = 32 ///< Throw an exception on error.
262  };
263  /// Bit-wise OR of FForkFlags @sa FForkFlags
264  typedef unsigned TForkFlags;
265 
266  /// Fork the process. Update PID and GUID used for logging (by default).
267  ///
268  /// @warning
269  /// The child process is created with a single thread, the one that called fork().
270  /// The entire virtual address space of the parent is replicated in the child,
271  /// including the states of mutexes, condition variables, open file descriptors,
272  /// pthreads objects, and etc. But child process doesn't inherit or reset many
273  /// other properties. Be aware. Consult fork(2) man-pages for a full details.
274  /// @warning
275  /// Fork() should be called from a single-threaded application, even if it built
276  /// in MT configurations. If you have many running threads in the parent process,
277  /// this can lead to unpredictable results and various deadlocks.
278  /// "After a fork() in a multithreaded program, the child can safely call only
279  /// async-signal-safe functions." until it calls execve(2) to replace a forked
280  /// child process as soon as possible after Fork().
281  /// See https://man7.org/linux/man-pages/man2/fork.2.html
282  /// @return
283  /// In the parent process, the call returns the child process ID.
284  /// In the child process, the call returns zero.
285  /// In case of an error, unless the fFF_AllowExceptions flag is specified,
286  /// the call returns -1.
287  /// @throw
288  /// If the fFF_AllowExceptions flag is specified, throws a CCoreException
289  /// in case of a fork(2) failure. If the platform does not support process
290  /// forking, an exception is always thrown regardless of whether
291  /// the fFF_AllowExceptions flag is specified.
292  /// @note
293  /// Implemented for Unix only.
294  /// @sa ForkForExec
295  ///
296  static TPid Fork(TForkFlags flags = fFF_UpdateDiag);
297 
298  /// Fork the process for "replacing" a child process with a new process.
299  ///
300  /// Special version of Fork() with a different name for easier recognizing.
301  /// Assumes that the user will replace child process after this call with using
302  /// exec(3) or execve(2) calls as soon as possible. The child can safely call
303  /// only async-signal-safe functions after Fork() until the child process
304  /// has replaced. This mean no memory allocation, streams, logging and etc.
305  /// Please consult the list of sync-signal-safe functions before using, like:
306  /// https://man7.org/linux/man-pages/man7/signal-safety.7.html
307  ///
308  /// @return
309  /// In the parent process, the call returns the child process ID.
310  /// In the child process, the call returns zero.
311  /// In case of an error, unless the fFF_AllowExceptions flag is specified,
312  /// the call returns -1.
313  /// @sa Fork
314  ///
315  static TPid ForkForExec(TForkFlags flags = 0) { return Fork(flags | fFF_Exec); };
316 
317  /// Daemonization flags
319  fDF_KeepCWD = 1, ///< Don't change CWD to "/"
320  fDF_KeepStdin = 2, ///< Keep stdin open as "/dev/null" (RO)
321  fDF_KeepStdout = 4, ///< Keep stdout open as "/dev/null" (WO)
322  fDF_ImmuneTTY = 8, ///< Make daemon immune to re-acquiring a controlling terminal
323  fDF_KeepParent = 16, ///< Do not exit the parent process but return
324  fDF_AllowExceptions = 32, ///< Throw an exception in case of an error.
325  fDF_AllowThreads = 64 ///< Do not fail if pre-existing threads are detected
326  };
327  /// Bit-wise OR of FDaemonFlags @sa FDaemonFlags
328  typedef unsigned int TDaemonFlags;
329 
330  /// Go daemon.
331  ///
332  /// Return TPid(-1) in the daemon thread (the parent thread doesn't return
333  /// unless fKeepParent is set), or TPid(daemon) in the parent thread.
334  /// On error return 0 in the parent thread (no daemon created), see errno.
335  ///
336  /// Reopen stderr/cerr in the daemon thread if "logfile" specified as
337  /// non-NULL (stderr will open to "/dev/null" if "logfile" has been passed
338  /// as ""), otherwise stderr is closed in the daemon thread.
339  ///
340  /// Unless instructed by the "flags" parameter, the daemon thread has its
341  /// stdin/cin and stdout/cout closed, and the current working directory
342  /// changed to the root directory ("/").
343  ///
344  /// If kept open, stdin and stdout are both redirected to "/dev/null".
345  /// Opening a terminal device as a controlling terminal is allowed, unless
346  /// fImmuneTTY is specified in the flags, which then causes a second
347  /// fork() so that the resultant process won't be allowed to open a TTY as
348  /// its controlling TTY (but only with an explicit O_NOCTTY, see open(2)),
349  /// thus protecting the process from any blocking via TTY signaling.
350  ///
351  /// Note that this call is somewhat destructive and may not be able
352  /// to restore the process that called it to a state prior to the call
353  /// in case of an error. So that calling process can find the standard
354  // file pointers (and sometimes descriptors) clobbered up.
355  ///
356  static TPid Daemonize(const char* logfile = 0, TDaemonFlags flags = 0);
357 
358 private:
359 #if defined NCBI_THREAD_PID_WORKAROUND
360  // Flags for internal sx_GetPid()
361  enum EGetPidFlag {
362  // get real or cached PID depending on thread ID
363  ePID_GetCurrent,
364  // get parent PID - real or cached depending on thread ID
365  ePID_GetParent,
366  // get real PID (of the thread) but do not cache it
367  ePID_GetThread
368  };
369  static TPid sx_GetPid(EGetPidFlag flag);
370  friend class CThread;
371 #endif
372 };
373 
374 
375 
376 /////////////////////////////////////////////////////////////////////////////
377 ///
378 /// CProcess --
379 ///
380 /// Process management functions.
381 ///
382 /// Class works with process identifiers and process handles.
383 /// On Unix both terms are equivalent and correspond a pid.
384 /// On MS Windows they are different.
385 ///
386 /// @note: All CExec:: functions work with process handles.
387 
389 {
390 public:
391  /// How to interpret the used process identifier.
392  enum EType {
393  ePid, ///< A real process identifier (pid).
394  eHandle ///< A process handle (MS Windows).
395  };
396 
397  /// Default constructor. Uses the current process pid.
398  CProcess(void);
399 
400  /// Constructor.
401  CProcess(TPid process, EType type = eHandle);
402 #if defined(NCBI_OS_MSWIN)
403  // Note:
404  // On MS Windows process identifiers and process handles are different.
405  // so we need a separate constructor for process handles.
406  CProcess(TProcessHandle process, EType type = eHandle);
407 #endif
408 
409  /// Get type of stored process identifier.
410  /// @note
411  /// On Windows process identifiers and process handles are different.
412  /// On UNIX handle/pid is the same, and GetHandle()/GetPid() return
413  /// the same value.
414  EType GetType(void) const { return m_Type; }
415 
416  /// Get stored process handle.
417  /// @sa
418  /// GetCurrentHandle
419  TProcessHandle GetHandle(void) const { return (TProcessHandle)m_Process; }
420 
421  /// Get stored process identifier (pid).
422  /// @sa
423  /// GetCurrentPid
424  TPid GetPid(void) const { return (TPid) m_Process; }
425 
426  /// Checks that stored process identifier (pid) represent the current process.
427  /// @sa
428  /// GetCurrentPid
429  bool IsCurrent(void);
430 
431  /// Check for process existence.
432  ///
433  /// @return
434  /// TRUE - if the process is still running.
435  /// FALSE - if the process does exist or has already been terminated.
436  /// @note
437  /// On Unix this method returns TRUE also for "zombie" processes,
438  /// those finished executing but waiting to post their exit code.
439  /// Usually the parent process should call Wait() for such processes
440  /// and release (aka reap) them.
441  /// @sa
442  /// Wait
443  bool IsAlive(void) const;
444 
445  /// Terminate process.
446  ///
447  /// First try "soft" and then try "hard" attempt to terminate the process.
448  /// @note Even the "hard" attempt does not guarantee that the process will
449  /// be actually killed. Process termination can take some time, and the
450  /// process may remain "alive" even after the "hard" termination attempt.
451  ///
452  /// @param timeout
453  /// Wait time in milliseconds between first "soft" and second "hard"
454  /// attempts to terminate the process.
455  /// If timeout is zero then use an unsafe process termination: just
456  /// try to terminate the process without checks that it is really gone.
457  /// @note
458  /// On UNIX in case of a zero or very small timeout, the killed process
459  /// may not be released immediately (and continue to persist as a zombie
460  /// process) even after this call.
461  /// @return
462  /// TRUE - if the process did not exist or was successfully terminated.
463  /// FALSE - if the process is still running, cannot be terminated, or
464  /// it is terminating right now (but is still incomplete).
465  /// @sa KillGroup, KillGroupById
466  bool Kill(unsigned long timeout = kDefaultKillTimeout);
467 
468  /// Terminate a group of processes.
469  ///
470  /// This method tries to terminate all processes in the group to which
471  /// process, specified in the constructor, belongs.
472  ///
473  /// @param timeout
474  /// Wait time in milliseconds between first "soft" and second "hard"
475  /// attempts to terminate the process group.
476  /// If timeout is zero then use an unsafe process termination: just
477  /// try to terminate the group without checks that it is really gone.
478  /// @note
479  /// On UNIX in case of a zero or very small timeout, some processes
480  /// may not be released (and continue to persist as zombie processes)
481  /// even after this call.
482  /// On MS Windows this method tries to terminate the process itself
483  /// and all of its children. But in case when one of the processes,
484  /// which should be terminated, spawns a new process at the very moment
485  /// that this method gets called, the new process may not be terminated.
486  /// @return
487  /// TRUE - if the process group did not exist or was successfully
488  /// terminated.
489  /// FALSE - if the process group is still running, cannot be terminated,
490  /// or it is terminating right now (but is still incomplete).
491  /// @sa Kill
492  bool KillGroup(unsigned long timeout = kDefaultKillTimeout) const;
493 
494  /// Terminate a group of processes with specified ID.
495  ///
496  /// Note: Implemented on UNIX only, on Windows returns FALSE.
497  /// @param pgid
498  /// Process group ID to terminate.
499  /// if "pgid" parameter is zero, terminate the process group of
500  /// the current process
501  /// @param timeout
502  /// Wait time in milliseconds between first "soft" and second "hard"
503  /// attempts to terminate the process group.
504  /// If timeout is zero then use an unsafe process termination: just
505  /// try to terminate the process group without checks whether it is
506  /// really gone.
507  /// @note
508  /// On UNIX in case of a zero or very small timeout, some processes from
509  /// the process group to be killed may not be released immediately
510  /// (and continue to persist as zombie processes) even after this call.
511  /// @return
512  /// TRUE - if the process group did not exist or was successfully
513  /// terminated.
514  /// FALSE - if the process group is still running, cannot be terminated,
515  /// or it is terminating right now (but is still incomplete).
516  /// @sa Kill
517  static bool KillGroupById(TPid pgid, unsigned long timeout = kDefaultKillTimeout);
518 
519  /// Extended exit information for waited process.
520  /// All information about the process available only after Wait() method
521  /// with specified parameter 'info' and if IsPresent() method returns TRUE.
523  {
524  public:
525  /// Constructor.
526  CExitInfo(void);
527 
528  /// TRUE if the object contains information about the process state.
529  ///
530  /// All other methods' return values are good only if this method
531  /// returns TRUE, otherwise they may throw exceptions.
532  bool IsPresent(void) const;
533 
534  /// TRUE if the process is still alive.
535  bool IsAlive(void) const;
536 
537  /// TRUE if the process terminated normally.
538  bool IsExited(void) const;
539 
540  /// TRUE if the process terminated by a signal (UNIX only).
541  bool IsSignaled(void) const;
542 
543  /// Get process exit code.
544  /// Works only if IsExited() returns TRUE, otherwise returns -1.
545  int GetExitCode(void) const;
546 
547  /// Get the signal number that has caused the process to terminate
548  /// (UNIX only).
549  /// Works only if IsSignaled() returns TRUE, otherwise returns -1.
550  int GetSignal(void) const;
551 
552  private:
553  int state; ///< Process state (unknown/alive/terminated).
554  int status; ///< Process status information.
555 
556  friend class CProcess;
557  };
558 
559  /// Wait until process terminates.
560  ///
561  /// Wait until the process terminates or timeout expires.
562  /// Return immediately if the specified process has already terminated.
563  /// @param timeout
564  /// Time interval in milliseconds (infinite by default) to wait.
565  /// @param info
566  /// Extended exit information for terminated process.
567  /// Note that if CProcess::Kill() was used to terminate the process
568  /// then the extended information may not be available.
569  /// @return
570  /// - Exit code of the process, if the call completed without errors.
571  /// - (-1) if an error occurred or it was impossible to get the exit
572  /// code of the process. If 'info' parameter is specified, then it
573  /// is filled with additional information about the process.
574  /// @note
575  /// It is recommended to call this method for all processes started
576  /// in eNoWait or eDetach modes (except on Windows for eDetach), because
577  /// it releases "zombie" processes, i.e. those finished running and
578  /// waiting for their parent to obtain their exit code. If Wait() is
579  /// not called somewhere, then the child process will be completely
580  /// removed from the system only when its parent process ends.
581  /// @note
582  /// Infinite timeout can cause an application to stop responding.
583  /// @sa
584  /// IsAlive, CExitInfo, CExec, WaitInfinite, WaitTimeout
585  int Wait(unsigned long timeout = kInfiniteTimeoutMs, CExitInfo* info = 0) const;
586 
587  /// Wait until the process terminates or timeout expires.
588  /// @sa Wait
589  int WaitTimeout(unsigned long timeout, CExitInfo* info = 0) const {
590  return Wait(timeout, info);
591  }
592 
593  /// Wait indefinitely until the process terminates.
594  /// @sa Wait
595  int WaitInfinite(CExitInfo* info = 0) const {
596  return Wait(kInfiniteTimeoutMs, info);
597  }
598 
599 
600  /////////////////////////////////////////////////////////////////////////////
601  // Process information
602 
603  /// @deprecated Please use CCurrentProcess::GetHandle() instead
607  }
608 
609  /// @deprecated Please use CCurrentProcess::GetPid() instead
611  static TPid GetCurrentPid(void) {
612  return CCurrentProcess::GetPid();
613  }
614 
615  /// @deprecated Please use CCurrentProcess::GetParentPid() instead
617  static TPid GetParentPid(void) {
619  }
620 
621  /// Get process execution times.
622  /// For current process pid/handle it is the same as CCurrentProcess::GetTimes().
623  ///
624  /// @param real
625  /// Pointer to a variable that receives the amount of time in second that
626  /// the process/thread has executed, when available.
627  /// @note
628  /// Here is no portable solution to get 'real' process execution time,
629  /// not all OS have an API to get such information from the system,
630  /// or it can include children times as well...
631  /// but it is available on some platforms like Windows, Linux and BSD.
632  /// @param user
633  /// Pointer to a variable that receives the amount of time in seconds that
634  /// the process, process tree or thread has executed in user mode.
635  /// Note, that this value can exceed the amount of "real" time if
636  /// the process executes across multiple CPU cores (OS dependent).
637  /// @param sys
638  /// Pointer to a variable that receives the amount of time in second that
639  /// the current process, process tree or thread has executed in kernel mode.
640  /// @param what
641  /// Defines what times to measure: current thread, process or children processes:
642  /// - eProcess:
643  /// Current process, which is the sum of resources used
644  /// by all threads in the process.
645  /// - eChildren: (limited support)
646  /// All children of the process that have terminated already
647  /// and been waited for. These statistics will include the resources
648  /// used by grandchildren, and further removed descendants, if all of
649  /// the intervening descendants waited on their terminated children.
650  /// - eThread: (limited support)
651  /// Usage statistics for the calling thread.
652  /// CProcess should be initialized with the current process pid/handle,
653  /// or result is undefined.
654  /// @return
655  /// TRUE on success; or FALSE on error.
656  /// If some value cannot be calculated on a current platform for "what" target,
657  /// it will be set to a negative value.
658  /// @note
659  /// NULL arguments will not be filled in.
660  /// @note
661  /// Usually it is possible to query information from users own processes,
662  /// but you should have an appropriate permissions to query other processes.
663  /// @note
664  /// On Windows it is possible to get process times even for terminated processes,
665  /// that are Wait()-ed for, even if IsAlive() returns false.
666  /// @sa
667  /// CCurrentProcess::GetTimes
668  bool GetTimes(double* real, double* user, double* sys, EWhat what = eProcess);
669 
670  /// Get process memory usage.
671  /// For current process pid/handle it is the same as CCurrentProcess::GetMemoryUsage().
672  ///
673  /// @param usage
674  /// Total memory usage by a process, in bytes. See SMemoryUsage structure.
675  /// @param resident
676  /// Resident set size (RSS), in bytes.
677  /// RSS is the portion of memory occupied by a process that is held in main memory (RAM).
678  /// @param shared
679  /// (optional) Shared memory usage, in bytes.
680  /// @param data
681  /// (optional) Data + stack usage, in bytes.
682  /// @return
683  /// TRUE on success; or FALSE otherwise.
684  /// @note
685  /// NULL arguments will not be filled in.
686  /// @sa
687  /// CCurrentProcess::GetMemoryUsage, SMemoryUsage
688  bool GetMemoryUsage(SMemoryUsage& usage);
689 
690  /// Get the number of threads in the process.
691  /// For current process pid/handle it is the same as CCurrentProcess::GetThreadCount().
692  ///
693  /// @return
694  /// Number of threads in the current process, or -1 on error.
695  /// @sa
696  /// CCurrentProcess::GetThreadCount
697  int GetThreadCount(void);
698 
699  /// Get the number of file descriptors consumed by the current process.
700  /// For current process pid/handle it is the same as CCurrentProcess::GetFileDescriptorsCount().
701  ///
702  /// @return
703  /// Number of file descriptors consumed by the process, or -1 on error.
704  /// @sa
705  /// CCurrentProcess::GetFileDescriptorsCount
706  /// @note Unix inly
707  int GetFileDescriptorsCount(void);
708 
709 
710  /////////////////////////////////////////////////////////////////////////////
711  // Forks & Daemons
712 
713  /// Forking flags.
714  /// @ deprecated Please use CCurrentProcess::FForkFlags instead
715  enum FForkFlags {
718  };
719  /// Bit-wise OR of FForkFlags @sa FForkFlags
720  /// @ deprecated Please use CCurrentProcess::TForkFlags instead
721  typedef unsigned TForkFlags;
722 
723  /// Fork the process.
724  /// @deprecated Please use CCurrentProcess::Fork() instead
728  }
729 
730  /// Daemonization flags
731  /// @ deprecated Please use CCurrentProcess::FDaemonFlags instead
740 
746  };
747  /// Bit-wise OR of FDaemonFlags @sa FDaemonFlags
748  /// @ deprecated Please use CCurrentProcess::TDaemonFlags instead
749  typedef unsigned int TDaemonFlags;
750 
751  /// Go daemon.
752  ///
753  /// Return TPid(-1) in the daemon thread (the parent thread doesn't return
754  /// unless fKeepParent is set), or TPid(daemon) in the parent thread.
755  /// On error return 0 in the parent thread (no daemon created), see errno.
756  ///
757  /// Reopen stderr/cerr in the daemon thread if "logfile" specified as
758  /// non-NULL (stderr will open to "/dev/null" if "logfile" has been passed
759  /// as ""), otherwise stderr is closed in the daemon thread.
760  ///
761  /// Unless instructed by the "flags" parameter, the daemon thread has its
762  /// stdin/cin and stdout/cout closed, and the current working directory
763  /// changed to the root directory ("/").
764  ///
765  /// If kept open, stdin and stdout are both redirected to "/dev/null".
766  /// Opening a terminal device as a controlling terminal is allowed, unless
767  /// fImmuneTTY is specified in the flags, which then causes a second
768  /// fork() so that the resultant process won't be allowed to open a TTY as
769  /// its controlling TTY (but only with an explicit O_NOCTTY, see open(2)),
770  /// thus protecting the process from any blocking via TTY signaling.
771  ///
772  /// Note that this call is somewhat destructive and may not be able
773  /// to restore the process that called it to a state prior to the call
774  /// in case of an error. So that calling process can find the standard
775  // file pointers (and sometimes descriptors) clobbered up.
776  /// @deprecated Please use CCurrentProcess::Daemonize() instead
778  static TPid Daemonize(const char* logfile = 0, TDaemonFlags flags = 0) {
779  return CCurrentProcess::Daemonize(logfile, flags);
780  };
781 
782 private:
783 #if defined(NCBI_OS_MSWIN)
784  // Return pid, converts from handle if necessary
785  TPid x_GetPid(void) const;
786 
787  // Return process handle, converts from pid with desired rights if necessary.
788  // Return NULL on error. Don't forget to close handle with x_CloseHandle().
789  TProcessHandle x_GetHandle(DWORD desired_access, DWORD* errcode = 0 /*optional errcode to return*/) const;
790 
791  // Close handle, if necessary
792  void x_CloseHandle(TProcessHandle handle) const;
793 #endif
794 
795  // itptr_t type can store both pid and process handle.
796  intptr_t m_Process; ///< Process identifier.
797  EType m_Type; ///< Type of process identifier.
798  ETriState m_IsCurrent; ///< Status that m_Process represent the current process.
799 };
800 
801 
802 
803 /////////////////////////////////////////////////////////////////////////////
804 ///
805 /// CPIDGuardException --
806 ///
807 
809 {
810 public:
811  enum EErrCode {
812  eStillRunning, ///< The process listed in the file is still around.
813  eWrite ///< Unable to write into the PID file.
814  };
815 
816  virtual const char* GetErrCodeString(void) const override;
817 
818  /// Constructor.
820  const CException* prev_exception, EErrCode err_code,
821  const string& message, TPid pid = 0,
822  EDiagSev severity = eDiag_Error)
823  : CException(info, prev_exception, message, severity),
824  m_PID(pid)
826 
827 public:
828  virtual void ReportExtra(ostream& out) const override
829  {
830  out << "pid " << m_PID;
831  }
832 
833  TPid GetPID(void) const throw() { return m_PID; }
834 
835 protected:
836  virtual void x_Assign(const CException& src) override
837  {
839  m_PID = dynamic_cast<const CPIDGuardException&>(src).m_PID;
840  }
841 
842 private:
844 };
845 
846 
847 /////////////////////////////////////////////////////////////////////////////
848 ///
849 /// CPIDGuard -- Process guard.
850 ///
851 /// If file already exists, CPIDGuard try to check that the process with PID
852 /// specified in the file is running or not. If guarded process is still
853 /// running, CPIDGuard throw an exception. Otherwise, it create file with
854 /// current PID. CPIDGuard use reference counters in the PID file.
855 /// This means that some CPIDGuard objects can be created for the same PID
856 /// and file name.
857 ///
858 /// @note
859 /// If you need something just to prevent run some application twice,
860 /// please look to CInterProcessLock class.
861 /// @note
862 /// CPIDGuard know nothing about PID file modification or deletion
863 /// by other processes directly, without using this API. Be aware.
864 ///
865 
867 {
868 public:
869  /// Create/check PID file.
870  ///
871  /// If the file already exists and identifies a live process,
872  /// throws CPIDGuardException.
873  /// @param filename
874  /// Name of the file to store PID.
875  /// If "filename" contains path, it should be absolute
876  /// and points to an existing directory.
877  /// If "filename" contains no path, that $TMPDIR will be used on Unix,
878  /// and %HOME% on Windows to store it.
879  CPIDGuard(const string& filename);
880 
881  /// Create/check PID file.
882  ///
883  /// If the file already exists and identifies a live process,
884  /// throws CPIDGuardException.
885  ///
886  /// @param filename
887  /// Name of the file to store PID.
888  /// If should not include any path, relative or absolute.
889  /// @param dir
890  /// An absolute path to the existing directory on the file system
891  /// to store PID file "filename".
892  /// If "dir" is empty and "filename" contains no path,
893  /// that $TMPDIR will be used on Unix, and %HOME% on Windows to store it.
894  /// @deprecated
896  CPIDGuard(const string& filename, const string& dir);
897 
898  /// Destructor.
899  ///
900  /// Just calls Release();
901  ~CPIDGuard(void);
902 
903  /// Release PID.
904  ///
905  /// Decrease reference counter for current PID and remove the file
906  /// if it is not used more (reference counter is 0).
907  void Release(void);
908 
909  /// Remove the file.
910  ///
911  /// Remove PID file forcibly, ignoring any reference counter.
912  void Remove(void);
913 
914  /// Update PID in the file.
915  ///
916  /// @param pid
917  /// The new process ID to store (defaults to the current PID);
918  /// useful when the real work occurs in a child process that outlives
919  /// the parent.
920  void UpdatePID(TPid pid = 0);
921 
922  /// Returns non-zero if there was a stale file.
923  /// Always return 0, because new implementation don't allow
924  /// any stale file left on the file system.
925  ///
926  /// @deprecated
928  TPid GetOldPID(void) { return 0; }
929 
930 private:
931  string m_Path; //< File path to store PID.
932  TPid m_PID; //< Sored PID.
933  unique_ptr<CInterProcessLock> m_MTGuard; //< MT-Safe protection guard.
934  unique_ptr<CInterProcessLock> m_PIDGuard; //< Guard to help with "PID reuse" problem.
935 };
936 
937 
938 /* @} */
939 
941 
942 
943 #endif /* CORELIB___NCBI_PROCESS__HPP */
const char * usage
CCurrentProcess –.
Incapsulate compile time information such as __FILE__, __LINE__, NCBI_MODULE, current function.
Definition: ncbidiag.hpp:65
CPIDGuardException –.
CPIDGuard – Process guard.
CProcessBase –.
Extended exit information for waited process.
CProcess –.
CProcess(TProcessHandle process, EType type=eHandle)
static uch flags
std::ofstream out("events_result.xml")
main entry point for tests
ETriState
Enumeration to represent a tristate value.
Definition: ncbimisc.hpp:128
#define NULL
Definition: ncbistd.hpp:225
EDiagSev
Severity level for the posted diagnostics.
Definition: ncbidiag.hpp:650
@ eDiag_Error
Error message.
Definition: ncbidiag.hpp:653
virtual void x_Assign(const CException &src)
Helper method for copying exception data.
Definition: ncbiexpt.cpp:536
#define NCBI_EXCEPTION_DEFAULT_IMPLEMENTATION(exception_class, base_class)
Helper macro for default exception implementation.
Definition: ncbiexpt.hpp:1300
#define EXCEPTION_VIRTUAL_BASE
Do not use virtual base classes in exception declaration at all, because in this case derived class s...
Definition: ncbiexpt.hpp:1388
int intptr_t
Definition: ncbitype.h:185
#define NCBI_DEPRECATED
FForkFlags
Forking flags.
bool GetTimes(double *real, double *user, double *sys, EWhat what=eProcess)
Get process execution times.
size_t resident_peak
Peak resident set size ("high water mark")
size_t total_peak
Peak total memory usage.
int WaitTimeout(unsigned long timeout, CExitInfo *info=0) const
Wait until the process terminates or timeout expires.
TPid x_GetPid(void) const
unsigned int TDaemonFlags
Bit-wise OR of FDaemonFlags.
const unsigned long kInfiniteTimeoutMs
Infinite timeout in milliseconds.
TProcessHandle x_GetHandle(DWORD desired_access, DWORD *errcode=0) const
static TPid GetParentPid(void)
Get process identifier (pid) for the parent of the current process.
EType
How to interpret the used process identifier.
size_t resident
Resident/working set size (RSS).
static TPid Daemonize(const char *logfile=0, TDaemonFlags flags=0)
Go daemon.
TProcessHandle GetHandle(void) const
Get stored process handle.
TPid GetPID(void) const
static TPid GetPid(void)
Get process identifier (pid) for the current process.
int status
Process status information.
unsigned int TDaemonFlags
Bit-wise OR of FDaemonFlags.
static TPid ForkForExec(TForkFlags flags=0)
Fork the process for "replacing" a child process with a new process.
static TProcessHandle GetCurrentHandle(void)
TPid TProcessHandle
EType m_Type
Type of process identifier.
EWhat
Process information "target".
size_t total
Total memory usage.
unique_ptr< CInterProcessLock > m_MTGuard
size_t shared
Shared memory usage.
size_t text
Text (code) segment size.
string m_Path
virtual void ReportExtra(ostream &out) const override
Constructor.
FForkFlags
Forking flags.
FDaemonFlags
Daemonization flags.
int state
Process state (unknown/alive/terminated).
ETriState m_IsCurrent
Status that m_Process represent the current process.
static TPid Daemonize(const char *logfile=0, TDaemonFlags flags=0)
Go daemon.
static TPid Fork(TForkFlags flags=fFF_UpdateDiag)
Fork the process.
FDaemonFlags
Daemonization flags @ deprecated Please use CCurrentProcess::FDaemonFlags instead.
int WaitInfinite(CExitInfo *info=0) const
Wait indefinitely until the process terminates.
TPid GetOldPID(void)
Returns non-zero if there was a stale file.
unique_ptr< CInterProcessLock > m_PIDGuard
size_t swap
Swap space usage.
static const unsigned long kInfiniteTimeoutMs
Infinite timeout (milliseconds).
intptr_t m_Process
Process identifier.
int Wait(unsigned long timeout=kInfiniteTimeoutMs, CExitInfo *info=0) const
Wait until process terminates.
void x_CloseHandle(TProcessHandle handle) const
int GetThreadCount(void)
Get the number of threads in the process.
static const unsigned long kDefaultKillTimeout
Default wait time (milliseconds) between "soft" and "hard" attempts to terminate a process.
unsigned TForkFlags
Bit-wise OR of FForkFlags.
pid_t TPid
Process identifier (PID) and process handle.
size_t lib
Shared library code size.
unsigned TForkFlags
Bit-wise OR of FForkFlags.
virtual void x_Assign(const CException &src) override
static TPid GetCurrentPid(void)
size_t data
Data segment size.
TPid GetPid(void) const
Get stored process identifier (pid).
static TProcessHandle GetHandle(void)
Get process handle for the current process (esp.
int GetFileDescriptorsCount(void)
Get the number of file descriptors consumed by the current process.
static TPid Fork(TForkFlags flags=fFF_UpdateDiag)
Fork the process.
EType GetType(void) const
Get type of stored process identifier.
size_t stack
Stack size of the initial thread in the process.
static TPid GetParentPid(void)
@ fFF_AllowExceptions
@ ePid
A real process identifier (pid).
@ eStillRunning
The process listed in the file is still around.
@ eChildren
All children of the calling process.
@ eProcess
Current process.
@ fFF_UpdateDiag
Reset diagnostics timer and log an app-start message in the child process.
@ fFF_AllowExceptions
Throw an exception on error.
@ fDF_KeepCWD
Don't change CWD to "/".
@ fDF_KeepParent
Do not exit the parent process but return.
@ fDF_KeepStdout
Keep stdout open as "/dev/null" (WO)
@ fDF_AllowExceptions
Throw an exception in case of an error.
@ fDF_KeepStdin
Keep stdin open as "/dev/null" (RO)
@ fDF_AllowThreads
Do not fail if pre-existing threads are detected.
@ fDF_ImmuneTTY
Make daemon immune to re-acquiring a controlling terminal.
@ fDF_AllowExceptions
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define NCBI_XNCBI_EXPORT
Definition: ncbi_export.h:1283
#define HANDLE
An abstraction for a file handle.
Definition: mdb.c:383
Simple inter-process lock.
static MDB_envinfo info
Definition: mdb_load.c:37
Defines MS Windows specifics for our "C++" code.
bool Daemonize(const char *logfile=0, TDaemonFlags flags=0)
bool GetMemoryUsage(size_t *total, size_t *resident, size_t *shared)
unsigned int DWORD
Definition: sqltypes.h:98
Process memory usage information, in bytes.
Definition: type.c:6
Modified on Sat Dec 09 04:48:19 2023 by modify_doxy.py rev. 669887